46 votes

ActionBar dans un DialogFragment

Dans l'application Calendrier sur mon Galaxy Tab 10.1, lors de la création d'un nouvel événement, une boîte de dialogue apparaît avec Fait et Annuler les boutons dans la barre de titre/action bar.

enter image description here

Je tiens à l'appliquer dans mon application. J'ai essayé à l'aide d' setHasOptionsMenu(true) de plus impérieuses onCreateOptionsMenu mon DialogFragment sous-classe, mais mon action éléments n'apparaissent pas. J'ai aussi essayé de les appeler, getDialog().getActionBar() de dans les onCreateView , mais il renvoie toujours null.

Je suis en mesure d'obtenir ce travail, si je commence un Activity plutôt que d'afficher une boîte de dialogue, mais qui prend tout l'écran. Est-il un moyen standard pour ce faire à l'aide d'un DialogFragment?

86voto

StrikeForceZero Points 1404

à l'aide de l'idée à partir d'un google group post , j'ai été en mesure de le retirer de style d'une activité. vous souhaitez modifier la hauteur et la largeur d'une "dynamique" de la taille de votre choix de préférence. Ensuite, réglez ActionBar boutons que vous souhaitez

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

14voto

nagoya0 Points 808

Si vous utilisez ActionBarSherlock, déclarer le thème comme ci-dessous:

<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>

Et, d'initialiser un SherlockActivity avec PopupTheme selon Luc Sleeman réponse.

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

Résultat:

enter image description here

11voto

user1475907 Points 108

Eu quelques difficultés à mettre en œuvre les solutions proposées à partir de StrikeForceZero et Luc Sleeman, donc j'ai voulu contribuer à mon expérience. Je suis sûr qu'il ya juste quelque chose qui me manque, donc la rétroaction serait très apprécié.

Ce que j'ai fait est le suivant:

  1. Créer un style à l'aide du PopupTheme, directement copier/coller:

    <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. Ajouter le showAsPopup() la méthode comme une méthode dans le fragment qui permettrait d'ouvrir le faux dialogue fragment, directement copier/coller:

    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. Créer une instance de la nouvelle activité à l'aide d'un simple nouveau (), et puis la passer à la showAsPopup() la méthode:

    DialogTestActivity test = new DialogTestActivity();
    showAsPopup(test);
    
  4. Dans le but de le tester (j'essayais juste pour confirmer que je pouvais ouvrir une activité qui est présenté comme un dialogue avec une barre d'action), j'ai utilisé une très simple test, volé directement à partir du bouton api d'affichage de démonstration (pour le fichier de mise en page, voir buttons_1.xml dans l'api démos):

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

Malheureusement, à chaque fois que j'ai essayé ceci, j'obtiens une quelconque exception de pointeur null sur le premier appel, en activité.requestWindowFeature(Fenêtre.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)

Comme vous pouvez le voir à partir de la trace de la pile, le comportement attendu est d'ouvrir la fenêtre sur un appui long sur une GoogleMap instance (à l'aide de la MapFragments de l'API 2). Donc, ma première pensée a été qu'il y avait un problème en essayant de l'ouvrir à partir d'un Fragment, donc j'ai passé l'appel vers le propriétaire de l'Activité. Même erreur, même pas de renseignements supplémentaires.

Ma meilleure supposition à ce point était qu'un nouveau() l'appel n'a pas suffisamment d'instancier la classe/vue pour faire des appels à modifier son point de vue. S'avère que cela semble être au moins un peu vrai, que la migration de la vue de la modification du code dans l'activité et simplement l'ouverture de l'activité d'une façon normale de travaux:

L'appel de l'activité:

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

Nouveau code de classe:

    public class DialogTestActivity extends Activity {

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

        // From: http://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);
        }
    }

Donc je suppose que le point de moi de poster tout cela est à préciser que si vous voulez faire ce que les affiches ci-dessus l'indique, vous ne pouvez pas nouveau() une activité et appelez showAsPopup(). C'est peut-être mon inexpérience avec Android montrant à travers, mais tout cela semble un peu évident, il semble naturel d'interpréter showAsPopup() que d'être appelé par le point de vue actuel, non de la vue en cours de création, que vous êtes de passage dans l'instance d'activité (ce qui pourrait être cette si il était censé être fait dans onCreate() comme j'ai fait).

Donc, si l'intention est d'appeler showAsPopup() dans la création de l'activité et non le créé de l'activité, il n'est pas évident comment faire pour obtenir l'instance d'Activité est modifiable avant le onCreate() est appelée. Le problème étant que vous ne pouvez pas appeler les choses comme requestWindowFeature() après setContentView() est appelée (exemple), ce qui est un problème car il est généralement appelé dans onCreate().

Encore une fois, si il est facile de/la meilleure façon de le faire, je serais très heureux de la rétroaction. Espérons que cela est utile pour les personnes qui veulent utiliser cette approche.

4voto

Luke Sleeman Points 395

J'ai passé une quantité incroyable de temps à jouer avec cela. La accepté de répondre travaille sur un galaxy nexus 7 (Android 4.2), mais échoue sur un samsung galaxy SIII (Android 4.1) et un samsung galaxy tab 10.2 (Android 4.0), avec l'exception suivante:

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

Ceci est causé par le code dans ActionBarView.onMeasure(int, int) qui vérifie pour s'assurer de la mise en page est définie à match_parent. La bonne solution est plutôt de régler la largeur de la fenêtre via setLayout au lieu d'utiliser le setAttributes.

C'est une version fixe de showAsPopup (), qui fonctionne sur tous les appareils que j'ai testé sous:

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

Par souci d'exhaustivité, voici la PopupTheme de nouveau:

<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>

1voto

javaJoe Points 1279

Comme Veeti implicite, vous pouvez essayer de mettre en œuvre une Activité avec une boîte de Dialogue Thème. Dans le Manifeste Android:

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

J'espère que ça va aider.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X