Currently, we have implemented the following UI components:
BottomSheetDialogFragment
NestedScrollView
EditText
The current behavior is illustrated in the screenshot below.
As the user types, the height of the BottomSheetDialogFragment
increases. If the user continues to type, the height of the BottomSheetDialogFragment
will expand until it fills the full screen.
However, rather than expanding to full screen, we would like the BottomSheetDialogFragment
to increase in height only up to a certain point, after which it should stop to prevent it from covering the full screen. This desired behavior is shown in the following screenshot. Beyond this point, if the user continues to type, the NestedScrollView
should become scrollable.
Do you have any ideas on how we can achieve this?
Below is our current implementation of the source code.
todo_input_dialog_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<!--
It appears that setting android:fillViewport to either true or false makes no difference
in our case. We are following the approach used in the noteplus project.
-->
<!--
Use NestedScrollView, if our bottom sheet dialog is draggable.
-->
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
<EditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:fontFamily="@font/open_sans_regular"
android:hint="Add a Todo"
android:inputType="textMultiLine"
android:padding="16dp"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp" />
</androidx.core.widget.NestedScrollView>
<!--
If we place the button in bottom sheet, we need to specific app:rippleColor explicitly, to
prevent ripple color from using colorPrimary
-->
<com.google.android.material.button.MaterialButton
android:elevation="4dp"
android:translationZ="4dp"
android:stateListAnimator="@null"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:id="@+id/submit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="56dp"
app:cornerRadius="28dp"
android:gravity="center"
android:layout_gravity="end"
app:backgroundTint="@color/colorAccentLight"
app:rippleColor="#7fffffff"
app:iconTint="@color/primaryTextColorDark"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:icon="@drawable/send_24px" />
</LinearLayout>
TodoInputDialogFragment.kt
class TodoInputDialogFragment : BottomSheetDialogFragment() {
private var _binding: TodoInputDialogFragmentBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private var keyboardVisible = false
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = TodoInputDialogFragmentBinding.inflate(inflater, container, false)
val root: View = binding.root
// /questions/64947700/how-to-adjust-dialog-layout-when-soft-keyboard-appears-using-the-latest-windowin
ViewCompat.setOnApplyWindowInsetsListener(root) { _, insets ->
// /a/63595830/72437
val currKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
if (!currKeyboardVisible && (this.keyboardVisible != currKeyboardVisible)) {
dismiss()
}
this.keyboardVisible = currKeyboardVisible
insets
}
binding.submitButton.setOnClickListener {
submit()
}
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
focusAndShowKeyboard(requireActivity(), binding.editText)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
// /questions/64947700/how-to-adjust-dialog-layout-when-soft-keyboard-appears-using-the-latest-windowin
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
dialog.window?.also {
it.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
}
}
// /questions/46861306/how-to-disable-bottomsheetdialogfragment-dragging
//dialog.setOnShowListener { dialogInterface ->
// val bottomSheet = dialog.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
//
// if (bottomSheet != null) {
// val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from(bottomSheet)
// behavior.isDraggable = false
// }
//}
return dialog
}
override fun getTheme(): Int {
return com.yocto.wetodo.R.style.TodoInputDialogFragmentStyle
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun submit() {
}
}