如何在使用导航组件时隐藏片段中的视图
How to hide a view in a fragment while using navigation component
我已经尝试了几乎所有在以下位置找到的答案:
但效果不佳:
我有一个activity:
activity_main.xml
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" >
</androidx.fragment.app.FragmentContainerView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottom_controls"
android:layout_width="match_parent"
android:layout_height="72dp"
android:onClick="onSongInfoClick"
android:background="@drawable/lyt_rounded_bottom_music"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:elevation="25dp"
app:layout_constraintTop_toBottomOf="@id/nav_host_fragment">
因此,在 nav_graph 中,起始目标是一个由各种选项卡组成的 ViewPagerFragment。
现在,我在 ViewPager 中的第一个目的地是 - SongsFragment
当我从 activity_main 单击 bottom_controls 视图时,我正在导航到 SongDetailsFragment 像这样:
MainActivity.kt
//on click song details
fun onSongInfoClick(v: View) {
val navController = findNavController(R.id.nav_host_fragment)
navController.navigateUp() // to clear previous navigation history
navController.navigate(R.id.songDetailsFragment)
}
这是我想要的:
在 SongDetailsFragment 中时:
- 在activity_main
中隐藏bottom_controls
在其他地方时:
- 在activity_main
中显示bottom_controls
现在:这是当前的行为。
第一次用,后来试用就不行了,大家可以看到:
- 我第一次点击 bottom_controls 时,它隐藏在 songDetailsFragment 中(应该如此),但随后它显示在 songDetailsFragment 中。
我是这样的 hiding/showing bottom_control 视图:
在MainActivity.kt
songDetailViewModel.currentData.observe(this) {
if (it.id !in arrayOf(0L, -1L, -2L)) {
if (getCurrentVisibleFragment(this) == null){
viewModel.showMiniPlayer()
} else viewModel.hideMiniPlayer()
} else viewModel.hideMiniPlayer()
}
在SongDetailsFragment.kt
class SongDetailsFragment : BaseSongDetailFragment() {
.....
}
基础SongDetailsFragment.kt
open class BaseSongDetailFragment : Fragment() {
private val songDetailViewModel by sharedViewModel<SongDetailViewModel>()
protected val mainViewModel by inject<MainViewModel>()
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
showHideBottomSheet()
}
override fun onPause() {
showHideBottomSheet()
super.onPause()
}
override fun onResume() {
showHideBottomSheet()
super.onResume()
}
private fun showHideBottomSheet() {
val currentData = songDetailViewModel.currentData.value ?: return
if (currentData.id == 0L) return
if (GeneralUtility.getCurrentVisibleFragment(requireActivity()) == SongDetailsFragment()){
mainViewModel.hideMiniPlayer()
}
else{
mainViewModel.showMiniPlayer()
}
}
}
最后,这是 getCurrentVisibleFragment() 函数
//check if song details fragment
fun getCurrentVisibleFragment(activity: Activity): SongDetailsFragment? {
val navHostFragment = (activity as FragmentActivity).supportFragmentManager.primaryNavigationFragment as NavHostFragment
val fragmentManager: FragmentManager = navHostFragment.childFragmentManager
val songDetailsFragment: Fragment? = fragmentManager.primaryNavigationFragment
return if (songDetailsFragment is SongDetailsFragment) {
songDetailsFragment as SongDetailsFragment
} else null
}
我怀疑这一行:
GeneralUtility.getCurrentVisibleFragment(requireActivity()) == SongDetailsFragment()
在 SongDetailsFragment()
中,您总是会创建片段的新实例,然后将其与当前实例进行比较。如果这种比较在任何情况下都返回真,我会感到惊讶。尝试:
GeneralUtility.getCurrentVisibleFragment(requireActivity()) == this as SongDetailsFragment
我已经尝试了几乎所有在以下位置找到的答案:
但效果不佳:
我有一个activity:
activity_main.xml
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" >
</androidx.fragment.app.FragmentContainerView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottom_controls"
android:layout_width="match_parent"
android:layout_height="72dp"
android:onClick="onSongInfoClick"
android:background="@drawable/lyt_rounded_bottom_music"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:elevation="25dp"
app:layout_constraintTop_toBottomOf="@id/nav_host_fragment">
因此,在 nav_graph 中,起始目标是一个由各种选项卡组成的 ViewPagerFragment。
现在,我在 ViewPager 中的第一个目的地是 - SongsFragment
当我从 activity_main 单击 bottom_controls 视图时,我正在导航到 SongDetailsFragment 像这样:
MainActivity.kt
//on click song details
fun onSongInfoClick(v: View) {
val navController = findNavController(R.id.nav_host_fragment)
navController.navigateUp() // to clear previous navigation history
navController.navigate(R.id.songDetailsFragment)
}
这是我想要的:
在 SongDetailsFragment 中时:
- 在activity_main 中隐藏bottom_controls
在其他地方时:
- 在activity_main 中显示bottom_controls
现在:这是当前的行为。
第一次用,后来试用就不行了,大家可以看到:
- 我第一次点击 bottom_controls 时,它隐藏在 songDetailsFragment 中(应该如此),但随后它显示在 songDetailsFragment 中。
我是这样的 hiding/showing bottom_control 视图:
在MainActivity.kt
songDetailViewModel.currentData.observe(this) {
if (it.id !in arrayOf(0L, -1L, -2L)) {
if (getCurrentVisibleFragment(this) == null){
viewModel.showMiniPlayer()
} else viewModel.hideMiniPlayer()
} else viewModel.hideMiniPlayer()
}
在SongDetailsFragment.kt
class SongDetailsFragment : BaseSongDetailFragment() {
.....
}
基础SongDetailsFragment.kt
open class BaseSongDetailFragment : Fragment() {
private val songDetailViewModel by sharedViewModel<SongDetailViewModel>()
protected val mainViewModel by inject<MainViewModel>()
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
showHideBottomSheet()
}
override fun onPause() {
showHideBottomSheet()
super.onPause()
}
override fun onResume() {
showHideBottomSheet()
super.onResume()
}
private fun showHideBottomSheet() {
val currentData = songDetailViewModel.currentData.value ?: return
if (currentData.id == 0L) return
if (GeneralUtility.getCurrentVisibleFragment(requireActivity()) == SongDetailsFragment()){
mainViewModel.hideMiniPlayer()
}
else{
mainViewModel.showMiniPlayer()
}
}
}
最后,这是 getCurrentVisibleFragment() 函数
//check if song details fragment
fun getCurrentVisibleFragment(activity: Activity): SongDetailsFragment? {
val navHostFragment = (activity as FragmentActivity).supportFragmentManager.primaryNavigationFragment as NavHostFragment
val fragmentManager: FragmentManager = navHostFragment.childFragmentManager
val songDetailsFragment: Fragment? = fragmentManager.primaryNavigationFragment
return if (songDetailsFragment is SongDetailsFragment) {
songDetailsFragment as SongDetailsFragment
} else null
}
我怀疑这一行:
GeneralUtility.getCurrentVisibleFragment(requireActivity()) == SongDetailsFragment()
在 SongDetailsFragment()
中,您总是会创建片段的新实例,然后将其与当前实例进行比较。如果这种比较在任何情况下都返回真,我会感到惊讶。尝试:
GeneralUtility.getCurrentVisibleFragment(requireActivity()) == this as SongDetailsFragment