Position de DialogFragment dans Android

j'ai un DialogFragment pour afficher un View comme un écran Popup. La fenêtre apparaît toujours au milieu de l'écran. Est-il un moyen de régler la position de la DialogFragment fenêtre? J'ai regardé dans le code source mais n'a pas pu trouver quoi que ce soit encore.

48
demandé sur Jonik 2012-03-14 12:43:02

5 réponses

Essayez quelque chose comme ceci:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    getDialog().getWindow().setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
    WindowManager.LayoutParams p = getDialog().getWindow().getAttributes();
    p.width = ViewGroup.LayoutParams.MATCH_PARENT;
    p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
    p.x = 200;
    ...
    getDialog().getWindow().setAttributes(p);
    ...

ou d'autres méthodes pour getDialog().getWindow() .

assurez-vous de régler la position après avoir appelé set-content.

79
répondu Steelight 2015-07-29 01:48:26

à droite, j'ai cogné la tête contre le mur pendant une heure ou deux avec ceci, avant de finalement obtenir DialogFragment positionné comme je voulais.

Je m'appuie sur la réponse de Steelight ici. C'est l'approche la plus simple et la plus fiable que j'ai trouvée.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle b) {
    Window window = getDialog().getWindow();

    // set "origin" to top left corner, so to speak
    window.setGravity(Gravity.TOP|Gravity.LEFT);

    // after that, setting values for x and y works "naturally"
    WindowManager.LayoutParams params = window.getAttributes();
    params.x = 300;
    params.y = 100;
    window.setAttributes(params);

    Log.d(TAG, String.format("Positioning DialogFragment to: x %d; y %d", params.x, params.y));
} 

notez que params.width et params.softInputMode (utilisés dans la réponse de Steelight) ne sont pas pertinents à cet égard.


ci-dessous est un exemple plus complet. Ce dont j'avais vraiment besoin était d'aligner un fragment de dialogue "confirm box" à côté d'une vue "source" ou "parent", dans mon cas un bouton D'image.

j'ai choisi D'utiliser DialogFragment, au lieu de N'importe quel Fragment personnalisé, Parce qu'il vous donne des fonctionnalités de" dialogue " gratuitement (fermer dialogue lorsque l'utilisateur clique en dehors de lui, etc).

Example ConfirmBox

exemple Confirmmbox au-dessus de son ImageButton "source" (poubelle)

/**
 * A custom DialogFragment that is positioned above given "source" component.
 *
 * @author Jonik, https://stackoverflow.com/a/20419231/56285
 */
public class ConfirmBox extends DialogFragment {
    private View source;

    public ConfirmBox() {
    }

    public ConfirmBox(View source) {
        this.source = source;            
    }

    public static ConfirmBox newInstance(View source) {
        return new ConfirmBox(source);
    }

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

        setStyle(STYLE_NO_FRAME, R.style.Dialog);
    }


    @Override
    public void onStart() {
        super.onStart();

        // Less dimmed background; see /q/dialogfragment-with-clear-background-not-dimmed-11668/"source" view
     */
    private void setDialogPosition() {
        if (source == null) {
            return; // Leave the dialog in default position
        }

        // Find out location of source component on screen
        // see https://stackoverflow.com/a/6798093/56285
        int[] location = new int[2];
        source.getLocationOnScreen(location);
        int sourceX = location[0];
        int sourceY = location[1];

        Window window = getDialog().getWindow();

        // set "origin" to top left corner
        window.setGravity(Gravity.TOP|Gravity.LEFT);

        WindowManager.LayoutParams params = window.getAttributes();

        // Just an example; edit to suit your needs.
        params.x = sourceX - dpToPx(110); // about half of confirm button size left of source view
        params.y = sourceY - dpToPx(80); // above source view

        window.setAttributes(params);
    }

    public int dpToPx(float valueInDp) {
        DisplayMetrics metrics = getActivity().getResources().getDisplayMetrics();
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
    }
}

il est assez facile de généraliser l'utilisation ci-dessus en ajoutant des paramètres de constructeur ou des setters si nécessaire. (Mon dernier ConfirmBox a un bouton stylé (à l'intérieur de certaines frontières etc) dont le texte et View.OnClickListener peuvent être personnalisés en code.)

70
répondu Jonik 2017-05-23 12:18:15

getDialog().getWindow() ne fonctionnera pas pour un DialogFragment car getWindow() retournera nul si l'activité d'hébergement n'est pas visible, ce qui n'est pas le cas si vous écrivez une application basée sur des fragments. Vous obtiendrez un NullPointerException en essayant getAttributes() .

je recommande la réponse de Mobistry. Si vous avez déjà une classe DialogFragment, il n'est pas trop difficile de basculer. Il suffit de remplacer la méthode onCreateDialog par une méthode qui construit et renvoie un PopupWindow. Ensuite, vous devriez être en mesure pour réutiliser la vue que vous fournissez à AlertDialog.builder.setView() , et appelez (PopupWindow object).showAtLocation() .

4
répondu Austin B 2014-11-23 05:22:40

j'utilise la classe PopupWindow à cet effet parce que vous pouvez spécifier l'emplacement et la taille de la vue.

3
répondu Sileria 2012-08-02 21:03:58

vous devez modifier la méthode onResume () dans votre fragment de dialogue comme suit:

@Override
public void onResume() {
    final Window dialogWindow = getDialog().getWindow();
    WindowManager.LayoutParams lp = dialogWindow.getAttributes();
    lp.x = 100;        // set your X position here
    lp.y = 200;        // set your Y position here
    dialogWindow.setAttributes(lp);

    super.onResume();
}
3
répondu Zahidur Rahman Faisal 2016-07-16 06:36:49