Как я могу установить тег для фрагментов viewpager?

Я использую slideTabLayout с 4 вкладками и виджетом и 4 фрагментами класса для каждой вкладки.

мне нужно перезагрузить один из моих фрагментов (первая вкладка) в моем проекте, когда пользователь нажимает какую-то кнопку, и для этого мне нужно иметь тег для этого фрагмента

мой вопрос: как я могу установить тег для одного из фрагментов viewpager???

Моя вкладка MainActivity и коды пейджера:

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {



Toolbar toolbar;
ViewPager pager;
ViewPagerAdapter adapter;
SlidingTabLayout tabs;
CharSequence Titles[]={"نوع","قیمت","برند","همه"};
int Numboftabs = 4;




@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);




    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "درج آگهی رایگان", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });



    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);




    // Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
    adapter =  new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs);

    // Assigning ViewPager View and setting the adapter
    pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(adapter);

    // Assiging the Sliding Tab Layout View
    tabs = (SlidingTabLayout) findViewById(R.id.tabs);
    tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width

    // Setting Custom Color for the Scroll bar indicator of the Tab View
    tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
        @Override
        public int getIndicatorColor(int position) {
            return getResources().getColor(R.color.colorWhite);
        }
    });

    // Setting the ViewPager For the SlidingTabsLayout
    tabs.setViewPager(pager);
    pager.setCurrentItem(3);




} and ....

Спасибо большое

4 ответа

Решение

Есть несколько решений для этого.

1). Когда FragmentPagerAdapter добавляет Fragment к FragmentManager, он использует специальный тег, основанный на конкретной позиции, что Fragment будет размещен. Таким образом, вы можете просто получить текущий видимый Fragment в вашем ViewPager используя эти строки кода

 Fragment fragment = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem());
 // based on the current position you can then cast the page to the correct Fragment class and call some method inside that fragment to reload the data:
 if (0 == ViewPager.getCurrentItem() && null != fragment) {
      ((TabFragment1)fragment).reloadFragmentData();     
 } 

2). Вы должны отслеживать все активные фрагменты в FragmentStatePagerAdapter, Для демонстрационного примера вы можете обратиться ко второму подходу здесь

3). Вы можете использовать EventBus отправлять события на ваш Fragment откуда угодно. Все, что вам нужно сделать, это зарегистрировать свой Fragment для этого конкретного события. Для официальной документации обратитесь к этому

Вот метод, который используется FragmentPagerAdapter создать FragmentИмя тега:

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

viewId это идентификатор ViewPager,
id положение фрагмента внутри ViewPager,

Пример:

String fragmentTag = makeFragmentName(myViewPager.getId(), 2);
Fragment fragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);

В случае, если кто-то использует , тег немного отличается. Это код из FragmentStateAdapter:

      mFragmentManager.beginTransaction()
    .add(fragment, "f" + holder.getItemId())
    .setMaxLifecycle(fragment, STARTED)
    .commitNow();

Как видите, это комбинация статической строки "f"а также getItemId(). После переопределения fun getItemId(position: Int): Longв вашем адаптере поиск определенного фрагмента должен быть довольно простым. Например, переопределить веселье

      getItemId(position: Int): Long {
    return if(position == 0) {
            "my_first_fragment"
    }else "my_second_fragment"
}

Тег для нашего первого фрагмента будет "fmy_first_fragment" и будет найден с помощью childFragmentManager.findFragmentByTag("fmy_first_fragment") as? MyFirstFragment

Будьте осторожны всякий раз, когда вы ищете фрагмент, вы должны использовать тот же FragmentManager, который использовался для его создания . Поэтому я рекомендую создать адаптер с помощью FragmentManagerа также LifeCycleкак конструктор.

Хотя на этот вопрос уже был дан ответ. У меня есть другой подход для достижения этого, и это может быть лучше, так как фрагменты тегов в коде подвергаются изменениям. Также отметить, что использование adapter.getItem (position) не возвращает экземпляр отображаемого фрагмента, это будет зависеть от нашей собственной реализации метода getItem.

Таким образом, в основном проблема в том, что у нас нет экземпляра фрагментов, которые присутствуют в viewPager. Идея состоит в том, чтобы переопределить метод

public Object instantiateItem(ViewGroup container, int position) {
    // If we already have this item instantiated, there is nothing
    // to do.  This can happen when we are restoring the entire pager
    // from its saved state, where the fragment manager has already
    // taken care of restoring the fragments we previously had instantiated.
    if (mFragments.size() > position) {
        Fragment f = mFragments.get(position);
        if (f != null) {
            return f;
        }
    }

    if (mCurTransaction == null) {
        mCurTransaction = mFragmentManager.beginTransaction();
    }

    Fragment fragment = getItem(position);
    if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
    if (mSavedState.size() > position) {
        Fragment.SavedState fss = mSavedState.get(position);
        if (fss != null) {
            fragment.setInitialSavedState(fss);
        }
    }
    while (mFragments.size() <= position) {
        mFragments.add(null);
    }
    fragment.setMenuVisibility(false);
    fragment.setUserVisibleHint(false);
    mFragments.set(position, fragment);
    mCurTransaction.add(container.getId(), fragment);

    return fragment;
}

FragmentStatePagerAdapter. Если мы посмотрим на реализацию этого метода по умолчанию, он в основном выполняет работу по созданию новых фрагментов, если они не существуют, и их возвращению. Также он хранит их в списке фрагментов, который является частным. Поэтому мы можем переопределить этот метод и сохранить экземпляры фрагментов в нашем собственном списке. Это может быть реализовано следующим образом

private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {

    private ArrayList<Fragment> fragmentList;

    private final int NUM_PAGES;

    public ScreenSlidePagerAdapter(FragmentManager fm, int numPages) {
        super(fm);
        NUM_PAGES = numPages;
        fragmentList = new ArrayList<>(NUM_PAGES);
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = new CustomFragment();
        //this method can be modified according to the requirement
        return fragment;
    }

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

    public Fragment getFragment(int position){
        return fragmentList.get(position);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position){
        Fragment fragment = (Fragment) super.instantiateItem(container,position);
        if(fragmentList.size()<NUM_PAGES&&!fragmentList.contains(fragment)){
            fragmentList.add(fragment);
        }
        return fragment;
    }
}

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

Другие вопросы по тегам