Reputation: 1146
I,m using slidingTabLayout with 4 tabs and a viewpager and 4 fragment class for every tab.
i need to reload one of my fragments (first tab) in my project when user click some button, and for this i need to have a tag for that fragment
my question is : how can i set a tag for one of viewpagers fragment???
My MainActivity tab and viewpager codes:
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 ....
Thank you a lot
Upvotes: 27
Views: 28820
Reputation: 875
In case anyone's using FragmentStateAdapter
, the tag is a bit different.
This is the code from FragmentStateAdapter
:
mFragmentManager.beginTransaction()
.add(fragment, "f" + holder.getItemId())
.setMaxLifecycle(fragment, STARTED)
.commitNow();
As you can see it's a combination of static string "f"
and getItemId()
.
After overriding fun getItemId(position: Int): Long
in your adapter, finding a specific fragment should be quite simple to do. For example, override fun
getItemId(position: Int): Long {
return if(position == 0) {
"my_first_fragment"
}else "my_second_fragment"
}
The tag for our first fragment would be "fmy_first_fragment" and found with childFragmentManager.findFragmentByTag("fmy_first_fragment") as? MyFirstFragment
Careful whenever you look for fragment, you have to use the same FragmentManager as was used to create it. So I recommend creating your adapter with FragmentManager
and LifeCycle
as a constructor.
Upvotes: 3
Reputation: 133
Though this question has already been answered. I have another approach for achiving this and this might be better one as the way fragments are tagged in the code are subjected to change. Also to point out using adapter.getItem(position) does not return the instance of fragment being displayed, it will depend on our own implementation of getItem method.
So Basically the problem is that we do not have the instance of Fragments that are present in the viewPager. The idea is to override method
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;
}
of FragmentStatePagerAdapter. If we look at the default implementation of this method, it basically does the job of instantiating new Fragments if they do not exists and returning them. Also it stores them in a list of fragments which is private. So what we can do is Override this method and store the instances on fragments in our own list. This can be implemented in the following way
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;
}
}
Therefore we will have the instances of all the fragments available with us we would no longer need any tags to find the fragment instances being displayed to the user.
Upvotes: 0
Reputation: 4091
There are couple of solution for this.
1). When the FragmentPagerAdapter
adds a Fragment
to the FragmentManager
, it uses a special tag based on the particular position that the Fragment
will be placed. So you can simply get the current visible Fragment
in your ViewPager
using these lines of code
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). You should keep track of all the active fragments in the FragmentStatePagerAdapter
. For demo sample you can refer to second approach here
3). You can make use of EventBus
to post events to your Fragment
from anywhere. All you have to do is to register your Fragment
for that specific event. For official documentation refer this
Upvotes: 33
Reputation: 36049
Here is the method which is used by FragmentPagerAdapter
to create the Fragment
's tag name:
private static String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
viewId
is the id of the ViewPager
.
id
is the position of the fragment inside the ViewPager
.
Example:
String fragmentTag = makeFragmentName(myViewPager.getId(), 2);
Fragment fragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
Upvotes: 11