2012-07-11 51 views
45

在我的Galaxy Tab 10.1上的日历应用程序中,创建新事件时,会在标题栏/动作栏区域中显示完成和取消按钮。对话框片段中的ActionBar

enter image description here

我想在我的应用程序来实现这一点。我试过在DialogFragment子类中使用setHasOptionsMenu(true)以及覆盖onCreateOptionsMenu,但我的操作项不会显示。我也尝试从onCreateView内呼叫getDialog().getActionBar(),但它总是返回null

我能够得到这个工作,如果我开始Activity而不是显示一个对话框,但占用了整个屏幕。有没有使用DialogFragment这样做的标准方法?

+5

这可能是一个看似对话而不是“真实对话”的活动。 – Veeti

回答

83

使用来自google group post的想法我能够将它从样式化活动中拉出来。您最好将高度和宽度修改为您选择的“动态”尺寸。然后设置任何动作条按钮,你想

<style name="PopupTheme" parent="android:Theme.Holo.Light.Dialog"> 
    <item name="android:windowIsFloating">false</item> 
    <item name="android:windowContentOverlay">@null</item> 
    <item name="android:windowSoftInputMode">stateAlwaysHidden</item> 
    <item name="android:windowActionModeOverlay">true</item> 
    <item name="android:windowIsTranslucent">true</item> 
</style> 

- 与此玩耍的时间

public static void showAsPopup(Activity activity) { 
    //To show activity as dialog and dim the background, you need to declare android:theme="@style/PopupTheme" on for the chosen activity on the manifest 
    activity.requestWindowFeature(Window.FEATURE_ACTION_BAR); 
    activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND, 
      WindowManager.LayoutParams.FLAG_DIM_BEHIND); 
    LayoutParams params = activity.getWindow().getAttributes(); 
    params.height = 850; //fixed height 
    params.width = 850; //fixed width 
    params.alpha = 1.0f; 
    params.dimAmount = 0.5f; 
    activity.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params); 
    setContentView(R.layout.activity_main); 
} 
+0

您节省了我的一天! – softwaresupply

+3

您刚刚通过LOT丰富了我的应用程序! –

+0

似乎对话框的操作栏没有获得自定义样式。它获得默认样式。任何想法如何使操作栏有定制的风格? –

1

就像Veeti暗示的那样,您可能想尝试使用对话主题实现活动。在Android清单中:

<activity android:name=".YourActivity" android:theme="@android:style/Theme.Dialog </activity> 

希望这会有所帮助。

1

我可能不是在有经验的,但我会用一个活动,添加操作栏项目,然后:

<activity android:name=".YourActivity" android:theme="@android:style/Theme.Holo.Light.Dialog" />

希望帮助!

+3

这样可以成功地显示看起来像对话框的活动,但仍然没有可见的操作栏。我也尝试过一个自定义主题,它继承自Theme.Holo.Light.Dialog,并将android:windowActionBar属性设置为true。一旦我这样做,我会得到一个异常'java.lang.IllegalStateException:ActionBarImpl只能与兼容的窗口装饰布局一起使用。 –

4

我花了一个令人难以置信的金额。接受答案的工作原理上的Galaxy Nexus 7(安卓4.2),但未能在三星Galaxy SIII(安卓4.1)和三星Galaxy Tab 10.2(安卓4.0),但下列情况除外:

IllegalStateException: ActionBarView can only be used with android:layout_width="match_parent" (or fill_parent) 

这是由ActionBarView.onMeasure(int, int)中的代码引起,该代码检查以确保布局设置为match_parent。正确的解决方案是通过setLayout来设置窗口的宽度,而不是使用setAttributes。

这是我下测试showAsPopup(),它在所有设备上工作的一个固定的版本:

private void showAsPopup(Activity activity) { 
    //To show activity as dialog and dim the background, you need to declare android:theme="@style/PopupTheme" on for the chosen activity on the manifest 
    activity.requestWindowFeature(Window.FEATURE_ACTION_BAR); 
    activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND, 
      WindowManager.LayoutParams.FLAG_DIM_BEHIND); 
    LayoutParams params = activity.getWindow().getAttributes(); 
    params.alpha = 1.0f; 
    params.dimAmount = 0f; 
    activity.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params); 

    // This sets the window size, while working around the IllegalStateException thrown by ActionBarView 
    activity.getWindow().setLayout(850,850); 
} 

为了完整起见,这里是PopupTheme再次:

<style name="PopupTheme" parent="android:Theme.Holo.Light.Dialog"> 
    <item name="android:windowIsFloating">false</item> 
    <item name="android:windowContentOverlay">@null</item> 
    <item name="android:windowSoftInputMode">stateAlwaysHidden</item> 
    <item name="android:windowActionModeOverlay">true</item> 
    <item name="android:windowIsTranslucent">true</item> 
</style> 
14

如果你是使用ActionBarSherlock,声明主题如下:

<style name="PopupTheme" parent="Theme.Sherlock"> 
    <item name="android:windowFrame">@null</item> 
    <item name="android:windowIsFloating">false</item> 
    <item name="android:windowContentOverlay">@null</item> 
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> 
    <item name="android:windowSoftInputMode">stateAlwaysHidden</item> 
    <item name="android:windowActionModeOverlay">true</item> 
    <item name="android:colorBackgroundCacheHint">@null</item> 
    <item name="android:windowCloseOnTouchOutside">true</item> 
    <item name="android:windowIsTranslucent">true</item> 
    <item name="windowContentOverlay">@null</item> 
</style> 

并初始化一个SherlockActivity根据Luke Sleeman's answer与PopupTheme。

private void showAsPopup(SherlockActivity activity) { 
    //To show activity as dialog and dim the background, you need to declare android:theme="@style/PopupTheme" on for the chosen activity on the manifest 
    //activity.requestWindowFeature(Window.FEATURE_ACTION_BAR); // NO NEED to call this line. 
    activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND, 
      WindowManager.LayoutParams.FLAG_DIM_BEHIND); 
    LayoutParams params = activity.getWindow().getAttributes(); 
    params.alpha = 1.0f; 
    params.dimAmount = 0.5f; 
    activity.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params); 

    // This sets the window size, while working around the IllegalStateException thrown by ActionBarView 
    activity.getWindow().setLayout(width,height); 
} 

结果:

enter image description here

11

遇到了一些麻烦实施从StrikeForceZero和卢克斯利曼建议的解决方案,所以我想贡献我的经验。我敢肯定,这只是我缺少的东西,所以反馈将非常感激。

我所做的是以下几点:

  1. 使用提供PopupTheme创建一个样式,直复制/粘贴:

    <style name="PopupTheme" parent="android:Theme.Holo.Light.Dialog"> 
        <item name="android:windowIsFloating">false</item> 
        <item name="android:windowContentOverlay">@null</item> 
        <item name="android:windowSoftInputMode">stateAlwaysHidden</item> 
        <item name="android:windowActionModeOverlay">true</item> 
        <item name="android:windowIsTranslucent">true</item> 
    </style> 
    
  2. 添加showAsPopup()方法中的方法片段将打开假对话片段,直接复制/粘贴:

    private void showAsPopup(Activity activity) { 
        //To show activity as dialog and dim the background, you need to declare android:theme="@style/PopupTheme" on for the chosen activity on the manifest 
        activity.requestWindowFeature(Window.FEATURE_ACTION_BAR); 
        activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND, 
         WindowManager.LayoutParams.FLAG_DIM_BEHIND); 
        LayoutParams params = activity.getWindow().getAttributes(); 
        params.alpha = 1.0f; 
        params.dimAmount = 0f; 
        activity.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params); 
    
        // This sets the window size, while working around the IllegalStateException thrown by ActionBarView 
        activity.getWindow().setLayout(850,850); 
    } 
    
  3. 创建使用简单的new()调用一个新的活动的实例,然后将它传递给showAsPopup()方法:

    DialogTestActivity test = new DialogTestActivity(); 
    showAsPopup(test); 
    
  4. 对于测试的目的(我只是想确认我)我使用了一个非常简单的测试,直接从按钮视图api demo中获取(对于布局文件,请参阅api演示中的buttons_1.xml):

    public class DialogTestActivity extends Activity { 
    
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.buttons_test); 
        } 
    } 
    

不幸的是,每次我尝试这个时,我都会得到一个不确定的在第一次调用时编辑空指针异常,activity.requestWindowFeature(Window.FEATURE_ACTION_BAR);

04-29 16:39:05.361: W/System.err(15134): java.lang.NullPointerException 
04-29 16:39:05.361: W/System.err(15134): at android.app.Activity.requestWindowFeature(Activity.java:3244) 
04-29 16:39:05.371: W/System.err(15134): at packagenameremovedforlegalreasons.classname.showAsPopup(classname.java:602) 
04-29 16:39:05.371: W/System.err(15134): at packagenameremovedforlegalreasons.classname.onMapLongClick(classname.java:595) 
04-29 16:39:05.371: W/System.err(15134): at com.google.android.gms.maps.GoogleMap$5.onMapLongClick(Unknown Source) 
04-29 16:39:05.371: W/System.err(15134): at com.google.android.gms.internal.k$a.onTransact(Unknown Source) 
04-29 16:39:05.381: W/System.err(15134): at android.os.Binder.transact(Binder.java:310) 
04-29 16:39:05.381: W/System.err(15134): at com.google.android.gms.maps.internal.IOnMapLongClickListener$Stub$Proxy.onMapLongClick(IOnMapLongClickListener.java:93) 
04-29 16:39:05.381: W/System.err(15134): at maps.i.s.a(Unknown Source) 
04-29 16:39:05.381: W/System.err(15134): at maps.y.v.d(Unknown Source) 
04-29 16:39:05.381: W/System.err(15134): at maps.y.bf.onLongPress(Unknown Source) 
04-29 16:39:05.381: W/System.err(15134): at maps.d.v.onLongPress(Unknown Source) 
04-29 16:39:05.381: W/System.err(15134): at maps.d.h.c(Unknown Source) 
04-29 16:39:05.381: W/System.err(15134): at maps.d.h.c(Unknown Source) 
04-29 16:39:05.381: W/System.err(15134): at maps.d.j.handleMessage(Unknown Source) 
04-29 16:39:05.391: W/System.err(15134): at android.os.Handler.dispatchMessage(Handler.java:99) 
04-29 16:39:05.391: W/System.err(15134): at android.os.Looper.loop(Looper.java:137) 
04-29 16:39:05.391: W/System.err(15134): at android.app.ActivityThread.main(ActivityThread.java:5041) 
04-29 16:39:05.391: W/System.err(15134): at java.lang.reflect.Method.invokeNative(Native Method) 
04-29 16:39:05.391: W/System.err(15134): at java.lang.reflect.Method.invoke(Method.java:511) 
04-29 16:39:05.391: W/System.err(15134): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
04-29 16:39:05.391: W/System.err(15134): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
04-29 16:39:05.391: W/System.err(15134): at dalvik.system.NativeStart.main(Native Method) 

你可以从堆栈跟踪看,预期的行为(使用API​​ 2 MapFragments)打开上长按上GoogleMap的实例的窗口。所以我首先想到的是试图从片段中打开的问题,所以我把这个回调传递给了拥有的Activity。同样的错误,同样没有额外的信息。

在这一点上,我最好的猜测是new()调用没有充分实例化类/视图,以便调用修改其视图。原来,这似乎是至少在某种程度上真的如视图修改代码迁移到活动,只需开启活动正常方式运行:

呼叫活动:

public void openMapDialog() 
    { 
     Intent intent = new Intent(this, DialogTestActivity.class); 
     startActivity(intent); 
    } 

新类代码:

public class DialogTestActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // From: https://stackoverflow.com/questions/11425020/actionbar-in-a-dialogfragment 
     this.requestWindowFeature(Window.FEATURE_ACTION_BAR); 
     this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND, WindowManager.LayoutParams.FLAG_DIM_BEHIND); 
     LayoutParams params = this.getWindow().getAttributes(); 
     params.alpha = 1.0f; 
     params.dimAmount = 0f; 
     this.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params); 

     // This sets the window size, while working around the IllegalStateException thrown by ActionBarView 
     this.getWindow().setLayout(600,600); 

     setContentView(R.layout.buttons_test); 
     } 
    } 

所以我想我张贴这一切的问题是要弄清楚,如果你想要做什么上面的海报建议,你不能只是新的()的活动,并呼吁showAsPopup()。这可能是我对Android的经验不足,虽然这看起来有点明显,但将showAsPopup()解释为由当前视图调用,而不是在创建视图时看起来很自然,因为您正在传递活动实例(如果它应该在onCreate()中完成,就像我最终做的那样,这只是这个)。

所以,如果目的是要调用showAsPopup()在创建活动,而不是创建活动,这不是明显的如何得到活动实例,它是之前的onCreate修改()被调用。问题是你不能在调用setContentView()之后调用诸如requestWindowFeature()之类的东西(example),这是一个问题,因为它通常在onCreate()中调用。

再次,如果有一个简单/更好的方法来做到这一点,我将非常感激反馈。希望这对那些想要使用这种方法的人有所帮助。

+0

谢谢,这对我有帮助。我面对问题的方法是将'showAsPopup(Activity activity)'方法改为“public static”方法,然后在其他任何地方('super.onCreate'除外)调用它'onCreate'。 – loudev

+0

Thanks for explain原始答案失败注意Niak说你的方法没有必要是静态的 –

+1

很好的解释!有两件事情仍然令人困惑:在第2点你正在写关于FRAGMENTS的内容,应该清楚的是,一个ACTIVITY显示另一个ACTIVITY 。没有涉及碎片。此外,DialogTestActivity的主题必须在应用清单中设置为@ style/PopupTheme,否则,对话框/弹出窗口将无法正确显示。 –

0

我知道这不是真正的答案,但上面的解决方案看起来很不雅,以至于人们可能会认为避免操作栏会更容易,就像从.noActionBar继承对话框主题,然后在仿效操作栏的面板顶部,至少这种方式都保留在xlm中。

+0

如果不雅,你的意思是太硬编码,在这里你去:'DisplayMetrics metrics = new DisplayMetrics(); \t \t getWindowManager()。getDefaultDisplay()。getMetrics()度量); \t \t getWindow()。setLayout(metrics.widthPixels - 80,metrics.heightPixels - 80);' – LoungeKatt

0

我已经找到了一个很好的方法来做到这一点,在DialogFragment的alertDialog的生成器上使用setCustomTitle(也可以在alertDialog本身上)。

public Dialog onCreateDialog(final Bundle savedInstanceState) { 
    final AlertDialog.Builder builder = new AlertDialog.Builder(activity,...); 
    final Toolbar toolbar = (Toolbar) inflater.inflate(R.layout.dialog_app_filter_toolbar, null, false); 
    // <= prepare toolbar and dialog here 
    return builder.create(); 
    } 

而结果(从my app):

enter image description here

enter image description here

如果你不想使用AlertDialog,你仍然可以只是把一个工具栏,你的布局对话框并使用它。