在嵌套片段中打开键盘时 BottomSheet 中出现超级奇怪的故障
Super Weird Glitch in BottomSheet when open Keyboard in nested Fragment
我的应用程序出现了这个超级奇怪的故障。
当我打开键盘然后膨胀另一个片段时,bottomsheet
片段将滚动直到到达 recyclerview
的顶部隐藏 bottomsheet
视图的顶部。
我有一个带有两个 FragmentContainerView
的 MainFragment。第一个是我在两个片段(NestedFragment_0
和 NestedFragment_1
)之间切换的容器,第二个我用它来填充具有 BottomSheet 的片段。两个片段之间的按钮切换。
只有当 EditText
位于其中一个嵌套片段内并且 BottomSheet 内有 RecyclerView
时才会发生。
项目我已经上传了here如果有人要下载
主要片段布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Switch Nested Fragment"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/bottom_sheet_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
MainFragment 代码:
class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
private lateinit var binding: MainFragmentBinding
private var activeSubFragment: Fragment = Nested0Fragment()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = MainFragmentBinding.inflate(inflater, container, false)
binding.button.setOnClickListener {
activeSubFragment = if (activeSubFragment is Nested0Fragment) {
Nested1Fragment()
} else {
Nested0Fragment()
}
childFragmentManager.beginTransaction()
.replace(R.id.content_container, activeSubFragment).commit()
}
childFragmentManager.beginTransaction().replace(R.id.content_container, activeSubFragment)
.commit()
childFragmentManager.beginTransaction()
.replace(R.id.bottom_sheet_container, BottomSheetFragment.newInstance()).commit()
return binding.root
}
}
BottomSheet 布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_peekHeight="100dp"
android:background="@color/teal_200"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.BottomSheetFragment">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="BottomSheet"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layoutManager="LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
问题与焦点有关,当EditText失去焦点时,系统会将焦点移至RecyclerView,这就是它移动到顶部的原因。在 Fragment 版本 1.4.0 中,它解决了 API 28 及更高版本的问题,对于 API 27 及以下版本,只需在最顶部添加 focusable=true
和 focusableInTouchMode=true
父视图。
我的应用程序出现了这个超级奇怪的故障。
当我打开键盘然后膨胀另一个片段时,bottomsheet
片段将滚动直到到达 recyclerview
的顶部隐藏 bottomsheet
视图的顶部。
我有一个带有两个 FragmentContainerView
的 MainFragment。第一个是我在两个片段(NestedFragment_0
和 NestedFragment_1
)之间切换的容器,第二个我用它来填充具有 BottomSheet 的片段。两个片段之间的按钮切换。
只有当 EditText
位于其中一个嵌套片段内并且 BottomSheet 内有 RecyclerView
时才会发生。
项目我已经上传了here如果有人要下载
主要片段布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Switch Nested Fragment"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/bottom_sheet_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
MainFragment 代码:
class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
private lateinit var binding: MainFragmentBinding
private var activeSubFragment: Fragment = Nested0Fragment()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = MainFragmentBinding.inflate(inflater, container, false)
binding.button.setOnClickListener {
activeSubFragment = if (activeSubFragment is Nested0Fragment) {
Nested1Fragment()
} else {
Nested0Fragment()
}
childFragmentManager.beginTransaction()
.replace(R.id.content_container, activeSubFragment).commit()
}
childFragmentManager.beginTransaction().replace(R.id.content_container, activeSubFragment)
.commit()
childFragmentManager.beginTransaction()
.replace(R.id.bottom_sheet_container, BottomSheetFragment.newInstance()).commit()
return binding.root
}
}
BottomSheet 布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_peekHeight="100dp"
android:background="@color/teal_200"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.BottomSheetFragment">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="BottomSheet"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layoutManager="LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
问题与焦点有关,当EditText失去焦点时,系统会将焦点移至RecyclerView,这就是它移动到顶部的原因。在 Fragment 版本 1.4.0 中,它解决了 API 28 及更高版本的问题,对于 API 27 及以下版本,只需在最顶部添加 focusable=true
和 focusableInTouchMode=true
父视图。