Получить фрагмент из 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 . Если что-то не получится, вы увидите хороший журнал аварий.


Большое спасибо:) . Через это я обработал его другим способом, который я использую обработчик для публикации фрагмента. Это не очень подходит, но в конце концов решило проблему. Кстати, ты хороший :)
— 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);
        }
    }

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.


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

7

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

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }

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

Я не понимаю здесь, вам нужна ссылка 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;

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;
        }
    }

}

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

0

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

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

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


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;
                    }

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;
}

}

-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.