Keyboard hides BottomSheetDialogFragment
17,651
Solution 1
I found the solution for 27 api. So the reason why keyboard hides view even with SOFT_INPUT_ADJUST_RESIZE is that the windowIsFloating is set for Dialogs.
The most convenient way that I found to change this is by creating style:
<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>
And set this in onCreate
method of your BottomSheetDialogFragment
:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogStyle)
}
This is how it looks on my device:
Solution 2
I tried all of answers in this topic but nothing helped. I looked through many sites and found only one solution that working for me.
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
}
Solution 3
You can use the next class:
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;
}
}
Comments
-
alvarlagerlof almost 2 years
There are more fields below the keyboard. This happened when i updated the support library. I know it's Kotlin but it looks almost the same as java. How do I fix this issue?
This is what it looks like:
My code:
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>