如何判断片段在 NavigationDrawer 中何时不可见
How to tell when fragment is not visible in a NavigationDrawer
我试图判断用户何时在我的导航抽屉中选择了不同的片段。我正在尝试使用
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
}
我如何在我的 MainActivity 中切换片段:
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.nav_camera -> {
// Handle the camera action
val fragment: HomeFragment = HomeFragment()
supportFragmentManager.beginTransaction().replace(R.id.content_main, fragment).commit()
}
R.id.nav_manage -> {
val fragment: SettingFragment = SettingFragment()
fragmentManager.beginTransaction().replace(R.id.content_main, fragment).commit()
}
R.id.nav_share -> {
onInviteClicked()
}
R.id.nav_send -> {
val emailIntent: Intent = Intent(android.content.Intent.ACTION_SEND)
emailIntent.type = Constants.FEEDBACK_EMAIL_TYPE
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
arrayOf(Constants.FEEDBACK_EMAIL_ADDRESS))
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
Constants.FEEDBACK_EMAIL_SUBJECT)
startActivity(Intent.createChooser(
emailIntent, Constants.FEEDBACK_TITLE))
}
}
val drawer: DrawerLayout = findViewById(R.id.drawer_layout)
drawer.closeDrawer(GravityCompat.START)
return true
}
然而,这似乎根本没有被调用。例如,在我的 NavigationDrawer
activity 中,它显示片段 A。用户打开导航抽屉并选择片段 B。setUserVisibleHint()
不会在片段 A 中调用,因此我的代码可以知道不再显示。我需要在片段 A 中隔离的代码才能知道它何时未显示,以便它可以在某些变量上调用 .stop() 。这与 activity.
中的 onPause() 用例相同
您可以直接调用
if (myFragment.isVisible()) {...}
或者另一种方式是
public boolean isFragmentUIActive() {
return isAdded() && !isDetached() && !isRemoving();
}
以下是我能想到的一些事情...
- 使用一致的片段,Support 或 Native,而不是两者。而且,有人说支持片段更可取(维护得更好)。
- 确保片段容器未在 XML 中进行硬编码。如果您打算替换一个片段,那么初始片段应该由您的代码动态加载(您通常会使用 id 作为您的 R.id.{frameLayoutId})加载到 FrameLayout 中。
- 使用 Frament 生命周期事件。
onPause
在替换片段时触发,onDetach
也是如此。这会告诉您何时您的旧片段不再可见(或很快就会不可见)。如果它没有触发,那么您的代码中还有另一个问题,可能是片段类型的混合,或者 XML? 中的硬编码片段
- 仅在片段寻呼机中使用
setUserVisibleHint
,或者准备手动设置它。 this 答案对 setUserVisibleHint
的使用有更多的说明。使用寻呼机时,可以一次附加多个片段,因此需要一种额外的方法(有人称之为生命周期事件)来判断片段是否 "really, truly" 可见,因此引入了 setUserVisibleHint
。
奖励:如果适合您的应用程序,请在 replace
之后调用 addToBackStack
使用返回堆栈进行备份。我主要将其添加为人们通常希望在他们的应用程序中添加的附加生命周期项目。代码看起来像这样...
// to initialize your fragment container
supportFragmentManager
.beginTransaction()
.add(R.id.content_fragment, fragment)
.addToBackStack("blank")
.commit()
// to update your fragment container
supportFragmentManager
.beginTransaction()
.replace(R.id.content_fragment, fragment)
.addToBackStack("settings")
.commit()
//in your XML, it can be as simple as adding the FrameLayout below,
// if you start with the Android Studio template for Navigation drawer,
// you can replace the call that includes the "content_main" layout
<!--<include layout="@layout/content_main" /> -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/content_fragment" />
希望对您有所帮助。
我试图判断用户何时在我的导航抽屉中选择了不同的片段。我正在尝试使用
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
}
我如何在我的 MainActivity 中切换片段:
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.nav_camera -> {
// Handle the camera action
val fragment: HomeFragment = HomeFragment()
supportFragmentManager.beginTransaction().replace(R.id.content_main, fragment).commit()
}
R.id.nav_manage -> {
val fragment: SettingFragment = SettingFragment()
fragmentManager.beginTransaction().replace(R.id.content_main, fragment).commit()
}
R.id.nav_share -> {
onInviteClicked()
}
R.id.nav_send -> {
val emailIntent: Intent = Intent(android.content.Intent.ACTION_SEND)
emailIntent.type = Constants.FEEDBACK_EMAIL_TYPE
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
arrayOf(Constants.FEEDBACK_EMAIL_ADDRESS))
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
Constants.FEEDBACK_EMAIL_SUBJECT)
startActivity(Intent.createChooser(
emailIntent, Constants.FEEDBACK_TITLE))
}
}
val drawer: DrawerLayout = findViewById(R.id.drawer_layout)
drawer.closeDrawer(GravityCompat.START)
return true
}
然而,这似乎根本没有被调用。例如,在我的 NavigationDrawer
activity 中,它显示片段 A。用户打开导航抽屉并选择片段 B。setUserVisibleHint()
不会在片段 A 中调用,因此我的代码可以知道不再显示。我需要在片段 A 中隔离的代码才能知道它何时未显示,以便它可以在某些变量上调用 .stop() 。这与 activity.
您可以直接调用
if (myFragment.isVisible()) {...}
或者另一种方式是
public boolean isFragmentUIActive() {
return isAdded() && !isDetached() && !isRemoving();
}
以下是我能想到的一些事情...
- 使用一致的片段,Support 或 Native,而不是两者。而且,有人说支持片段更可取(维护得更好)。
- 确保片段容器未在 XML 中进行硬编码。如果您打算替换一个片段,那么初始片段应该由您的代码动态加载(您通常会使用 id 作为您的 R.id.{frameLayoutId})加载到 FrameLayout 中。
- 使用 Frament 生命周期事件。
onPause
在替换片段时触发,onDetach
也是如此。这会告诉您何时您的旧片段不再可见(或很快就会不可见)。如果它没有触发,那么您的代码中还有另一个问题,可能是片段类型的混合,或者 XML? 中的硬编码片段
- 仅在片段寻呼机中使用
setUserVisibleHint
,或者准备手动设置它。 this 答案对setUserVisibleHint
的使用有更多的说明。使用寻呼机时,可以一次附加多个片段,因此需要一种额外的方法(有人称之为生命周期事件)来判断片段是否 "really, truly" 可见,因此引入了setUserVisibleHint
。 奖励:如果适合您的应用程序,请在
replace
之后调用addToBackStack
使用返回堆栈进行备份。我主要将其添加为人们通常希望在他们的应用程序中添加的附加生命周期项目。代码看起来像这样...// to initialize your fragment container supportFragmentManager .beginTransaction() .add(R.id.content_fragment, fragment) .addToBackStack("blank") .commit() // to update your fragment container supportFragmentManager .beginTransaction() .replace(R.id.content_fragment, fragment) .addToBackStack("settings") .commit() //in your XML, it can be as simple as adding the FrameLayout below, // if you start with the Android Studio template for Navigation drawer, // you can replace the call that includes the "content_main" layout <!--<include layout="@layout/content_main" /> --> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/content_fragment" />
希望对您有所帮助。