I am new to Android development. I have a ViewPager which holds TabLayout (that has fixed number of tabs). The ViewPager has SectionPagerAdapter (that has a fragment corresponding to tabs).
Now, I want to update tab content when user selects the tab and as it becomes visible (or when user wants to refresh the content).
But I am not sure which is correct way I can do this.
So far till now I found two solutions:
1) Add listener to TabLayout:
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
{
#Override
public void onTabSelected(TabLayout.Tab tab)
{
mViewPager.setCurrentItem(tab.getPosition());
// Update tab containts here
}
#Override
public void onTabUnselected(TabLayout.Tab tab)
{
}
#Override
public void onTabReselected(TabLayout.Tab tab)
{
}
});
2) Use ViewPager.OnPageChangeListener to get callbacks for when a page fragment (inside Tab) becomes visible:
viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
#Override
public void onPageSelected(int position)
{
// Update tab containts here
}
});
Can someone expert in this please advice me?
The way a viewpager adapter works (with tabs) is that once you add your fragments to the viewpager, then you basically need to add content to your fragments and let the adapter manage which fragment is visible when a given tab is selected.
So, by simply using : OnTabSelectedListenerinterface on your tabLayout, all you need to do is `setCurrentItem(tab.getPosition()); on your viewPager reference (from your layout).
You can have a method like this to add fragments to your viewPagerAdapter:
private void setupViewPager(ViewPager viewPager){
//then create an instance of your ViewPagerAdapter class here
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
//then add fragments for each TAB here
//by calling a method inside your Adapter like this
adapter.addFrag(new FragmentOne(), "TITLE HERE");
adapter.addFrag(new FragmentTwo(), "TITLE TWO");
//Now set your adapter here
viewPager.setAdapter(adapter);
}
Now in your fragments, you can show different content accordingly.
I hope this helps!
Related
I used the tablayout in my project. I have to replace the fragment in the tablayout. The code is like below
Activity Class
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(Fragment1, "One");
adapter.addFragment(Fragment2, "Two ");
adapter.addFragment(Fragment3, "Three");
viewPager.setAdapter(adapter);
}
Interface in Activity
#Override
public void onInput(int input) {
Here how to replace fragment three
}
I think replacing the fragment is not a good idea. So I would like to show you another way to achieve what you want.
viewPager.setCurrentItem(position); you can use this method to change the page. Here position is page-number starting from 0 to total-pages - 1.
Use ViewModal to pass latest data (in your case "input"). So here you can set value from onInput(int input) and in each fragment of ViewPager you can subscribe/ unsubscribe ViewModal to listen changes. In this way you do not need to replace fragment and the page which is on screen will get latest data and can show.
I have a main activity with 3 tabs,when i swipe the tabbed indicator doesn't move but the layout changes while selecting a tab the indicator moves and the layout changes too.
Make sure you have a OnPageChangeListener attached to your ViewPager
mViewPager.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
mTabs.getTabAt(position).select();
}
});
You can also do like
tabLayout.setupWithViewPager(viewPager);
My application is using Tab Layout . I am creating four tabs in MainActivity(This is the activity which gets launched when i open the Application).
Each tab is associated with a fragment using viewpager . Please refer the below code:
TabLayout tabLayout;
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
pagerAdapter = new MainFragmentPagerAdapter(this, getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
// Give the TabLayout the ViewPager
tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager) {
#Override
public void onTabSelected(TabLayout.Tab tab) {
super.onTabSelected(tab);
}});
This is what i am doing in the onCreate method of the MainActivity.
By default the application shows the first tab as the selected tab . But i want to show the 2ndTab as the selected tab every time application is launched fresh.
So for this i am using following code in the onResume method of MainActivity:
tabLayout.getTabAt(1).select(); //position 1 - means second tab , 0 means tab 1
This api selects the 2nd tab properly.
But Problem 1:-
it does not call the onTabSelected method which i have overridden.
Problem 2: Right After calling tab.select, when i try to get the fragment associated with the 2nd tab, it returns null.
#Override
public void onResume() {
tabLayout.getTabAt(1).select();
Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.viewpager + ":" + 1); // position 1 is for 2nd tab.
}
here page is coming as NULL. But if i try to get the page after 2 seconds (using Android Handler postDelayed ). It gives me the proper page value .This is how i get it using handler:
#Override
public void onResume() {
tabLayout.getTabAt(1).select();
handler.postDelayed(getFragment, 2000);
}
private Runnable getFragment = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Fragment page = null;
page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.viewpager + ":" + 1); // position 1 is for 2nd tab
}
};
Now the page value will come proper from the run method.
So how do i resolve problem 1 and is the using handler solution good for second problem.
Hey please check the code below:
TabLayout tabLayout;
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
pagerAdapter = new MainFragmentPagerAdapter(this,getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
// Give the TabLayout the ViewPager
tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
viewPager.setCurrentItem(1);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new
TabLayout.ViewPagerOnTabSelectedListener(viewPager) {
#Override
public void onTabSelected(TabLayout.Tab tab) {
super.onTabSelected(tab);
}});
I am trying to implement a sliding tab layout that and each fragment should only load when the tab is selected instead i get the adjacent fragment loading, I have tried setOffScreenPageLimit(1) as my code shows but still the adjacent fragment gets loaded any assistance please ???
private SlidingTabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
viewPager.setOffscreenPageLimit(1);
tabLayout = (SlidingTabLayout) findViewById(R.id.tabs);
if (tabLayout != null) {
tabLayout.setViewPager(viewPager);
tabLayout.setDistributeEvenly(true);
tabLayout.setSelectedIndicatorColors(R.color.md_amber_600);
}
I can see you have used setOffScreenPageLimit as 1. It means you are loading only 1 extra screen at a time using viewPager, when actually you want to load nothing. It is not possible to set 0 value for setOffScreenPageLimit this method, actually you can set it but it will not work.
So, it is not possible to achieve this using view pager. If you still want to perform such a functionality, you can use FrameLayout and switch between the fragments based on tab selection.
Below is the tab selection code sample:
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
switchToTab(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
I'm using ViewPager in my app and define it in the main Activity. Inside onCreate method I load some number of pages from SharedPreferences and then pass it to PagerAdapter:
#Override
public int getCount() {
return numberOfPages;
}
The problem is that if I would change this number in Preferences (or another Activity) to some other less then page index I viewed before, my app crashes because this index is out of bounds when I return to the activity with this ViewPager. It can be fixed simply by changing active ViewPager's page. Is there any way to do it?
I'm not sure that I fully understand the question, but from the title of your question, I'm guessing that what you're looking for is pager.setCurrentItem( num ). That allows you to programatically switch to another page within the ViewPager.
I'd need to see a stack trace from logcat to be more specific if this is not the problem.
slide to right
viewPager.arrowScroll(View.FOCUS_RIGHT);
slide to left
viewPager.arrowScroll(View.FOCUS_LEFT);
Without checking your code, I think what you are describing is that your pages are out of sync and you have stale data.
You say you are changing the number of pages, then crashing because you are accessing the old set of pages. This sounds to me like you are not calling pageAdapter.notifyDataSetChanged() after changing your data.
When your viewPager is showing page 3 of a set of 10 pages, and you change to a set with only 5, then call notifyDataSetChanged(), what you'll find is you are now viewing page 3 of the new set. If you were previously viewing page 8 of the old set, after putting in the new set and calling notifyDataSetChanged() you will find you are now viewing the last page of the new set without crashing.
If you simply change your current page, you may just be masking the problem.
for switch to another page, try with this code:
viewPager.postDelayed(new Runnable()
{
#Override
public void run()
{
viewPager.setCurrentItem(num, true);
}
}, 100);
Supplemental answer
I was originally having trouble getting a reference to the ViewPager from other class methods because the addOnTabSelectedListener made an anonymous inner class, which in turn required the ViewPager variable to be declared final. The solution was to use a class member variable and not use the anonymous inner class.
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
// don't use an anonymous inner class here
tabLayout.addOnTabSelectedListener(tabListener);
}
TabLayout.OnTabSelectedListener tabListener = new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
};
// The view pager can now be accessed here, too.
public void someMethod() {
viewPager.setCurrentItem(0);
}
}