Pregunta

tengo un DialogFragment para mostrar un View como una pantalla emergente.La ventana aparece siempre en el medio de la pantalla.¿Hay alguna manera de establecer la posición del DialogFragment ¿ventana?He mirado en el código fuente pero no pude encontrar nada todavía.

¿Fue útil?

Solución

Pruebe algo como esto:

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

u otros métodos para getDialog().getWindow().

asegúrese de establecer la posición después de llamar a set-content.

Otros consejos

Bien, me golpeé la cabeza contra la pared durante una o dos horas con esto, antes de finalmente conseguirlo. DialogFragment posicionado como quería.

estoy construyendo sobre La respuesta de Steelight aquí.Este es el enfoque más simple y confiable que encontré.

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

Tenga en cuenta que params.width y params.softInputMode (usados ​​en la respuesta de Steelight) son irrelevantes para esto.


A continuación se muestra un ejemplo más completo.Lo que realmente necesitaba era alinear un DialogFragment de "cuadro de confirmación" junto a una Vista "fuente" o "principal", en mi caso un ImageButton.

Elegí usar DialogFragment, en lugar de cualquier Fragmento personalizado, porque le brinda funciones de "diálogo" de forma gratuita (cerrar el diálogo cuando el usuario hace clic fuera de él, etc.).

Example ConfirmBox
Ejemplo de ConfirmBox encima de su ImageButton "fuente" (papelera)

/**
 * 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 bastante fácil hacer que lo anterior sea de uso más general agregando parámetros de constructor o definidores según sea necesario.(Mi final ConfirmBox tiene un botón con estilo (dentro de algunos bordes, etc.) cuyo texto y View.OnClickListener se puede personalizar en código.)

getDialog().getWindow() no funcionará para un DialogFragment como getWindow() devolverá nulo si la actividad de alojamiento no es visible, lo cual no es así si estás escribiendo una aplicación basada en fragmentos.Obtendrás un NullPointerException cuando lo intentas getAttributes().

Recomiendo la respuesta de Mobistry.Si ya tiene una clase DialogFragment, no es demasiado difícil cambiarla.Simplemente reemplace el método onCreateDialog con uno que construya y devuelva una ventana emergente.Entonces deberías poder reutilizar la Vista que proporcionas AlertDialog.builder.setView(), y llama (PopupWindow object).showAtLocation().

Debe anular el método onResume() en su DialogFragment de la siguiente manera:

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

Estoy usando la clase PopupWindow para este propósito porque puedes especificar la ubicación y el tamaño de la 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;
}

estoy usando AppCompatDialogFragment de android.support.v7.app.AppCompatDialogFragment y quiero alinear el fragmento de diálogo con la parte inferior de la pantalla y también eliminar todos los bordes, especialmente necesitaba establecer el ancho del contenido para que coincida con el principal.

Entonces, quería de esto (el fondo amarillo proviene del diseño raíz del fragmento de diálogo):

src_img_1

Toma esto:

src_img_2

Ninguna de las soluciones anteriores funcionó.Entonces, logré hacer esto:

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()
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top