Question

j'ai un DialogFragment montrer un View comme un écran contextuel.La fenêtre apparaît toujours au milieu de l'écran.Existe-t-il un moyen de définir la position du DialogFragment fenêtre?J'ai regardé dans le code source mais je n'ai encore rien trouvé.

Était-ce utile?

La solution

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 définir la position après avoir appelé set-content.

Autres conseils

C'est vrai, je me suis cogné la tête contre le mur pendant une heure ou deux avec ça, avant de finalement obtenir DialogFragment positionné comme je le voulais.

je bâtis 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));
} 

Noter que params.width et params.softInputMode (utilisés dans la réponse de Steelight) ne sont pas pertinents pour cela.


Vous trouverez ci-dessous un exemple plus complet.Ce dont j'avais vraiment besoin, c'était d'aligner un DialogFragment "boîte de confirmation" à côté d'une vue "source" ou "parente", dans mon cas, un ImageButton.

J'ai choisi d'utiliser DialogFragment, au lieu de n'importe quel Fragment personnalisé, car il vous offre gratuitement des fonctionnalités de "dialogue" (fermer la boîte de dialogue lorsque l'utilisateur clique à l'extérieur, etc.).

Example ConfirmBox
Exemple ConfirmBox 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 https://stackoverflow.com/q/13822842/56285
        Window window = getDialog().getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.dimAmount = 0.2f; // dim only a little bit
        window.setAttributes(params);

        // Transparent background; see https://stackoverflow.com/q/15007272/56285
        // (Needed to make dialog's alpha shadow look good)
        window.setBackgroundDrawableResource(android.R.color.transparent);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Put your dialog layout in R.layout.view_confirm_box
        View view = inflater.inflate(R.layout.view_confirm_box, container, false);

        // Initialise what you need; set e.g. button texts and listeners, etc.

        // ...

        setDialogPosition();

        return view;
    }

    /**
     * Try to position this dialog next to "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 rendre l'utilisation ci-dessus plus générale en ajoutant des paramètres de constructeur ou des setters si nécessaire.(Ma finale ConfirmBox a un bouton stylisé (à l'intérieur de certaines bordures, etc.) dont le texte et View.OnClickListener peut être personnalisé dans le code.)

getDialog().getWindow() ne fonctionnera pas pour un DialogFragment comme getWindow() renverra null 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 quand tu essaies getAttributes().

Je recommande la réponse de Mobistry.Si vous disposez déjà d’une classe DialogFragment, il n’est pas trop difficile d’en changer.Remplacez simplement la méthode onCreateDialog par une méthode qui construit et renvoie une PopupWindow.Vous devriez alors pouvoir réutiliser la vue que vous fournissez AlertDialog.builder.setView(), et appelle (PopupWindow object).showAtLocation().

Vous devez remplacer la méthode onResume() dans votre DialogFragment 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();
}

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

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(mActivity, R.style.BottomDialog);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // 
    dialog.setContentView(R.layout.layout_video_live);
    dialog.setCanceledOnTouchOutside(true);

    Window window = dialog.getWindow();
    assert window != null;
    WindowManager.LayoutParams lp = window.getAttributes();
    lp.gravity = Gravity.BOTTOM; //psotion
    lp.width = WindowManager.LayoutParams.MATCH_PARENT; // fuill screen
    lp.height = 280;
    window.setAttributes(lp);
    return dialog;
}

j'utilise AppCompatDialogFragment depuis android.support.v7.app.AppCompatDialogFragment et je souhaite aligner le fragment de boîte de dialogue au bas de l'écran et également supprimer toutes les bordures, en particulier je devais définir la largeur du contenu pour qu'elle corresponde au parent.

Donc, je voulais de ceci (le fond jaune vient du rootLayout du fragment de dialogue) :

src_img_1

Obtenez ceci :

src_img_2

Aucune des solutions ci-dessus n'a fonctionné.J'ai donc réussi à faire ceci :

fun AppCompatDialogFragment.alignToBottom() {
    dialog.window.apply {
        setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)
        decorView.apply {

            // Get screen width
            val displayMetrics = DisplayMetrics().apply {
                windowManager.defaultDisplay.getMetrics(this)
            }

            setBackgroundColor(Color.WHITE) // I don't know why it is required, without it background of rootView is ignored (is transparent even if set in xml/runtime)
            minimumWidth = displayMetrics.widthPixels
            setPadding(0, 0, 0, 0)
            layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
            invalidate()
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top