Клавиатура скрывает BottomSheetDialogFragment

Под клавиатурой есть дополнительные поля. Это произошло, когда я обновил библиотеку поддержки. Я знаю, что это Kotlin, но он выглядит почти так же, как Java. Как решить эту проблему?

Вот как это выглядит:

введите описание изображения здесь

Мой код:

class ProjectsEditBottomSheetFragment(val privateID: String,
                                  val publicID: String) : BottomSheetDialogFragment() {



private val mBottomSheetBehaviorCallback = object : BottomSheetBehavior.BottomSheetCallback() {
    override fun onStateChanged(bottomSheet: View, newState: Int) {
        if (newState == BottomSheetBehavior.STATE_HIDDEN) {
            dismiss()
        }

    }


    override fun onSlide(bottomSheet: View, slideOffset: Float) {
        if (slideOffset < -0.15f) {
            dismiss()
        }
    }
}


override fun setupDialog(dialog: Dialog, style: Int) {
    super.setupDialog(dialog, style)
    val view = View.inflate(context, R.layout.projects_edit_sheet, null)
    dialog.setContentView(view)

    dialog.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)


    val params = (view.parent as View).layoutParams as CoordinatorLayout.LayoutParams
    val behavior = params.behavior

    if (behavior != null && behavior is BottomSheetBehavior<*>) {
        behavior.setBottomSheetCallback(mBottomSheetBehaviorCallback)
    }


    // Get and set values
    val realm = Realm.getDefaultInstance()
    val realmObject = realm.where(ProjectsRealmObject::class.java)
            .equalTo("privateID", privateID)
            .findFirst()




    realm.beginTransaction()
    view.title_input.text = SpannableStringBuilder(realmObject.title)
    view.description_input.text = SpannableStringBuilder(realmObject.description)
    view.public_checkbox.isChecked = realmObject.isPublic
    realm.commitTransaction()


    // Keyboard
    view.title_input.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
        if (hasFocus) {
            (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(view.title_input, InputMethodManager.SHOW_FORCED)
        } else {
            (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(view.title_input.windowToken, 0)
        }
    }

    view.description_input.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
        if (hasFocus) {
            (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).showSoftInput(view.description_input, InputMethodManager.SHOW_FORCED)
        } else {
            (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(view.description_input.windowToken, 0)
        }
    }


    // Click listners
    view.public_layout.setOnClickListener { view.public_checkbox.toggle() }

    view.cancel.setOnClickListener {
        view?.hideKeyboard()
        dismiss()
    }

    view.save.setOnClickListener {
        view?.hideKeyboard()
        // Save to realm
        realm.beginTransaction()
        realmObject.title = if (view.title_input.text.toString() == "") getString(R.string.unnamed) else view.title_input.text.toString()
        realmObject.description = view.description_input.text.toString()
        realmObject.isPublic = view.public_checkbox.isChecked
        realmObject.synced = false
        realmObject.updatedRealm = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()).toString() + ""
        realm.commitTransaction()

        ProjectsSync(context)

        toast("Sparat")

        dismiss()
    }

  }
}

XML:

<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:layout_collapseMode="none"
app:behavior_hideable="false"
app:behavior_peekHeight="100dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
style="@style/Widget.Design.BottomSheet.Modal">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:id="@+id/content">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingRight="16dp"
            android:paddingLeft="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginBottom="8dp">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/edit_info_placeholder_title"
                android:id="@+id/title_input"/>

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingRight="16dp"
            android:paddingLeft="16dp">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/edit_info_placeholder_description"
                android:id="@+id/description_input"/>

        </android.support.design.widget.TextInputLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:clickable="true"
            android:background="@drawable/click"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            android:id="@+id/public_layout">

            <android.support.v7.widget.AppCompatCheckBox
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="12dp"
                android:id="@+id/public_checkbox"
                android:layout_marginRight="8dp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/edit_info_placeholder_is_public"
                android:layout_gravity="center_vertical"
                style="@style/textMedium"/>

        </LinearLayout>


        <!-- Buttons -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="right"
            android:paddingBottom="8dp">

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/edit_info_button_cancel"
                android:id="@+id/cancel"
                style="@style/Widget.AppCompat.Button.Borderless.Colored"/>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/edit_info_button_save"
                android:id="@+id/save"
                style="@style/Widget.AppCompat.Button.Borderless.Colored"/>

        </LinearLayout>

    </LinearLayout>


</FrameLayout>


person alvarlagerlof    schedule 19.06.2017    source источник
comment
Код котлина в порядке. пожалуйста, опубликуйте свой код styles.xml.   -  person 배준모    schedule 19.06.2017
comment
какую версию библиотеки дизайна Android вы используете? Он отлично работает в 25.3.1, но не работает в 25.4.0.   -  person orium    schedule 29.06.2017
comment
какие-нибудь обновления по этому поводу?   -  person orium    schedule 03.08.2017


Ответы (6)


Я нашел решение для 27 API. Таким образом, причина, по которой клавиатура скрывает вид даже с SOFT_INPUT_ADJUST_RESIZE, заключается в том, что для диалогов установлено значение windowIsFloating.

Я нашел самый удобный способ изменить это, создав стиль:

<style name="DialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="android:windowIsFloating">false</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowSoftInputMode">adjustResize</item>
</style>

И установите это в методе onCreate вашего BottomSheetDialogFragment:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogStyle)
}

Вот как это выглядит на моем устройстве:

введите описание изображения здесь

person jblejder    schedule 20.06.2018
comment
Хорошее решение! Также обратите внимание, что важно, чтобы верхний макет был ScrollView, иначе он не работает. - person headsvk; 25.06.2018
comment
@headsvk на самом деле не имеет значения, какой у вас верхний макет. На снимке экрана у меня есть простой ConstraintLayout с EditText и TextView. BottomSheetDialogFragment оборачивает мой макет в необходимый макет. - person jblejder; 27.06.2018
comment
@jblejder Может быть, ваш макет достаточно прост, и он вам не нужен. У меня было больше TextView и кнопок под текстом редактирования, и мне пришлось обернуть ConstraintLayout с помощью ScrollView, иначе он не работал должным образом. - person headsvk; 28.06.2018
comment
Для меня это работало только с android:isScrollContainer="true" в дочернем представлении, которое должно быть прокручиваемым. - person ab.helly; 28.11.2018
comment
android:statusBarColor требует API 21 и зачем он нужен? - person CoolMind; 18.04.2019
comment
это работает, у меня был родительский ConstraintLayout со сложным дизайном, работает только тогда, когда я обернул ConstraintLayout с NestedScrollView (ScrollView не работает) - person Zayid Mohammed; 04.09.2019
comment
@jblejder Я использую Constraint Layout и пробовал ваше решение, но оно не сработало, можете ли вы также добавить свой XML-код? - person Shruti; 29.09.2019
comment
@CoolMind android:statusBarColor не нужен, но без него, с другими настройками по умолчанию, будет видна строка состояния, которая нарушает ощущение BottomSheetDialog. @Shruti Я только что еще раз попробовал свое решение, и, похоже, оно работает нормально даже с ConstraintLayout. Просто убедитесь, что у вас установлены все вертикальные ограничения. - person jblejder; 01.01.2020
comment
Этот ответ может помочь: stackoverflow.com/a/56631966/5064151 - person Muhammad Umair Shafique; 27.08.2020

Я пробовал все ответы в этой теме, но ничего не помогло. Я просмотрел множество сайтов и нашел только одно решение, которое работает для меня.

 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = super.onCreateDialog(savedInstanceState)

    dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
    dialog.setOnShowListener {
        Handler().post {
            val bottomSheet = (dialog as? BottomSheetDialog)?.findViewById<View>(R.id.design_bottom_sheet) as? FrameLayout
            bottomSheet?.let {
                BottomSheetBehavior.from(it).state = BottomSheetBehavior.STATE_EXPANDED
            }
        }
    }

    return dialog
}

Оригинальное решение

person Andrey Liashuk    schedule 16.06.2019
comment
У меня тоже сработало! - person Neckster; 30.03.2020

Вы можете использовать следующий класс:

import android.graphics.Rect; 
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.BottomSheetDialog;
import android.support.design.widget.BottomSheetDialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

public class TestBottomSheetDialog extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View fragmentView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_bottom_sheet, container, false);
        if (getDialog().getWindow() != null) {
           getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        }
        if (getActivity() != null) {
            View decorView = getActivity().getWindow().getDecorView();
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
                Rect displayFrame = new Rect();
                decorView.getWindowVisibleDisplayFrame(displayFrame);
                int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                int heightDifference = height - displayFrame.bottom;
                if (heightDifference != 0) {
                    if (fragmentView.getPaddingBottom() != heightDifference) {
                        fragmentView.setPadding(0, 0, 0, heightDifference);
                    }
                } else {
                    if (fragmentView.getPaddingBottom() != 0) {
                        fragmentView.setPadding(0, 0, 0, 0);
                    }
                }
            });
        }
        getDialog().setOnShowListener(dialog -> {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            View bottomSheetInternal = d.findViewById(android.support.design.R.id.design_bottom_sheet);
            if (bottomSheetInternal == null) return;
             BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
        });
        return fragmentView;
    }
}
person Vitali    schedule 28.02.2019
comment
Вы должны дать некоторые пояснения к вашему ответу - person Mikev; 28.02.2019

Это работает для меня

public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment 
{
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle 
    savedInstanceState) {
View v = inflater.inflate(R.layout.content_dialog_bottom_sheet, container, false);


getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    return v;
 }
person Irfan Raza    schedule 27.02.2018
comment
Может быть. На 27 не проверял. Пожалуйста, выложите свой рабочий код для андроида 27, если найдете - person Irfan Raza; 20.06.2018

Это решение сработало для меня, потратив 5 часов без везения:

Шаг 1:

Добавьте этот код в свой файл styles.xml (находится в папке res\values).

<style name="CustomizedBottomDialogStyle">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:backgroundDimAmount">0.7</item>
    <item name="android:windowIsFloating">false</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowSoftInputMode">adjustResize</item>
    <item name="android:background">@android:color/transparent</item>
</style>

Ключевым моментом здесь является установка android:windowIsFloating -› false, если это true, ваш код не будет работать! Поэтому я использовал android:backgroundDimEnabled и android:backgroundDimAmount, чтобы фон выглядел прозрачным с красивым наложением.

Шаг 2:

Напишите эту функцию, чтобы настроить ее программно (обратите внимание, что это необязательно, вам нужно выполнить оба шага № 1 и № 2):

private fun showDialog() {

    BottomSheetDialog(requireActivity(), R.style.CustomizedBottomDialogStyle).apply {

        window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

        setOnShowListener {
            Handler().post {
                val bottomSheet = findViewById<View>(R.id.design_bottom_sheet) as? FrameLayout
                bottomSheet?.let {
                    BottomSheetBehavior.from(it).state = STATE_EXPANDED
                }
            }
        }

        setContentView(R.layout.dialog_layout)

        // Your code goes here....

        show()
    }
}
person Osama Remlawi    schedule 25.10.2020

добавьте это в свои стили

<style name="DialogStyle">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="colorPrimaryDark">@android:color/transparent</item>
</style>

затем в диалоговом окне вашего нижнего листа onCreate() добавьте

setStyle(DialogFragment.STYLE_NO_FRAME, R.style.DialogStyle);

также не забудьте добавить в диалог метод setupDialog()

dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
person orium    schedule 05.08.2017
comment
Теперь это сработало. Я разместил код отдельно, который работает для меня. Спасибо за ваше предложение, попробуем и это. - person Irfan Raza; 27.02.2018