Подтвердить что ты не робот

Фрагмент обновления ViewPager для салфетки

У меня проблема, с которой я боролся последние 2 дня.

Я создаю приложение, которое использует ActionBar, ViewPager и FragmentPagerAdapter. Код для Activity, Fragments и FragmentPagerAdapter точно соответствует тем, которые указаны в примере андроида на http://developer.android.com/reference/android/support/v4/view/ViewPager.html

Проблема, с которой я сталкиваюсь, - если у меня есть только 2 фрагмента в viewPager. при переключении/прокрутке между ними фрагменты не обновляются. onResume не вызывается, потому что viewPager кэширует минимум 1 фрагмент по обе стороны от отображаемого фрагмента.

Я попытался использовать onTabSelected, чтобы определить, когда выбран фрагмент, а затем запустить метод из этого фрагмента с помощью интерфейса (код ниже).

public void onTabSelected(Tab tab, FragmentTransaction ft) {
    TabInfo tag = (TabInfo)tab.getTag();
    for (int i=0; i<mTabs.size(); i++) {
        if (mTabs.get(i) == tag) {
            mViewPager.setCurrentItem(i);
        }
    }
    ((IStartStop)getItem(tab.getPosition())).Start();
}

Однако, когда используется метод "Пуск", при попытке обновить текстовое окно запускается исключение NullPointerException. Код метода запуска:

public void Start() {
    TextView tv = _view.findViewById(R.id.text);
    tv.setText("test");
}

Исключение выбрано в строке:

TextView tv = _view.findViewById(R.id.text);

Интерфейс IStartStop довольно прост:

public interface IStartStop {
    public void Start();
    public void Stop();
}

Я не хочу использовать notifyDataSetChanged(); с POSITION_NONE, потому что каждый раз, когда я прокручиваю новый фрагмент, для загрузки фрагментов требуется несколько секунд

В это время фрагменты включают только текст, в будущем они будут иметь анимацию, поэтому важно:

1- Выполнять анимацию только при выборе фрагмента, а не при выборе фрагмента рядом с ним (способ ViewPager кэширует и возобновляет фрагменты).

2- Остановите анимацию, когда фрагмент больше не выбран, чтобы избежать потерь ресурсов устройства.

Да, я уже проверил все, что доступно в Интернете, но со мной ничего не работает.

Большое спасибо за вашу помощь!

4b9b3361

Ответ 1

Удивительно, что ViewPager не делает это "изначально" (между прочим). Но не все потеряно.

Сначала вам нужно изменить свои фрагменты, чтобы они запускали анимацию только тогда, когда вы сообщали им, что это нормально, а не когда они создаются. Таким образом, вы можете играть со смещением viewpager (по умолчанию = 3) и предварительно загружать 2-3 фрагмента, но не анимировать.

Второй шаг - создать интерфейс или аналогичный, который определяет, когда "фрагмент стал видимым".

Третий шаг должен состоять в том, чтобы присоединить к вашему viewpager новый OnPageScrollListener.

Далее следует код (в полу-непроверенном коде):

1) Прикрепите слушателя:

mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(final int i, final float v, final int i2) {
            }
            @Override
            public void onPageSelected(final int i) {
                YourFragmentInterface fragment = (YourFragmentInterface) mPagerAdapter.instantiateItem(mViewPager, i);
                if (fragment != null) {
                    fragment.fragmentBecameVisible();
                } 
            }
            @Override
            public void onPageScrollStateChanged(final int i) {
            }
        });

2) Это ваш интерфейс:

public interface YourFragmentInterface {
    void fragmentBecameVisible();
}

3) Измените фрагменты, чтобы они реализовали это:

public class YourLovelyFragment extends Fragment implements YourFragmentInterface {

4) Внедрить интерфейс в фрагменте

@Override
public void fragmentBecameVisible() {
    // You can do your animation here because we are visible! (make sure onViewCreated has been called too and the Layout has been laid. Source for another question but you get the idea.
}

Куда пойти отсюда?

Возможно, вы захотите реализовать метод/прослушиватель, чтобы уведомить "другие" фрагменты, которые они больше не видны (т.е. когда они видны, а другие нет). Но это может не понадобиться.

Ответ 2

Это повлияет на изменения с одной страницы на другую страницу в представлении пейджера.

OnPageChangeListener  pagechangelistener =new OnPageChangeListener() {

                @Override
                public void onPageSelected(int arg0) {
                    Logger.logMessage("Called first");

                    pageAdapter.notifyDataSetChanged();
                    indicator.setCurrentItem(arg0);
                }

                @Override
                public void onPageScrolled(int arg0, float arg1, int arg2) {

                    Logger.logMessage("Called second");

                }

                @Override
                public void onPageScrollStateChanged(int arg0) {

                    Logger.logMessage("Called third");

                }
            };
            myViewPager.setOnPageChangeListener(pagechangelistener);

Используйте это в своем адаптере страницы.

@Override
    public int getItemPosition(Object object) {

        return POSITION_NONE;
    }

Ответ 3

setOnPageChangeListener устарел. Вместо этого вы должны использовать addOnPageChangeListener.

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(final int i, final float v, final int i2) {
        }
        @Override
        public void onPageSelected(final int i) {
            YourFragmentInterface fragment = (YourFragmentInterface) mPagerAdapter.instantiateItem(mViewPager, i);
            if (fragment != null) {
                fragment.fragmentBecameVisible();
            } 
        }
        @Override
        public void onPageScrollStateChanged(final int i) {
        }
    });

Ответ 4

Добавьте этот код, когда вы определяете Viewpager

mViewPager.setOffscreenPageLimit(0);

Он не сохранит никакого представления об фрагментах при переключении на другой фрагмент.. поэтому переключение с фрагмента на другой создаст фрагмент с самого начала и обновит все.