Как использовать setUserVisibleHint во фрагменте на Android

В моем приложении у меня есть BottomNavBar, и я хочу показывать fragments, когда нажимаю на элементы этого BottomNavBar!
Для набора этого fragments с BottomNavBar я использовал компонент NavigationGraph!

Я хочу использовать метод setUserVisibleHint для одного из этих fragment, но при показе этого 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 14.05.2019 14:51

@EpicPandaForce, почему? Что мы должны использовать вместо этого?

KokoBand 14.05.2019 14:53
FragmentTransaction.setMaxLifecycle
EpicPandaForce 14.05.2019 15:20

@EpicPandaForce, как им пользоваться? можешь прислать мне код? Мне нужна ваша помощь

KokoBand 15.05.2019 06:21
10
4
13 691
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Перед тем, как поставить этот код, вы знаете о жизненном цикле фрагмента.

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

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

спасибо мой друг, это работа для меня. но почему это устарело setUserVisibleHint?

KokoBand 14.05.2019 14:43

НЕТ... это не устарело. он все еще работает .. добро пожаловать ... счастливого кодирования ...

Mayur 14.05.2019 14:51

На самом деле, он скоро станет устаревшим. Следующий выпуск AndroidX Fragment устарел setUserVisibleHint.

EpicPandaForce 14.05.2019 14:53

Теперь это устарело

Yasiru Nayanajith 18.05.2019 09:45

Почему это устарело?! Я дважды прочитал описание setMaxLifeCycle и до сих пор не знаю, как он заменит setUserVisibleHint, который я использую, чтобы скрыть программную клавиатуру и выполнять другие действия (например, запускать анимацию) в ViewPager, когда фрагмент полностью появляется в поле зрения.

fattire 24.05.2019 23:26
 @Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

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

Используйте BottomSheetBehavior https://developer.android.com/reference/android/support/design/widget/BottomSheetBehavior для этого типа реализации. Вы также можете использовать BottomSheetDialogFragment.

Чтобы установить конкретное поведение, используйте этот код, например.

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

Если вы используете Навигация, это может быть не лучший способ добиться желаемого поведения. Навигация имеет интерфейс OnDestinationChangedListener, который получает обратный вызов всякий раз, когда вызывается NavController.getCurrentDestination.

К счастью, вы используете Kotlin, и в HomeActivity вам может сойти с рук что-то вроде:

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

И вы должны получить желаемый результат.

Если вы новичок в навигации, я бы порекомендовал это codelab. Он проходит через некоторые основы и может помочь вам начать работу. Для более продвинутых концепций вы можете проверить NavigationAdvancedSample на Github.

Если вы все равно хотите напрямую использовать фрагменты, вероятно, было бы более надежным использовать методы жизненного цикла (onStart) вместо setUserVisibleHint().

Поскольку 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().

Прямой способ — использовать setMaxLifeCycle с FragmentTransaction при добавлении или переключении фрагмента, где затем

setMaxLifecycle(fragment, Lifecycle.State.STARTED);

эквивалентен

setUserVisibleHint(false);

а также

setMaxLifecycle(fragment, Lifecycle.State.RESUMED);

эквивалентно

setUserVisibleHint(true);

затем снова слушайте с обратным вызовом Fragment onResume()

как при подаче заявки в ViewPager2?

Latief Anwar 22.09.2019 06:37
but instead, onResume() cause now onResume() will be called only for the visible fragment решил мою проблему спасибо
DIRTY DAVE 23.12.2019 14:35

Как насчет обычного onResume, когда я вернулся из фона?

Aman Verma 17.02.2021 14:59
override fun onPrimaryNavigationFragmentChanged(isPrimaryNavigationFragment: Boolean) {
        super.onPrimaryNavigationFragmentChanged(isPrimaryNavigationFragment)
        if (isPrimaryNavigationFragment) {
            // Your fragment is shown
        } else {
            // Your fragment is hidden
        }
    }

Пожалуйста, не просто размещайте код. Добавьте контекст к вашему ответу.

Martin Gal 24.05.2020 12:21

After AndroidX setUserVisibleHint is deprecated as a replacement we can use the setMenuVisibility Method.

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

Другие вопросы по теме