ActionBar en un DialogFragment

En la aplicación Calendario de mi Galaxy Tab 10.1, al crear un evento nuevo aparece un cuadro de diálogo con los botones Hecho y Cancelar en la barra de título / área de la barra de acciones.

enter image description here

Me gustaría implementar esto en mi aplicación. Intenté usar setHasOptionsMenu(true) además de anular onCreateOptionsMenu en mi subclase DialogFragment , pero mis elementos de acción no aparecen. También intenté llamar a getDialog().getActionBar() desde onCreateView pero siempre devuelve null .

Puedo hacer que esto funcione si comienzo una Activity lugar de mostrar un diálogo, pero eso ocupa toda la pantalla. ¿Hay una forma estándar de hacer esto usando un DialogFragment ?

    Usando la idea de una publicación de grupo de Google, pude llevarlo a cabo diseñando una actividad. desearía modificar la altura y el ancho preferiblemente a un tamaño “dynamic” de su elección. Luego configura los botones de ActionBar que quieras

      

     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); } 

    Si está utilizando ActionBarSherlock, declare el tema de la siguiente manera:

      

    Y, inicialice una actividad de Sherlock con PopupTheme según la respuesta de Luke Sleeman .

     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); } 

    Resultado:

    enter image description here

    Tuve algunos problemas para implementar las soluciones sugeridas de StrikeForceZero y Luke Sleeman, así que quería contribuir con mi experiencia. Estoy seguro de que hay algo que me falta, por lo que los comentarios serán muy apreciados.

    Lo que hice fue lo siguiente:

    1. Crea un estilo usando el PopupTheme provisto, copia / pega directamente:

        
    2. Agregue el método showAsPopup () como un método en el fragmento que abriría el fragmento falso del diálogo, copiar / pegar directamente:

       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. Cree una instancia de la nueva actividad usando una llamada new () nueva y luego páselo al método showAsPopup ():

       DialogTestActivity test = new DialogTestActivity(); showAsPopup(test); 
    4. Para el propósito de la prueba (solo estaba tratando de confirmar que podía abrir una actividad que se presenta como un diálogo con una barra de acción) utilicé una prueba extremadamente simple, robada directamente de la demo de API de la vista de botón (para el archivo de diseño) , vea buttons_1.xml en las demos de api):

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

    Desafortunadamente, cada vez que probé esto, obtengo una excepción de puntero nulo no especificado en la primera llamada, 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.isa(Unknown Source) 04-29 16:39:05.381: W/System.err(15134): at maps.yvd(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.dvonLongPress(Unknown Source) 04-29 16:39:05.381: W/System.err(15134): at maps.dhc(Unknown Source) 04-29 16:39:05.381: W/System.err(15134): at maps.dhc(Unknown Source) 04-29 16:39:05.381: W/System.err(15134): at maps.djhandleMessage(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) 

    Como se puede ver en el seguimiento de la stack, el comportamiento previsto es abrir la ventana con una pulsación larga en una instancia de GoogleMap (utilizando los MapFragments de la API 2). Así que lo primero que pensé fue que había un problema al intentar abrir desde un Fragmento, así que pasé la llamada a la Actividad propietaria. Mismo error, mismo sin información adicional.

    Mi mejor suposición en este punto fue que una llamada nueva () no creaba una instancia suficiente de la clase / vista para hacer llamadas para modificar su vista. Resulta que esto parece ser al menos algo cierto, ya que migrar el código de modificación de vista a la actividad y simplemente abrir la actividad de la manera normal funciona:

    Actividad de llamada

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

    Nuevo código de clase:

      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); } } 

    Así que supongo que el objective de publicar todo esto es aclarar que si quieres hacer lo que sugieren los carteles anteriores, no puedes simplemente new () una actividad y llamar a showAsPopup (). Esta puede ser mi falta de experiencia con Android, pero aunque parezca obvio, también parece natural interpretar que ShowAsPopup () es invocado por la vista actual, no por la vista que se está creando, cuando pasas la instancia de la actividad (que sería solo esto si se suponía que debía hacerse en onCreate () como terminé haciendo).

    Entonces, si la intención es llamar a showAsPopup () en la actividad de creación y no a la actividad creada , no es obvio cómo obtener la instancia de la actividad que es modificable antes de llamar a onCreate (). El problema es que no se puede llamar a cosas como requestWindowFeature () después de llamar a setContentView () ( ejemplo ), que es un problema ya que normalmente se llama en onCreate ().

    Una vez más, si hay una manera fácil / mejor de hacer esto, apreciaría mucho los comentarios. Con suerte, esto es útil para las personas que desean utilizar este enfoque.

    He pasado una cantidad increíble de tiempo jugando con esto. La respuesta aceptada funciona en un galaxy nexus 7 (Android 4.2), pero falla en una galaxia Samsung SIII (Android 4.1) y una Samsung Galaxy Tab 10.2 (Android 4.0), con la siguiente excepción:

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

    Esto es causado por el código en ActionBarView.onMeasure (int, int) que comprueba para asegurarse de que el diseño se establece en match_parent. La solución correcta es establecer el ancho de la ventana mediante setLayout en lugar de usar setAttributes.

    Esta es una versión fija de showAsPopup () que funciona en todos los dispositivos en los que he probado:

     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); } 

    Para completar, aquí está el PopupTheme nuevamente:

      

    Como Veeti implicó, puede intentar implementar una Actividad con un Tema de Diálogo. En el Manifiesto de Android:

     
    		      	

    Probablemente no tengo tanta experiencia en eso, pero usaría una actividad, agregaría elementos de la barra de acción y luego:

    android:theme="@android:style/Theme.Holo.Light.Dialog" />

    ¡Espero que ayude!

    He encontrado una buena manera de hacerlo, usando setCustomTitle en el generador del alertDialog para DialogFragment (también posible en el alertDialog mismo).

     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(); } 

    Y el resultado (de mi aplicación ):

    enter image description here

    enter image description here

    Si no desea utilizar AlertDialog, puede simplemente poner una barra de herramientas en su diseño del diálogo y usarlo.

    Sé que no es una respuesta real, pero las soluciones anteriores parecen tan poco elegantes que uno podría pensar que sería más fácil evitar la barra de acción, como heredar el tema de su diálogo de algo con .noActionBar y luego crear una vista en la parte superior de su panel que imita la barra de acción, al menos de esta manera todo queda en xlm.