Pergunta

eu tenho um DialogFragment para mostrar um View como uma tela pop-up.A Janela aparece sempre no meio da tela.Existe uma maneira de definir a posição do DialogFragment janela?Eu olhei para o Código fonte mas ainda não consegui encontrar nada.

Foi útil?

Solução

Tente algo assim:

@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 outros métodos para getDialog().getWindow().

certifique-se de definir a posição após chamar set-content.

Outras dicas

Certo, bati a cabeça na parede por uma ou duas horas com isso, antes de finalmente conseguir DialogFragment posicionado como eu queria.

Estou construindo A resposta da Steelight aqui.Esta é a abordagem mais simples e confiável que encontrei.

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

Observe que params.width e params.softInputMode (usados ​​na resposta do Steelight) são irrelevantes para isso.


Abaixo está um exemplo mais completo.O que eu realmente precisava era alinhar um DialogFragment de "caixa de confirmação" ao lado de uma visualização "fonte" ou "pai", no meu caso, um ImageButton.

Optei por usar o DialogFragment, em vez de qualquer Fragment personalizado, porque ele oferece recursos de "caixa de diálogo" gratuitamente (fechar a caixa de diálogo quando o usuário clicar fora dela, etc.).

Example ConfirmBox
Exemplo de ConfirmBox acima de seu ImageButton "fonte" (lixeira)

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

É muito fácil tornar o uso acima mais geral adicionando parâmetros de construtor ou setters conforme necessário.(Meu último ConfirmBox tem um botão estilizado (dentro de algumas bordas, etc.) cujo texto e View.OnClickListener pode ser personalizado no código.)

getDialog().getWindow() não funcionará por um DialogFragment como getWindow() retornará nulo se a atividade de hospedagem não estiver visível, o que não acontece se você estiver escrevendo um aplicativo baseado em fragmentos.Você receberá um NullPointerException quando você tenta getAttributes().

Eu recomendo a resposta do Mobistry.Se você já possui uma classe DialogFragment, não é muito difícil mudar.Basta substituir o método onCreateDialog por um que construa e retorne um PopupWindow.Então você poderá reutilizar a visualização fornecida para AlertDialog.builder.setView(), e ligue (PopupWindow object).showAtLocation().

Você precisa substituir o método onResume() em seu DialogFragment como 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();
}

Estou usando a classe PopupWindow para essa finalidade porque você pode especificar a localização e o tamanho da visualização.

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

estou usando AppCompatDialogFragment de android.support.v7.app.AppCompatDialogFragment e quero alinhar o fragmento da caixa de diálogo à parte inferior da tela e também remover todas as bordas, especialmente porque precisava definir a largura do conteúdo para corresponder ao pai.

Então, eu queria isso (o fundo amarelo vem do rootLayout do fragmento de diálogo):

src_img_1

Pegue isto:

src_img_2

Nenhuma das soluções acima funcionou.Então, consegui fazer isso:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top