Вопрос по android, android-viewpager – ViewPager с фрагментами - onPause (), onResume ()?

43

При использовании ViewPager с фрагментами наши методы onPause (), onResume () не вызываются при перемещении между вкладками. Есть ли какой-нибудь способ, которым мы можем выяснить фрагмент, когда нас делают видимыми или скрытыми?

К сожалению, у меня есть логика в onResume (), onPause (), например, регистрация в службах определения местоположения, которые никогда не останавливаются при переключении вкладок, потому что onPause () никогда не вызывается до тех пор, пока не выйдет все приложение.

Спасибо

Хорошее простое решение:stackoverflow.com/a/35450575/2162226 .. объясняет, как переопределить фрагмент:public void setUserVisibleHint(boolean isVisibleToUser) знать, является ли «текущим» вкладка показывает Gene Bo

Ваш Ответ

6   ответов
10

что предыдущие решения не очень понятны, вот как я решил это благодаря 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.

РЕДАКТИРОВАТЬ: заменить UserVisibleHint частным флагом. Работал намного лучше!

Это не ошибка ОС. Это означает, чтоFragment все еще в памяти.ViewPager сохранит в памяти как минимум 2Fragments сделать его пейджинговый характер. Посмотри на этоanswer Больше подробностей.
Правильным решением было бы выполнить логику в OnPageChangeListener. onPause и onResume предназначены для случаев, когда действие перемещается в фоновый режим и выходит из него, а не для изменений видимости.
Следовательно, я также сказал «поведение». Обратите внимание, что ваш комментарий или ссылка, которую вы предоставляете, добавляют к обсуждению. Проблема в том, что нужен способ узнать, когда фрагмент показан / скрыт, что я реализовал более или менее таким образом, за исключением того, что я вызываю некоторые частные методы onVisible и onHidden. Если вы знаете лучшее решение, почему бы не написать свое собственное? Только 2 ответа на этот вопрос более или менее одинаковы.
Конечно, это не хорошее решение, но в настоящий момент нет другого способа обойти эту операционную систему "ошибка". или поведение. Почему фрагменты имеют onResume () onPause (), но он никогда не вызывается?
Прямой вызов методов жизненного цикла никогда не является хорошим решением
2

Fragment

public void setUserVisibleHint(boolean isVisibleToUser){

}

когдаisVisibleToUser == trueфрагмент показан

0

savepopulationответ:

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) {

        }
    });
0

но в моем текущем приложении я установил OffScreenPageLimit на 1 для моего окна просмотра, это означает, что фрагменты не кэшируются, и каждый раз, когда представление меняется, он перезагружает текущий фрагмент

https://developer.android.com/reference/android/support/v4/view/ViewPager.html#getOffscreenPageLimit ()

17

OnPageChangeListener интерфейс. Установив некоторые флаги для предыдущих и отображаемых в данный момент страниц, вы можете эмулировать это поведение.

Извини, приятель, меня не было в городе. Рад, что кто-то прошел!
Я полагаю, что во время обратного вызова OnPageChange () вы могли бы установить UserVisiblityHint в true для нового выбранного фрагмента и в false на старом фрагменте. Затем вызывая их соответствующие методы onResume () и onPause (). Подсказка видимости пользователя затем должна быть проверена в onResume (), чтобы гарантировать, что вызов сделан во время onPageChange вместо стандартного all во время создания фрагмента. Есть ли реальный флаг для восстановления задокументированного поведения?
Не могли бы вы дать немного больше информации?
3

Solution 1:

ОпределитьSparseArray в вашемViewPagers& APOS; адаптеры, как показано ниже. В этом массиве мы будем хранить экземпляр фрагментов.

SparseArray<Fragment> registeredFragments = new SparseArray<>();

А такжеOverride ваши адаптеры & apos;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. Here's an example about how you can implement a viewpager's 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();

Solution 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));

Edit: Несколько лет назад, когда я искал решение для получения текущего элемента ViewPager, который я пробовалUserVisibleHint вFragments и заметил, что это не надежно. Я не уверен, надежно ли это сейчас или нет, но все же я избегаю использовать.

Похожие вопросы