2012-07-11 48 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,你仍然可以只是把一個工具欄,你的佈局對話框並使用它。