Domanda

Ho un DialogFragment per mostrare a View come una schermata popup.La finestra appare sempre al centro dello schermo.C'è un modo per impostare la posizione di DialogFragment finestra?Ho esaminato il codice sorgente ma non sono ancora riuscito a trovare nulla.

È stato utile?

Soluzione

Prova qualcosa del genere:

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

o altri metodi per getDialog().getWindow().

Assicurarsi di impostare la posizione dopo aver chiamato il contenuto di set.

Altri suggerimenti

Giusto, ho sbattuto la testa contro il muro per un'ora o due con questo, prima di riuscirci finalmente DialogFragment posizionato come volevo.

Sto continuando La risposta di Steelight Qui.Questo è l'approccio più semplice e affidabile che ho trovato.

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

Notare che params.width E params.softInputMode (usati nella risposta di Steelight) sono irrilevanti per questo.


Di seguito è riportato un esempio più completo.Ciò di cui avevo veramente bisogno era allineare un DialogFragment "casella di conferma" accanto a una vista "sorgente" o "genitore", nel mio caso un ImageButton.

Ho scelto di utilizzare DialogFragment, anziché qualsiasi frammento personalizzato, perché offre funzionalità di "dialogo" gratuite (chiudi la finestra di dialogo quando l'utente fa clic al di fuori di essa, ecc.).

Example ConfirmBox
Esempio confirmbox sopra il suo ImageButton "fonte" (cestino)

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

È abbastanza semplice rendere quanto sopra più generale aggiungendo parametri o setter del costruttore secondo necessità.(La mia finale ConfirmBox ha un pulsante con stile (all'interno di alcuni bordi, ecc.) il cui testo e View.OnClickListener può essere personalizzato nel codice.)

getDialog().getWindow() non funzionerà per un DialogFragment come getWindow() restituirà NULL se l'attività di hosting non è visibile, che non è se stai scrivendo un'app basata su frammenti.Otterrai un NullPointerException quando si tenta getAttributes().

Raccomando la risposta della Moutry.Se hai già una classe di dialogoFagment, non è troppo difficile passare.Basta sostituire il metodo OnCreateDialog con uno che costruisce e restituisce un popupwindow.Quindi dovresti essere in grado di riutilizzare la vista che si fornisce al AlertDialog.builder.setView() e chiamare (PopupWindow object).showAtLocation().

È necessario sovrascrivere il metodo OnResume () nella finestra di dialogo come segue:

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

Sto usando la classe POPUPWINDOW per questo scopo perché è possibile specificare la posizione e la dimensione della vista.

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

Sto usando AppCompatDialogFragment da android.support.v7.app.AppCompatDialogFragment e voglio allineare il frammento di dialogo sulla parte inferiore dello schermo e rimuovere anche tutti i bordi, specialmente dovevo impostare la larghezza del contenuto per abbinare il genitore.

Allora, volevo da questo (sfondo giallo proviene dal rootlayout del frammento di dialogo):

 SRC_IMG_1

Ottieni questo:

 SRC_IMG_2

Nessuna delle soluzioni abate ha funzionato.Quindi, sono riuscito a farlo:

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top