Размер DialogFragment всегда изменяется при открытии программной клавиатуры.

У меня возникли проблемы с пользовательским DialogFragment, который отображается в полноэкранном режиме. Это диалоговое окно имеет содержимое, которое можно прокручивать, и имеет автозаполнение текста.

Первоначально диалоговое окно отображается с отступом вверху, установленным программно как прозрачный вид в верхней части содержимого макета. Как только автозаполнение текстового представления фокусируется, это поле уменьшается до 0 (что создает иллюзию того, что диалог переходит в полноэкранный режим). В этот момент также отображается клавиатура.

В настоящее время клавиатура уменьшила размер диалогового окна, а кнопка, которая находится в диалоговом окне, перемещена вверх, над клавиатурой. Это создает проблему, потому что, как только autocompletetextview теряет фокус, размер диалогового окна изменяется, а из-за изменения размера клавиатуры также создается мерцание: клавиатура скрыта -> диалог перемещается внизу -> размер диалога изменяется до полноэкранного -> диалоговое окно изменяется до исходного размера

Текущее создание диалога:

@Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);

        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);

        if (!hasTitle()) {
            dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        }

        // the content
        //final RelativeLayout root = new RelativeLayout(getActivity());
        //root.setLayoutParams(
        //        new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        //dialog.setContentView(root);

        if (position != null) {
            WindowManager.LayoutParams windowParams = dialog.getWindow().getAttributes();
            windowParams.x = position.x;
            windowParams.y = position.y;
            dialog.getWindow().setAttributes(windowParams);
        } else {
            dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        }

        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(hasTitle() ? Color.WHITE : Color.TRANSPARENT));
        dialog.getWindow().setGravity(Gravity.TOP | Gravity.START);

        return dialog;
    }

Это работает частично, так как диалоговое окно не заполняет ширину, оно намного меньше.

Что-то исправляет это, но создает другую проблему:

@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_DeviceDefault_DialogWhenLarge_NoActionBar);
    }

Но это повлияет на то, как выглядит фон диалога, и я не могу изменить его с помощью метода создания диалога.


person Ionut Negru    schedule 10.06.2016    source источник


Ответы (2)


Наконец-то я нашел решение своей проблемы.

Создание диалога:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = super.onCreateDialog(savedInstanceState);

    if (!hasTitle()) {
        dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
    }

    if (position != null) {
        WindowManager.LayoutParams windowParams = dialog.getWindow().getAttributes();
        windowParams.x = position.x;
        windowParams.y = position.y;
        dialog.getWindow().setAttributes(windowParams);
    } else {
        WindowManager.LayoutParams attrs = dialog.getWindow().getAttributes();
        attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
        dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    }

    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(hasTitle() ? Color.WHITE : Color.TRANSPARENT));
    dialog.getWindow().setGravity(Gravity.TOP | Gravity.START);

    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);    

    return dialog;
}

Создание фрагмента (стиль диалога настраиваю - очень важно использовать No_FRAME):

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // We customize the style of this dialog - we remove the frames of the dialogs and leave the drawing to the
    // onCreateView() method, and we use the custom theme for dialogs - this is a special theme which has no
    // Background and the status bar is left unchanged
    setStyle(DialogFragment.STYLE_NO_FRAME, R.style.Theme_Dialog);
}

Пользовательская тема (я повторно использую все свои стили, чтобы диалог выглядел одинаково):

<!-- Custom theme for dialogs - this will use the same styling as the main theme, but will disable the background
 of the window, and it will also leave the status bar color unchanged -->
<style name="Theme.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <!-- We do not want to change the status bar color -->
    <item name="colorPrimaryDark">@color/transparent</item>
</style>

Теперь мой фрагмент диалога выглядит так, как будто он полноэкранный, и он больше не изменяет размер при открытии программной клавиатуры, создавая эффект мерцания при ручном изменении его размера. Важная часть была DialogFragment.STYLE_NO_FRAME.

Я надеюсь, что это поможет другим с похожими проблемами.

person Ionut Negru    schedule 10.06.2016
comment
Какой УЖАС, брув.. Поверь мне, Ты спаси меня. Я ломаю голову над этим с последних 2 дней. Этот ответ заслуживает 100 голосов. Я нигде не нашел STYLE_NO_FRAME. - person Diaz diaz; 18.07.2018
comment
Рад, что это кому-то помогло, даже спустя несколько лет после публикации: D - person Ionut Negru; 25.02.2019
comment
спасибо! Я был обеспокоен этой проблемой в течение нескольких часов. Ты мне нравишься! Но я не могу выйти замуж... прости... - person Tom Marvolo Riddle; 13.03.2019

Вы можете сделать одну вещь для этого...

Добавьте это в свой onViewCreated:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
    super.onViewCreated(view, savedInstanceState);
}

Использование AdjustPan Размер главного окна активности не изменяется, чтобы освободить место для программной клавиатуры. Поэтому в этом случае все виды страницы вашего фрагмента должны быть в ScrollView, или пользователю может потребоваться закрыть программную клавиатуру, чтобы получить доступ к скрытым частям окна и взаимодействовать с ними. .

Надеюсь, что это поможет вам.

person Vishal Chauhan    schedule 10.06.2016
comment
Ваш отредактированный ответ такой же, только он установлен программно. Как и следовало ожидать, результат тот же. - person Ionut Negru; 10.06.2016
comment
Да, вы правы... но в некоторых случаях определение статических атрибутов не работает. Так что проверь один раз. - person Vishal Chauhan; 10.06.2016
comment
Не получилось настроить программный режим ввода только программно, мне также пришлось настроить стиль диалога, чтобы он выглядел именно так. Я опубликовал ответ с моим решением. Тем не менее, спасибо за ваше время и за вашу помощь. - person Ionut Negru; 13.06.2016