Ответ 1
ViewPager поставляется с интерфейсом OnPageChangeListener
. Установив несколько флагов для предыдущих и текущих страниц, вы можете эмулировать это поведение.
При использовании ViewPager с фрагментами наши методы onPause(), onResume() не вызывается при перемещении между вкладками. Есть ли способ, который мы можем найти во фрагменте, когда мы становимся видимыми или скрытыми?
К сожалению, у меня есть логика в onResume(), onPause(), например, регистрация с помощью служб определения местоположения, которые никогда не останавливаются при переключении вкладок, потому что onPause() никогда не вызывается, пока не выйдет из всего приложения.
Спасибо
ViewPager поставляется с интерфейсом OnPageChangeListener
. Установив несколько флагов для предыдущих и текущих страниц, вы можете эмулировать это поведение.
Учитывая предыдущие решения, не совсем понятно, вот как я решил это благодаря Phix для его намека:
В обратном вызове OnPageChange():
Fragment old_fragment = getActiveFragment(old_position);
Fragment new_fragment = getActiveFragment(new_position);
old_f.setUserVisibleHint(false);
old_f.onPause();
new_f.setUserVisibleHint(true);
new_f.onResume();
Затем в onResume():
if (getUserVisibleHint())
/* resume code */
и в onPause():
if (!getUserVisibleHint())
/* pause code */
Вот код getActiveFragment, также избегая его поиска:
return fragmentManager.findFragmentByTag("android:switcher:" + viewPagerId + ":" + position);
NB: Фрагмент имеет метод isVisible(), но он не кажется очень последовательным, поэтому использование UserVisibleHint.
EDIT: замените UserVisibleHint на частный флаг. Работала намного лучше!
Если вы используете библиотеку поддержки Android (версия 11), вы можете использовать getUserVisibleHint() или переопределить setUserVisibleHint() для захвата видимых и скрытых изменений. Посмотрите этот пост.
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// do something when visible.
}
}
Решение 1:
Определите SparseArray
в ваших адаптерах ViewPagers
, как показано ниже. В этом массиве мы будем содержать экземпляр фрагментов.
SparseArray<Fragment> registeredFragments = new SparseArray<>();
И Override
ваш метод адаптеров instantiateItem
.
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
Также Override
destroyItem
метод вашего ViewPagers
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
И определите новый метод для получения экземпляра ViewPager
Fragments
.
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
Теперь вы можете реализовать свою логику с помощью ViewPager's
OnPageChangeListener
.
Вот пример того, как вы можете реализовать viewpager OnPageChangeListener
:
Определите целое число, чтобы сохранить текущую позицию:
int currentPos;
yourViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Empty method
}
@Override
public void onPageSelected(int position) {
// This is paused fragment.
final Fragment pausedFragment = yourAdapter.getRegisteredFragment(currentPos);
// update current position value
currentPos = position;
// This is resumed fragment
final Fragment resumedFragment = yourAdapter.getRegisteredFragment(currentPos);
}
@Override
public void onPageScrollStateChanged(int state) {
// Empty method
}
});
Наконец, для восстановления состояния экземпляра обновите текущую позицию, чтобы обновлять, в какой позиции пользователь оставил ViewPager
currentPos = yourViewPager.getCurrentItem();
Решение 2:
Для другого решения вы можете найти ViewPager
Fragments
на Tag
. Вы можете создать свой тег с помощью:
@NonNull
public static String generateViewPagerFragmentTag(int viewPagerId, int position) {
final StringBuilder tagBuilder = new StringBuilder();
tagBuilder.append("android:switcher:");
tagBuilder.append(viewPagerId);
tagBuilder.append(":");
tagBuilder.append(position);
return tagBuilder.toString();
}
И найдите свой Fragment
:
final Fragment yourFragment = getSupportFragmentManager().findFragmentByTag(generateViewPagerFragmentTag(R.id.your_viewpager, currentPos));
Изменить: Несколько лет назад, когда я искал решение для получения текущего элемента ViewPager, я попробовал UserVisibleHint
в Fragments
и заметил, что он не является надежным. Я не уверен, что он надежный или нет, но все же я избегаю использования.
Вы можете использовать метод ниже в Fragment
public void setUserVisibleHint(boolean isVisibleToUser){
}
когда isVisibleToUser == true
, фрагмент показан
Немного поздно для вечеринки, но в моем текущем приложении я установил OffScreenPageLimit в 1 для моего viewpager, это означает, что фрагменты не кэшируются, и каждый раз, когда представление меняет его, он перезагружает текущий фрагмент
Чтобы дать немного больше определения методам в savepopulation answer:
yourPager.setOnPageChangeListener(new GridViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int row, int column, float rowOffset, float columnOffset, int rowOffsetPixels, int columnOffsetPixels) {
}
@Override
public void onPageSelected(int row, int column) {
// When on page selected if position is not specific for you
// you can find your fragment or you can switch position.
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
После некоторых исследований я нашел идеальное решение для этого.
когда вы инициализируете свой адаптер, сделайте это так: -
import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT;
//(i am using androidx but if you have not yet migrated yet you can use appcompat)
adapter = new FeedTabsPagerAdapter(getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
После добавления этой строки вы будете получать обратные вызовы onResume() и onPause. Пожалуйста, отметьте это правильное решение, если эта проблема решена моим кодом.