目前,我们已经实现了以下UI组件:
BottomSheetDialogFragment
NestedScrollView
EditText
当前行为如下面的屏幕截图所示。
随着用户键入,
BottomSheetDialogFragment
的高度会增加。如果用户继续键入,BottomSheetDialogFragment
的高度将扩展直至填满整个屏幕。
但是,我们不希望扩展到全屏,而是希望
BottomSheetDialogFragment
的高度仅增加到某个点,之后它应该停止以防止其覆盖全屏。以下屏幕截图显示了所需的行为。除此之外,如果用户继续键入,NestedScrollView
应变为可滚动。
您对我们如何实现这一目标有什么想法吗?
下面是我们当前的源代码实现。
<?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>
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
// https://stackoverflow.com/questions/64947700/how-to-adjust-dialog-layout-when-soft-keyboard-appears-using-the-latest-windowin
ViewCompat.setOnApplyWindowInsetsListener(root) { _, insets ->
// https://stackoverflow.com/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)
// https://stackoverflow.com/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)
}
}
// https://stackoverflow.com/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() {
}
}
BottomSheetDialogFragment
在内部使用 BottomSheetDialog
。您可以更改其行为,例如:
// TodoInputDialogFragment.kt
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
(dialog as BottomSheetDialog).getBehavior().setMaxHeight(400) // <-- add this
return dialog
}
您可以通过限制
Edittext
的最大行数来实现此目的。当你的 Edittext
充满行数时,它会增加底部粪便的高度,因此行为会填充,就像背景视图被底部粪便看不见一样。通过将 Edittext
更改为下面我提到的 Edittext
的 maxLines属性,将管理
Edittext
的最大高度,因此你的底部粪便永远不会超过某个高度。
<EditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:hint="Add a Todo"
android:maxLines="3"
android:inputType="textMultiLine"
android:padding="16dp"
android:textSize="18sp" />
您可以根据需要管理线路。