如何在 Android 的 Fragment 中使用 setUserVisibleHint

Posted

技术标签:

【中文标题】如何在 Android 的 Fragment 中使用 setUserVisibleHint【英文标题】:How to use setUserVisibleHint in Fragment on Android 【发布时间】:2019-10-01 11:44:09 【问题描述】:

在我的应用程序中,我有BottomNavBar,我想在单击此BottomNavBar 的项目时显示fragments! 为了设置这个fragmentsBottomNavBar,我使用了NavigationGraph 组件!

我想对这个fragment 之一使用setUserVisibleHint 方法,但是当显示这个fragment 时不要调用setUserVisibleHint

我的活动代码,用于将 fragments 设置为 BottomNavBar 项目:

class HomeActivity : BaseActivity() 
    override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    setupNavigation()

    

        private fun setupNavigation() 
        val navController = Navigation.findNavController(this, R.id.homePage_fragmentNavHost)
        NavigationUI.setupWithNavController(homePage_bottomNavBar, navController)
    

    override fun onSupportNavigateUp() = Navigation.findNavController(this, R.id.homePage_fragmentNavHost).navigateUp()

我的片段代码:

class HomeDashboardFragment : Fragment()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? 
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home_dashboard, container, false)
    

    override fun setUserVisibleHint(isVisibleToUser: Boolean) 
        super.setUserVisibleHint(isVisibleToUser)
        if (isVisibleToUser) 
            Handler().postDelayed( requireContext().toast("Show") , 500)
        
    

为什么不能将setUserVisibleHint 转换为fragment

【问题讨论】:

别担心,setUserVisibleHint 将在下一个 androidX Fragment 版本中被弃用。 @EpicPandaForce 为什么?我们应该用什么来代替这个? FragmentTransaction.setMaxLifecycle @EpicPandaForce,怎么用?你能把代码发给我吗?我需要你的帮助 【参考方案1】:

由于现在不推荐使用 setUserVisibleHint(boolean aBoolean),对于那些仍然想知道片段何时可​​见的人,您仍然可以使用

 public FragmentTransaction setMaxLifecycle(Fragment fragment, Lifecycle.State state)

间接使用 FragmentPagerAdapter(或 FragmentStatePagerAdapter) 只需使用新的构造函数

MyFPagerAdapter(FragmentManager fm) 
        super(fm ,FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
       //...

请注意 FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 允许适配器在内部使用 setMaxLifecycle(通过 setPrimaryItem)而不是 setUserVisibleHint。 因此,在您的片段实现中,您将不再需要使用

setUserVisibleHint(boolean aBoolean)

但相反,onResume() 导致现在 onResume() 将只为可见片段调用。其余的仍然可以到达 onCreateView()。

直接的方法是在添加或切换fragment时使用setMaxLifeCycle和FragmentTransaction,然后

setMaxLifecycle(fragment, Lifecycle.State.STARTED);

等价

setUserVisibleHint(false);

setMaxLifecycle(fragment, Lifecycle.State.RESUMED);

相当于

setUserVisibleHint(true);

然后再次使用 Fragment 的 onResume() 回调进行监听

【讨论】:

如果在ViewPager2中申请呢? but instead, onResume() cause now onResume() will be called only for the visible fragment 解决了我的问题,谢谢 从后台回来后正常的onResume怎么样?【参考方案2】:

在你放这段代码之前你知道片段生命周期

 override fun setUserVisibleHint(isVisibleToUser: Boolean) 
        super.setUserVisibleHint(isVisibleToUser)
        if (isVisibleToUser) 
           // post your code
        
    

    override fun onStart() 
        super.onStart()
        userVisibleHint = true
    

【讨论】:

谢谢我的朋友,这对我有用。但是为什么不推荐使用这个setUserVisibleHint 不...它没有被弃用。它仍在工作......欢迎......快乐编码...... 实际上,它很快就会被弃用。下一个 AndroidX Fragment 版本将弃用 setUserVisibleHint 现在已弃用 为什么不推荐使用它?!我已经阅读了两次 setMaxLifeCycle 的描述,但仍然不知道它将如何替换 setUserVisibleHint——当片段完全进入视图时,我用它来隐藏软键盘并在 ViewPager 中执行其他操作(例如触发动画)。 【参考方案3】:

AndroidX setUserVisibleHint 作为替代品被弃用后 我们可以使用 setMenuVisibility 方法。

  override fun setMenuVisibility(menuVisible: Boolean) 
        super.setMenuVisibility(menuVisible)
  

【讨论】:

【参考方案4】:

使用 BottomSheetBehavior https://developer.android.com/reference/android/support/design/widget/BottomSheetBehavior 进行此类实现。您也可以使用 BottomSheetDialogFragment。

要设置特定行为,请使用此代码,例如

bottomSheetBehavior.setPeekHeight(300);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);

【讨论】:

【参考方案5】:

如果您使用Navigation,这可能不是实现您想要的行为的最佳方式。 Navigation 有一个OnDestinationChangedListener 接口,每当调用NavController.getCurrentDestination 时都会接收回调。

幸运的是,您使用的是 Kotlin,并且在 HomeActivity 中您可能能够摆脱类似的情况:

navController.addOnDestinationChangedListener  _, destination, _ ->
    Handler().postDelayed( requireContext().toast("Show") , 500)

你应该得到想要的结果。

如果您是 Navigation 的新手,我会推荐 this codelab。它介绍了一些基础知识,可以帮助您入门。对于一些更高级的概念,您可以在 Github 上查看NavigationAdvancedSample。

如果您还是想直接使用 Fragments,则使用生命周期方法 (onStart) 可能比 setUserVisibleHint() 更可靠。

【讨论】:

【参考方案6】:
override fun onPrimaryNavigationFragmentChanged(isPrimaryNavigationFragment: Boolean) 
        super.onPrimaryNavigationFragmentChanged(isPrimaryNavigationFragment)
        if (isPrimaryNavigationFragment) 
            // Your fragment is shown
         else 
            // Your fragment is hidden
        
    

【讨论】:

请不要简单地发布代码。为您的答案添加一些上下文。【参考方案7】:
 @Override
public void setUserVisibleHint(boolean isVisibleToUser) 
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser)
        if (NetworkUtils.isConnected(getActivity())) 
            callYourApi();
         
    

【讨论】:

以上是关于如何在 Android 的 Fragment 中使用 setUserVisibleHint的主要内容,如果未能解决你的问题,请参考以下文章

如何在listview android中使文本颜色透明?

如何在android中使位图不可见? [关闭]

Android如何在ListView中使EditText可编辑

如何在android中使LinearLayout中的TextView拖动平滑?

如何在 Android 中使位图加载更快?

如何在Android Studio中使图像中的特定颜色透明?