Получить фрагмент из ViewPager

248

Я использую ViewPagerвместе с собой FragmentStatePagerAdapterтри разных фрагмента:

  • [Fragment1]
  • [FRAGMENT2]
  • [Fragment3]

Когда я хочу получить Fragment1от ViewPagerв FragmentActivity.

В чем проблема, и как мне это исправить?

Цюнь Цинь
источник

Ответы:

504

Основной ответ основан на имени, сгенерированном фреймворком. Если это когда-либо изменится, то это больше не будет работать.

Как насчет этого решения, переопределения instantiateItem()и destroyItem()вашего Fragment(State)PagerAdapter:

public class MyPagerAdapter extends FragmentStatePagerAdapter {
    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

    public MyPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return ...;
    }

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(...); 
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }
}

Кажется, это работает для меня при работе с фрагментами, которые доступны. Фрагменты, которые еще не были созданы, при вызове возвращают ноль getRegisteredFragment. Но я использовал это главным образом, чтобы получить ток Fragmentиз ViewPager: adapater.getRegisteredFragment(viewPager.getCurrentItem())и это не вернется null.

Я не знаю никаких других недостатков этого решения. Если таковые имеются, я хотел бы знать.

Улицы Бостона
источник
41
Это лучшее решение, которое я могу придумать. Единственным предложением было бы, может быть, завернуть Fragmentв, WeakReferenceчтобы гарантировать, что вы не предотвратите сборку уничтоженного фрагмента? Просто кажется, что это правильно ...
Алекс Локвуд
7
Что произойдет, если MyPagerAdapterне registerdFragmentsбудет потеряно из-за жизненного цикла (то есть поворота) ? Придется ли сохранить файл Activity/ Fragmentusing , а затем обновить его с помощью новой ссылки? MyPagerAdapteronSaveInstanceStateFragmentManager
Стивен Байл
10
Если я не ошибаюсь (и вы должны это проверить), метод getItem не вызывается - как вы знаете - но метод instantiateItem вызывается для каждого фрагмента, который восстанавливается платформой после ротации.
Улицы Бостона
6
Да, я проверил, что getItemне вызывается снова при повороте (для любых уже созданных фрагов), так как FragmentManagerвосстанавливает состояния, которые Fragmentsон держит в пейджере. Если instantiateItemвызывается, когда каждый Fragmentвосстанавливается, то это решение на самом деле является более безопасным и более надежным в будущем, чем мое или принятый ответ. Я подумаю попробовать это сам.
Стивен Байл
6
@ Дори, я не сломаю это. Мое решение не использует результат вызова getItem (). Вместо этого он использует результат, сохраненный из вызова instantiateItem (). И жизненный цикл фрагмента не нарушен, потому что сохраненный фрагмент будет удален из разреженного массива при вызове destroyItem ().
Улицы Бостона
85

Для получения фрагментов из ViewPager есть много ответов здесь и в других связанных с этим темах / блогах. Все, кого я видел, сломаны, и обычно они попадают в один из двух типов, перечисленных ниже. Существуют и другие допустимые решения, если вы хотите получить только текущий фрагмент, как этот другой ответ в этой теме.

При использовании FragmentPagerAdapterсм. Ниже. Если использовать FragmentStatePagerAdapterего стоит посмотреть на это . Захват индексов, которые не являются текущими в FragmentStateAdapter, не так полезен, так как по своей природе они будут полностью снесены, вне поля зрения / вне границ ScScreenLimit.

Несчастные пути

Неправильно: ведите свой собственный внутренний список фрагментов, добавленный к тому, когда FragmentPagerAdapter.getItem()вызывается

  • Обычно используя SparseArrayилиMap
  • Не один из многих примеров, которые я видел, описывает события жизненного цикла, поэтому это решение хрупкое. Как getItemвызывается только в первый раз, когда страница прокручивается (или получается, если ViewPager.setOffscreenPageLimit(x)> 0) в ViewPager, если хостинг Activity/ Fragmentубит или перезапущен, то внутреннее SpaseArrayбудет уничтожено, когда пользовательский FragmentPagerActivity будет воссоздан, но за кулисами ViewPagers внутренние фрагменты будут воссозданы, и getItemбудет НЕ называться любой из индексов, поэтому возможность получить фрагмент из индекса будут потеряны навсегда. Вы можете объяснить это за счет экономии, и восстановление этих ссылок фрагментов с помощью FragmentManager.getFragment()и , putFragmentно это начинает запутаться ИМХО.

Неправильно. Создайте свой собственный идентификатор тега, соответствующий тому, что используется внутри,FragmentPagerAdapter и используйте его для извлечения фрагментов страницы изFragmentManager

  • Это лучше, так как он справляется с проблемой потерянных фрагментов ссылок в первом решении внутреннего массива, но, как справедливо указано в ответах выше и в других местах сети - он чувствует себя хакерским, поскольку его закрытый метод является внутренним по отношению к ViewPagerэтому. изменить в любое время или для любой версии ОС.

Метод, воссозданный для этого решения,

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

СЧАСТЛИВЫЙ ПУТЬ: ViewPager.instantiateItem()

Подход, аналогичный getItem()описанному выше, но не нарушающий жизненный цикл, заключается в том, чтобы подключиться к нему, instantiateItem()а не так, getItem()как первый будет вызываться при каждом создании / обращении к индексу. Смотрите этот ответ

СЧАСТЛИВЫЙ ПУТЬ: Построй свой собственный FragmentViewPager

Создайте свой собственный FragmentViewPagerкласс из источника последней библиотеки поддержки и измените метод, используемый внутри для генерации тегов фрагмента. Вы можете заменить его ниже. Преимущество этого в том, что вы знаете, что создание тега никогда не изменится, и вы не полагаетесь на частный API / метод, который всегда опасен.

/**
 * @param containerViewId the ViewPager this adapter is being supplied to
 * @param id pass in getItemId(position) as this is whats used internally in this class
 * @return the tag used for this pages fragment
 */
public static String makeFragmentName(int containerViewId, long id) {
    return "android:switcher:" + containerViewId + ":" + id;
}

Затем, как говорит документ, когда вы хотите получить фрагмент, используемый для индекса, просто вызовите что-то вроде этого метода (который вы можете поместить в пользовательский FragmentPagerAdapterили подкласс), зная, что результат может быть нулевым, если getItem еще не был вызван для эта страница, т.е. она еще не была создана.

/**
 * @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
 * yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
 * the current positions fragment.
 */
public @Nullable Fragment getFragmentForPosition(int position)
{
    String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    return fragment;
}

Это простое решение, которое решает проблемы в двух других решениях, которые можно найти в Интернете.

Дори
источник
6
Это будет работать, но это требует копирования класса ViewPager в ваш собственный исходный код. Использование 'instantiateItem ()' и 'destroyItem ()' пейджер-адаптера ViewPager будет работать и учитывать жизненные циклы фрагментов (эти 2 метода также вызываются, когда фрагменты создаются из состояния сохраненного экземпляра). Вы правы, что полагаться на вызываемый метод getItem () не очень хорошая идея, а использование закрытых API-интерфейсов - тоже.
Улицы Бостона
+1 Я согласен, что это тоже решение и отредактировал выше. Единственное отличие состоит в том, что вышеприведенное работает в еще одном случае, instantiateItem()когда вы хотите получить доступ к фрагменту, который еще не был посещен после того, как произошло событие жизненного цикла и было посещено до события жизненного цикла. Небольшая разница, которую я знаю, но она привела к незначительной ошибке в моей программе, поэтому я изучаю это.
Дори
Если setOffscreenPageLimit = 1 (по умолчанию), FragmentStatePageAdapter начнет обмениваться фрагментами в памяти и из памяти при доступе к страницам просмотра. При вызове getItem () будет создан новый экземпляр повторно посещенных страниц / фрагментов. При таком повторном посещении, есть ли способ дать системе команду возобновить ранее созданные экземпляры, а не создавать новые?
Карл
если за пределы страницы он должен будет создать новый - но переходя в сохраненное состояние. Если вы хотите сохранить старые, вы можете увеличить лимит страниц
Дори
@ Дори нет getItemId(pos)внутриFragmentStatePagerAdapter
Джемшит Искендеров
70

Добавьте следующие методы в ваш FragmentPagerAdapter:

public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return  mFragmentManager.findFragmentByTag(name);
}

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

getActiveFragment (0) должен работать.

Вот решение, реализованное в ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d . Если что-то не получится, вы увидите хороший журнал аварий.

kzotin
источник
Большое спасибо:) . Через это я обработал его другим способом, который я использую обработчик для публикации фрагмента. Это не очень подходит, но в конце концов решило проблему. Кстати, ты хороший :)
Qun Qin
12
Я использовал этот метод, но я считаю, что он перестал работать, когда я перешел на API 17 (?). Я бы порекомендовал другой метод и предпочел бы, чтобы Google просто опубликовал API для извлечения фрагмента из ViewPager, учитывая его позицию.
gcl1
у меня проблемы с вызовом второго фрагмента, метод создания нового
Василь Вальчев,
2
Так как метод API версии makeFragmentName был изменен на частный статический String makeFragmentName (int viewId, long id) {return "android: switcher:" + viewId + ":" + id; } поэтому метод getActiveFragment теперь должен выглядеть примерно так (используйте getItemId вместо позиции для второго аргумента) public Fragment getActiveFragment (контейнер ViewPager, int position) {String name = makeFragmentName (container.getId (), getItemId (position)); return mFragmentManager.findFragmentByTag (name); }
Евгений Попович
1
Это действительно работает, но это действительно опасно, потому что он ретранслирует внутреннюю реализацию пейджера представления, и если Google изменит реализацию (и они могут), могут случиться плохие вещи. Я действительно надеюсь, что Goole сделает это доступным, чтобы получить живой фрагмент
Shem
38

Еще одно простое решение:

    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }
Mindphaser
источник
1
Это кажется идеальным для моих текущих потребностей фрагмента.
danny117
Если все, что вам нужно сделать, это получить текущий выбранный фрагмент, это все, что вам нужно - метод setPrimaryItem устанавливается для присоединения, а также для каждого обновленного внутреннего набора фрагмента в качестве текущего элемента.
Грэм
1
Это звучит как хорошее решение, но как setPrimaryItem()называется после того, как ViewPager.OnPageChangeListener#onPageSelected() я не могу его использовать :-(
hardysim
21

Я знаю, что у этого есть несколько ответов, но, возможно, это поможет кому-то. Я использовал относительно простое решение, когда мне нужно было получить Fragmentот меня ViewPager. В вашем Activityили Fragmentудерживая ViewPager, вы можете использовать этот код для циклического перебора всего, что Fragmentон содержит.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
    if(viewPagerFragment != null) {
        // Do something with your Fragment
        // Check viewPagerFragment.isResumed() if you intend on interacting with any views.
    }
}
  • Если вы знаете свою позицию Fragmentв ViewPager, вы можете просто позвонить getItem(knownPosition).

  • Если вы не знаете своего положения Fragmentв ViewPager, вы можете попросить своих детей Fragmentsреализовать интерфейс с подобным методом getUniqueId()и использовать его для их дифференциации. Или вы можете перебрать все Fragmentsи проверить тип класса, такой какif(viewPagerFragment instanceof FragmentClassYouWant)

!!! РЕДАКТИРОВАТЬ !!!

Я обнаружил, что он getItemвызывается только тогда, FragmentPagerAdapterкогда каждый Fragmentдолжен быть создан в первый раз , после этого кажется, что Fragmentsони перерабатываются с использованием FragmentManager. Таким образом, многие реализации FragmentPagerAdapterсоздают новые Fragment с getItem. Используя мой метод, описанный выше, это означает, что мы будем создавать новые Fragments каждый раз, когда getItemвызывается при прохождении всех элементов в FragmentPagerAdapter. В связи с этим я нашел лучший подход, используя вместо него FragmentManagerкаждый Fragment(используя принятый ответ). Это более полное решение, и оно хорошо работает для меня.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    String name = makeFragmentName(mViewPager.getId(), i);
    Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
    // OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
    if(viewPagerFragment != null) {

        // Do something with your Fragment
        if (viewPagerFragment.isResumed()) {
            // Interact with any views/data that must be alive
        }
        else {
            // Flag something for update later, when this viewPagerFragment
            // returns to onResume
        }
    }
}

И вам понадобится этот метод.

private static String makeFragmentName(int viewId, int position) {
    return "android:switcher:" + viewId + ":" + position;
}
Стивен Байл
источник
1
Вы просто находите FragmentByTag (), но где мы можем установить TAG с фрагментом ??
VinceStyling
@vince ViewPagerСам устанавливает эти теги. Это решение хрупкое, потому что оно основано на знании «скрытого» соглашения об именах ViewPager. Ответ «Улицы Бостона» - гораздо более комплексное решение, которое я сейчас использую в своем проекте (вместо этого подхода).
Стивен Байл
Это прекрасно работает! Но я удалил условие if (viewPagerFragment.isResumed ()), потому что мне нужно обновить страницы ListFragment, которые находятся за пределами экрана. Затем, когда пользователь возвращается на страницу ListFragment, он обновляется новыми данными.
JDJ
10

Для моего случая ни одно из вышеперечисленных решений не сработало.

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

Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());

Это будет работать только в том случае, если ваши фрагменты в диспетчере соответствуют элементу ViewPager.

Veedka
источник
Это идеальный ответ, чтобы получить старые фрагменты из пейджера представления, когда действие или фрагмент воссоздан.
Смит
7

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

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }
Zar E Ahmer
источник
3

Я обработал это, сначала составив список всех фрагментов ( List<Fragment> fragments;), которые я собирался использовать, затем добавил их в пейджер, упрощая обработку текущего просматриваемого фрагмента.

Так:

@Override
onCreate(){
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);
}

тогда это можно назвать:

public Fragment getFragment(ViewPager pager){   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;
}

так что тогда я мог бы бросить его в операторе if, который работал бы, только если он был на правильном фрагмент

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();
}

но это только мой подход к хаку и слэшу, но он сработал для меня, я использую его, чтобы отменить изменения в отображаемом фрагменте, когда нажата кнопка «Назад».

Рассел Каргилл
источник
1
лучший ответ для меня
Сону Кумар
3

Это основано на ответе Стивена выше. Это вернет фактический экземпляр фрагмента, который уже присоединен к родительскому действию.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) {

            if (viewPagerFragment instanceof FragmentOne){
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null){
                    oneFragment.update(); // your custom method
                }
            } else if (viewPagerFragment instanceof FragmentTwo){
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null){
                    twoFragment.update(); // your custom method
                }
            }
        }
    }
Апельсиновое дерево
источник
2

Я не мог найти простой, чистый способ сделать это. Однако виджет ViewPager - это просто еще одна ViewGroup, в которой хранятся ваши фрагменты. ViewPager имеет эти фрагменты как непосредственные потомки. Таким образом, вы можете просто перебрать их (используя .getChildCount () и .getChildAt ()) и посмотреть, загружен ли в данный момент искомый экземпляр фрагмента в ViewPager и получить ссылку на него. Например, вы можете использовать какое-то статическое поле уникального идентификатора, чтобы различать фрагменты.

Обратите внимание, что ViewPager, возможно, не загрузил искомый фрагмент, так как это виртуализирующий контейнер, такой как ListView.

Жомбор Эрдёди-Надь
источник
1
Спасибо за ваш ответ, я получаю его с помощью adpter.getItem (); Я новичок в программировании Android. Я очень ценю тебя. Теперь я могу получить ListFragment и хочу добавить к нему footerView. Пока я делаю это в своей Деятельности, вывод logcat: «java.lang.IllegalStateException: представление контента еще не создано. Я знаю, почему, но у меня возникают трудности с с этим.
Цюнь Цинь
1
FragmentActivity имеет метод onAttachFragment (), доза эта работа для содержимого фрагмента ViewPager?
Василь Вальчев
2

FragmentPagerAdapter - это фабрика фрагментов. Чтобы найти фрагмент, основанный на его позиции, если он все еще находится в памяти, используйте это:

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

Пример кода для поддержки API v4.

Даниэль Де Леон
источник
Возвращает нуль в onresume (). Есть идеи почему и как это исправить?
Сема
2

Вам не нужно вызывать getItem()или какой-либо другой метод на более позднем этапе, чтобы получить ссылку на Fragmentразмещение внутри ViewPager. Если вы хотите обновить некоторые данные внутри, Fragmentиспользуйте этот подход: динамически обновлять ViewPager?

Ключ заключается в том, чтобы установить новые данные внутри, Adaperи вызов, notifyDataSetChanged()который, в свою очередь, будет вызывать getItemPosition(), передавая вам ссылку Fragmentи давая вам возможность обновить ее. Все остальные способы требуют, чтобы вы сохраняли ссылку на себя или какой-то другой взлом, который не является хорошим решением.

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(xyzData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}
M-WaJeEh
источник
Я не понимаю здесь, вам нужна ссылка Fragment для использования getItemPosition (), так что вы могли бы также не использовать getItemPosition, а?
getItemPosition()это метод в вашем адаптере. Вы не будете звонить прямо. У вас есть ссылка на ваш адаптер, поэтому вы звоните, adapter.notifyDataSetChanged()что, в свою очередь, вызовет getItemPosition()ваш адаптер, передавая ссылку вашего Fragments. Вы можете увидеть полную реализацию в действии здесь stackoverflow.com/questions/19891828/…
M-WaJeEh
Я прочитал это, и я все еще не понимаю. Вам по-прежнему нужна прямая ссылка на эти фрагменты, чтобы звонить против них, верно? Вы упоминаете это как хак, но я не вижу альтернативы; adapter.getItem (i), очевидно, не будет работать.
2
Хорошо, я обновил свой ответ, чтобы уточнить больше. Конечно, для обновления нужна ссылка, Fragmentно вопрос о том, как получить ссылку, спорен. Другие решения получить справку с FragmentManagerпомощью строки аналогична "android:switcher:"+idили возвращения POSITION_NONEиз getItemosition()чего все фрагменты воссоздать себя.
M-WaJeEh
Спасибо, это имеет больше смысла и соответствует моему опыту (так что я, возможно, не делаю что-то не так, ха).
2

Должен распространяться FragmentPagerAdapterна ваш класс адаптера ViewPager.
Если вы используете, FragmentStatePagerAdapterто вы не сможете найти Fragmentего по егоID

public static String makeFragmentName(int viewPagerId, int index) {
  return "android:switcher:" + viewPagerId + ":" + index;
}

Как использовать этот метод: -

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;
mahesh_babariya
источник
2

Эй, я ответил на этот вопрос здесь . В основном вам нужно переопределить

открытый объект instantiateItem (контейнер ViewGroup, позиция int)

метод FragmentStatePagerAdapter.

Уткарш Саксена
источник
1

Лучшее решение - использовать расширение, которое мы создали в CodePath и которое называется SmartFragmentStatePagerAdapter . Следуя этому руководству, это значительно упрощает извлечение фрагментов и текущего выбранного фрагмента из ViewPager. Это также лучше справляется с управлением памятью фрагментов, встроенных в адаптер.

Натан
источник
0

Самый простой и краткий способ. Если все ваши фрагменты ViewPagerотносятся к разным классам, вы можете извлечь и различить их следующим образом:

public class MyActivity extends Activity
{

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) {
            mMyFragment = (MyFragment) fragment;
        }
    }

}
riwnodennyk
источник
Это тоже неправильно, так как есть несколько фрагментов, которые прикрепляются при использовании ViewPager. есть текущий фрагмент страницы, и есть один слева и один справа. Это позволяет пользователю перемещаться между ними без необходимости инициализировать их, только когда пользователь их достигает.
Android-разработчик
0

Я реализовал это легко с немного другим подходом.

Мой пользовательский метод FragmentAdapter.getItem возвратил не новый MyFragment (), а экземпляр MyFragment, созданный в конструкторе FragmentAdapter.

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

lxknvlk
источник
0

Создать целочисленный идентификатор ресурса в /values/integers.xml

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

Затем в функции getItem PagerAdapter:

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

Затем в действии напишите эту функцию, чтобы получить ссылку на фрагмент:

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

Получите ссылку на фрагмент, вызвав вышеупомянутую функцию, а затем приведите ее к вашему пользовательскому фрагменту:

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }
user2574090
источник
0

Простой способ перебирать фрагменты в диспетчере фрагментов. Найдите viewpager с аргументом позиции раздела, размещенный в общедоступном статическом PlaceholderFragment newInstance (int sectionNumber) .

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}
Евгений
источник
0

Во фрагменте

public int getArgument(){
   return mPage;
{
public void update(){

}

В FragmentActivity

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
    if((f instanceof PageFragment)&&(!f.isDetached())){
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    }
}
Марк Журавлев
источник
0

в TabLayout есть несколько вкладок для фрагмента. Вы можете найти фрагмент по тегу, используя индекс фрагмента.

Например индекс для Fragment1 равен 0, поэтому в findFragmentByTag()методе передайте тег для Viewpager.after с помощью фрагмента транзакции, который вы можете добавить, замените фрагмент.

String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);

САМИТ МОНАПАРА
источник
-1

Хорошо для адаптера FragmentStatePagerAdapter я финансирую решение:

в вашей FragmentActivity:

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

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

public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}

в вашем адаптере:

public class MyPagerAdapter extends FragmentStatePagerAdapter {

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}

@Override
public int getCount() {
return this.actionBar.getTabCount();
}

@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}

private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}

}
douarbou
источник
-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

indexэто место фрагмента в адаптере, как вы добавили fragment1вначале, так что получите fragment1проход index0 и так далее для отдыха

Вишну Прасад
источник