Frage

Ich habe eine DialogFragment um ein zu zeigen View wie ein Popup-Bildschirm.Das Fenster erscheint immer in der Mitte des Bildschirms.Gibt es eine Möglichkeit, die Position des DialogFragment fenster?Ich habe in die geschaut Quellcode konnte aber noch nichts finden.

War es hilfreich?

Lösung

Versuchen Sie so etwas:

@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);
    ...

oder andere Methoden für getDialog().getWindow().

stellen Sie sicher, dass Sie die Position nach dem Aufruf von set-content festlegen.

Andere Tipps

Richtig, ich habe damit ein oder zwei Stunden lang mit dem Kopf gegen die Wand geschlagen, bevor ich endlich kam DialogFragment positioniert wie ich wollte.

Ich baue auf Antwort von Steelight hier.Dies ist der einfachste und zuverlässigste Ansatz, den ich gefunden habe.

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

Beachten Sie, dass params.width und params.softInputMode (in Steelights Antwort verwendet) sind dafür irrelevant.


Unten ist ein vollständigeres Beispiel.Was ich wirklich brauchte, war, ein DialogFragment "Bestätigungsfeld" neben einer "Quell" - oder "übergeordneten" Ansicht auszurichten, in meinem Fall einen ImageButton.

Ich habe mich dafür entschieden, DialogFragment anstelle eines benutzerdefinierten Fragments zu verwenden, da es Ihnen kostenlose "Dialog" -Funktionen bietet (Dialog schließen, wenn der Benutzer außerhalb davon klickt usw.).

Example ConfirmBox
Beispiel Bestätigungsbox über dem ImageButton "Quelle" (Papierkorb)

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

Es ist ziemlich einfach, das Obige allgemeiner zu verwenden, indem Konstruktorparameter oder Setter nach Bedarf hinzugefügt werden.(Mein Finale ConfirmBox hat eine gestaltete Schaltfläche (innerhalb einiger Ränder usw.), deren Text und View.OnClickListener kann im Code angepasst werden.)

getDialog().getWindow() wird nicht für eine Arbeit DialogFragment als getWindow() gibt null zurück, wenn die Hosting-Aktivität nicht sichtbar ist, was nicht der Fall ist, wenn Sie eine fragmentbasierte App schreiben.Sie erhalten eine NullPointerException wenn du es versuchst getAttributes().

Ich empfehle die Antwort von Mobistry.Wenn Sie bereits eine DialogFragment Klasse haben, ist es nicht allzu schwer umzuschalten.Ersetzen Sie einfach die onCreateDialog-Methode durch eine, die ein PopupWindow erstellt und zurückgibt.Dann sollten Sie in der Lage sein, die von Ihnen bereitgestellte Ansicht wiederzuverwenden AlertDialog.builder.setView(), und rufen Sie an (PopupWindow object).showAtLocation().

Sie müssen die onResume () -Methode in Ihrem DialogFragment wie folgt überschreiben:

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

Ich verwende zu diesem Zweck die PopupWindow-Klasse, da Sie den Speicherort und die Größe der Ansicht angeben können.

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

Ich benutze AppCompatDialogFragment von android.support.v7.app.AppCompatDialogFragment und ich möchte das Dialogfragment am unteren Bildschirmrand ausrichten und auch alle Ränder entfernen, insbesondere musste ich die Inhaltsbreite so einstellen, dass sie mit dem übergeordneten Element übereinstimmt.

Also, ich wollte davon (gelber Hintergrund kommt von rootLayout des Dialogfragments):

src_img_1

Hol dir das:

src_img_2

Keine der oben genannten Lösungen hat funktioniert.Also habe ich das geschafft:

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()
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top