I have a TabLayout with 3 tab.They are a fragment.
Test.java->PagerAdapter.java->TabFragment1+TabFragment2+TabFragment3
I want to call TabFragment1.helloworld() function. How can i call this function? Thanks.
Test.java created 3 tabs in below
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("tab1"));
tabLayout.addTab(tabLayout.newTab().setText("tab2"));
tabLayout.addTab(tabLayout.newTab().setText("tab3"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setOffscreenPageLimit(3);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(),
tabLayout.getTabCount());
viewPager.setAdapter(adapter);
PagerAdapter.java
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabFragment1 tab1 = new TabFragment1();
return tab1;
case 1:
TabFragment2 tab2 = new TabFragment2();
return tab2;
case 2:
TabFragment3 tab3 = new TabFragment3();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
You can access the desired fragment's method through your PagerAdapter:
((TabFragment1)adapter.getItem(0)).helloworld();
It's a bit trickier than usual with ViewPagers, because you can't use the preferred findFragmentByTag() method. Here's something you could try - it's untested, but should be ok:
Create an interface, which all Fragments in your ViewPager implement:
public interface ViewPagerFragmentBase {
void callCommonMethod(int code);
}
Implement it in all your ViewPager Fragments:
public FragmentOne implements ViewPagerFragmentBase {
#Override
public void callCommonMethod(int code) {
if (code == 1) {
//Run code in this Fragment
}
}
public FragmentTwo implements ViewPagerFragmentBase {
#Override
public void callCommonMethod(int code) {
if (code == 2) {
//Run code in this Fragment
}
}
Inside your Activity class, grab all Fragments currently in your Adapter, then cycle through each one, calling the callCommonMethod() along with a code which indicates the Fragment you are trying to reach:
public class MainActivity extends AppCompatActivity {
private void callCommonMethodInFragments(int code) {
for (int i = 0; i < viewPagerAdapter.getCount(); i++) {
((ViewPagerFragmentBase)viewPagerAdapter.getItem(i)).callCommonMethod(code);
}
}
//To call it...
callCommonMethodInFragments(1); //This will run the method in FragmentOne only
}
If the code matches the one in the Fragment you are trying to reach, then the method will run.
Something else you could also try though is an EventBus - this would allow you to achieve your goal more directly, and with less typing: https://github.com/greenrobot/EventBus
To call fragment method from parent activity:
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
fragment.callFunction();
I had the same issue, and this worked for me:
You have to add the fragments via your adapter and then you can access the fragment functions:
myViewPager = (ViewPager) findViewById(R.id.viewpager);
MyAdapterClass adapter = new MyAdapterClass(getSupportFragmentManager());
adapter.addFragment(new TabOneFragment(), "");
adapter.addFragment(new TabTwoFragment(), "");
adapter.addFragment(new TabThreeFragment(), "");
myViewPager.setAdapter(adapter);
myTabLayout = (TabLayout) findViewById(R.id.tab_layout);
myTabLayout.setupWithViewPager(myViewPager);
// to access fragment functions:
TabOneFragment tabOneFragment = (TabOneFragment) adapter.getItem(0);
tabOneFragment.functionWhatSoEver();
Related
Let's say that I have a ViewPager that will have 2 Fragments. From those Fragments, I create a PublishSubject which I would like to subscribe to within the MainActivity. However, the issue is during the onCreate(), I would not be able to grab that specific PublishSubject from the Fragment since it seems like it hasn't been created yet. Therefore, I end up with an NPE if I tried to make a subscription for it.
Is there a way to pass the PublishSubject once the Fragment is created by the ViewPager to the MainActivity? Or should I be trying to do something else instead. I've tried looking through other issues, but I couldn't find anything that is similar with something like this.
Some Code to illustrate what I mean:
Fragment
public class ExampleFragment extends Fragment {
PublishSubject<SomeObject> mPublishSubject = PublishSubject.create();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance){
// Regular fragment stuff here
}
public PublishSubject<SomeObject> getPublishSubject() {
return mPublishSubject;
}
}
ViewPager
public class ExamplePagerAdapter extends FragmentStatePagerAdapter {
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new ExampleFragment();
case 1:
return new SomeOtherFragment();
default:
return null;
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private PublishSubject<SomeObject> mSubjectFromTheFragment;
private ExamplePagerAdapter mPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("tab1"));
tabLayout.addTab(tabLayout.newTab().setText("tab2"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mPagerAdapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
mViewPager.setAdapter(mPagerAdapter);
// Set listener
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
// Code to implement the methods
});
// When or where do I set PublishSubject
mPublishSubject = ?
// The subscription
mPublishSubject.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(/** Some new Action1<> etc. **/ )
}
}
Any help or pointing me to some kind of direction is really appreciated!
I have an activity named: ShoppingListActivity in which i have added 3 fragments. For this example i will use only one fragment. In onCreate method i have declared a ViewPager that looks like this:
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
and a setupViewPager(viewPager); method that looks like this:
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
Fragment shoppingListFragment = new ShoppingListFragment();
getSupportFragmentManager().beginTransaction().add(shoppingListFragment, "ShoppingListFragmentTag").commit();
adapter.addFragment(shoppingListFragment, "SHOPPING LIST");
viewPager.setAdapter(adapter);
}
My ViewPagerAdapter class lookslike this:
private class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> fragmentTitleList = new ArrayList<>();
ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
}
My problem is when i go from ShoppingListActivity to another activity and than come back, my fragments are not refreshed. This is my code from onResume method in which i try to find the fragment to detach and attach the fragment like this:
FragmentManager fragmentManager = getSupportFragmentManager();
ShoppingListFragment shoppingListFragment = (ShoppingListFragment) fragmentManager.findFragmentByTag("ShoppingListFragmentTag");
fragmentManager.beginTransaction().detach(shoppingListFragment).attach(shoppingListFragment).commit();
The problem is that i get this error: java.lang.IllegalStateException: Can't change tag of fragment ShoppingListFragment{528673f4 #0 ShoppingListFragmentTag}: was ShoppingListFragmentTag now android:switcher:2131558559:0
How can i set the Tag correctly to the fragment?
Thanks in advance!
from the code what I understand is, There is a ViewPager implemented in ShoppingListActivity along with tabs.
In viewpager each fragment contains the list of something which come from server right? Now you want to refresh whole viewpager when user back from the ShoppingListInfoActivity right?
Do below changes in you ShoppinglistActivity.
1) Declare ViewPagerAdapter adapter; at class level global.
2)change private class ViewPagerAdapter extends FragmentPagerAdapter
replace FragmentPagerAdapter to FragmentStatePagerAdapter
3) change in onresume()
#Override
protected void onResume() {
super.onResume();
if(adapter!=null){
adapter.notifyDataSetChanged();
}
}
Here i am getting result like...
Activity start..
at at that time these two fragments calls
-> Fragment 1 load
-> Fragment 2 load in background
swapping right (means going from frag 1 to fragment 2)
at that time I am in fragment two and same time
-> Fragment 3 load in background
swapping in right (means going from Frag 2 to 3 then)
--> there is nothing issue.
HERE IS MY CODE
Main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new OneFragment(), "ONE");
adapter.addFragment(new TwoFragment(), "TWO");
adapter.addFragment(new ThreeFragment(), "THREE");
viewPager.setAdapter(adapter);
}
This is my adapter class
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
// add fragment
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
// for title
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
And there is 3 fragment right now there is nothing into that fragment .....
ViewPager setOffscreenPageLimit default is 1
Please view this link
Visit Documentation
Update
Please Override this method of fragment
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// load data here
}else{
// fragment is no longer visible
}
}
Use this tutorial..this may helps you
http://www.androidhive.info/2015/09/android-material-design-working-with-tabs/
you need not include this lines in your onCreate Method (Remove this lines)
viewPager.setCurrentItem(0);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
By default,Viewpager will set '0' for starting index..
Replace your code with this. This runs well on my app :
#Override
protected void onCreate(Bundle savedInstanceState) {
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
assert tabLayout != null;
tabLayout.setupWithViewPager(viewPager);
tabLayout.setSelected(true);
}
And no need to add viewPager.setCurrentItem(0);
Because by default ViewPager will be set to the Starting index of 0. As already told by Ajay Jayendran.
Hope this will works. (:
I'm sorry I am not fluent in English.
I wanna change the starting fragment in tab layout.
There is a value from another activity that gave with intent.
so I just want to start tab layout's fragment with my selection.
This is main activity's onCreate()
public class MainActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
And this is the code of changing in fragment
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(position)
{
case 0:
return new TotalFragment();
case 1:
return new StatsFragment();
case 2:
return new FeedbackFragment();
case 3:
return new ManageFragment();
}
return null;
}
#Override
public int getCount() {
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "TOTAL";
case 1:
return "STATS";
case 2:
return "FEEDBACK";
case 3:
return "MANAGE";
}
return null;
}
}
}
Jisu Lee, we can set the starting tab in tab layout with the help of setCurrentItem() to viewpager.
We can set it by two types :
Example :
1.Simple setting tab:
Explation : Set the currently selected page. If the ViewPager has already been through its first layout with its current adapter there will be a smooth animated transition between the current item and the specified item.
viewPager.setCurrentItem(1);
2.For enableing smoothScroll :
Secand parameter "True" to smoothly scroll to the new item, "false" to transition immediately
viewPager.setCurrentItem(1, true);
Or for getting the CurrentItem we have : viewPager.getCurrentItem();
It will return the starting tab index (int).
mViewPager.setCurrentItem({index you want}, true);
I have activity and 3 fragments. I use PagerSlidingTabStrip for suport tabs. Adapter:
public class MyPagerAdapter extends FragmentStatePagerAdapter {
...
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
}
return null;
}
...
}
Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
final ViewPager pager = (ViewPager) findViewById(R.id.pager);
final MyPagerAdapter pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
pager.setAdapter(pagerAdapter);
pager.setCurrentItem(1);
final int pageMargin = (int) applyDimension(COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics());
pager.setPageMargin(pageMargin);
tabs.setViewPager(pager);
tabs.setOnPageChangeListener(listener);
tabs.setTextColor(Color.rgb(255, 255, 255));
tabs.setIndicatorColor(Color.parseColor("#FF96AA39"));
}
When app is loading first time getItem is executed 3 times. What is correct. First fragment is shown. Then after change roration getItem for first fragment is not executed. But when I switch to secons or third one getItem is executed.
Could you help me why getItem is not called for first fragment when screen orientation was changed?