I am facing one issue regarding tab swipe. My project is built on Android 3.2. I am implementing tab swipe using support library 4.0 (android-support-v4.jar). Everything implemented is working fine but when I deploy my app to an ICS device, then in portrait mode I am getting a spinner in action bar for tab selection. In portrait mode, the tab selection is not changing when swipe is done although content is changing, and everything is working fine in landscape mode.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayHomeAsUpEnabled(true);
// Set up the ViewPager with the sections adapter.
ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
I have tried putting breakpoint actionBar.setSelectedNavigationItem(position); on this line and even on portrait mode it's getting called but the selection is not changing.
Can anybody help with this?
EDITED:
Found a similar problem but don't see exactly how it is solved and how to integrate it in my code.
Problem:
Due to an insufficient real-state the platform uses collapsed navigation (i.e. Spinner). The system auto-determines NAVIGATION_MODE_TABS for landscape & NAVIGATION_MODE_LIST for portrait, changing the orientation from landscape to portrait updates the UI but for some reason does not update the navigation mode property to NAVIGATION_MODE_LIST and hence mActionView.setDropdownSelectedPosition(position) is not called. See the following code of ActionBarImpl : setSelectedNavigationItem
public void setSelectedNavigationItem(int position) {
switch (mActionView.getNavigationMode()) {
case NAVIGATION_MODE_TABS:
selectTab(mTabs.get(position));
break;
case NAVIGATION_MODE_LIST:
mActionView.setDropdownSelectedPosition(position);
break;
default:
throw new IllegalStateException(
"setSelectedNavigationIndex not valid for current navigation mode");
}
}
Workaround solution:
Through reflection we can get the tab spinner object and call setSelection method.
private Spinner getTabSpinner()
{
try
{
int id = getResources().getIdentifier("action_bar", "id", "android");
View actionBarView = findViewById(id);
Class<?> actionBarViewClass = actionBarView.getClass();
Field mTabScrollViewField = actionBarViewClass.getDeclaredField("mTabScrollView");
mTabScrollViewField.setAccessible(true);
Object mTabScrollView = mTabScrollViewField.get(actionBarView);
if (mTabScrollView == null) {
return null;
}
Field mTabSpinnerField = mTabScrollView.getClass().getDeclaredField("mTabSpinner");
mTabSpinnerField.setAccessible(true);
Object mTabSpinner = mTabSpinnerField.get(mTabScrollView);
if (mTabSpinner != null)
{
return (Spinner)mTabSpinner;
}
}
catch (Exception e) {
return null;
}
return null;
}
Then call the above method in onPageSelected event.
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
Spinner spinner = getTabSpinner();
if (spinner != null) {
spinner.setSelection(position);
}
}
Referred this post https://gist.github.com/2657485
Related
I have created 30 scrollable tabs using tablayout.
So first three tabs are visible on screen and rest of them are invisible which can be scroll using swipe gesture.
The problem is when I am selecting last tab programmatically but it is not get visible (tab layout not get scrolled to last tab).
How can I make tablayout to scroll to last tab?
I found the solution.
First I had found the width of tablayout and scroll it's x position to width and than called the select() method of last tab.
And it works fine.
Below is the code.
mTabLayout.setScrollX(mTabLayout.getWidth());
mTabLayout.getTabAt(lastTabIndex).select();
Updated:
If above is not working you can use the below code as well, it is also working fine.
new Handler().postDelayed(
new Runnable() {
#Override public void run() {
mTabLayout.getTabAt(TAB_NUMBER).select();
}
}, 100);
write this method in your custom tablayout (Your own layout which extends tablayout). So, in future you can use this method whenever you need instad of code duplication
public void selectTabAt(int tabIndex) {
if (tabIndex >= 0 && tabIndex < getTabCount() && getSelectedTabPosition() != tabIndex) {
final Tab currentTab = getTabAt(tabIndex);
if (currentTab != null) {
this.post(new Runnable() {
#Override
public void run() {
currentTab.select();
}
});
}
}
}
If you don't want yo use CustomLayout. you can just do this
final Tab currentTab = mTabLayout.getTabAt(tabIndex);
if(currentTab != null){
mTabLayout.post(new Runnable() {
#Override
public void run() {
currentTab.select();
}
});
}
I found this solution for me:
TabLayout tabLayout = activity.getTabLayout();
tabLayout.setSmoothScrollingEnabled(true);
tabLayout.setScrollPosition(targetChannelPosition, 0f, true);
Also, if you receive this error: "Only the original thread that created a view hierarchy can touch its views.", you can use this code, in order to run on Ui thread:
// find a way to get the activity containing the tab layout
TabLayout tabLayout = activity.getTabLayout();
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
TabLayout.Tab tab = tabLayout.getTabAt(targetChannelPosition);
tab.select();
}
});
Are you calling tab.select() before the TabLayout and its children have actually been measured and drawn? If so, your TabLayout won't animate to the selection with tab.select() (or Kayvan N's suggestion of scrollTo()). Using a Handler will probably work, but that's not an ideal solution.
Provided the layout hasn't been laid out yet, a ViewTreeObserver will allow you to move to your selected tab after the layout process is finished.
private void scrollToTabAfterLayout(final int tabIndex) {
if (getView() != null) {
final ViewTreeObserver observer = mTabLayout.getViewTreeObserver();
if (observer.isAlive()) {
observer.dispatchOnGlobalLayout(); // In case a previous call is waiting when this call is made
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
observer.removeOnGlobalLayoutListener(this);
} else {
//noinspection deprecation
observer.removeGlobalOnLayoutListener(this);
}
mTabLayout.getTabAt(tabIndex).select();
}
});
}
}
}
Please comment if you have any suggestions.
The above answer wouldn't work because first As agirardello mentioned you should not use mTabLayout.getWidth() since it doesn't return what we need (which is the position of the child you want to scroll to) and the updated solution doesn't always work because of a bug in TabLayout (reported here) but a work around is simple.
The tabs on the tabLayout are not direct children of the TabLayout so we need to go one level deeper using
((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(YOUR_DESIRED_TAB_INDEX).getRight()
the only child of tabLayout is a TabLayout.SlidingTabStrip which is also a ViewGroup and getRight() will give us the right most position of our desired tab view. Thus scrolling to that position will give us what we desire. Here is a complete code:
int right = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(4).getRight();
mTabLayout.scrollTo(right,0);
mTabLayout.getTabAt(4).select();
NOTE: Make sure you are calling these methods after the layout has been drown (like onResume and not onCreate)
Hope this helps.
new Handler().postDelayed(
new Runnable() {
#Override public void run() {
mTabLayout.getTabAt(TAB_NUMBER).select();
}
}, 100);
The code snippet below works for me
class TriggerOnceListener(private val v: View, private val block: () -> Unit) : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
block()
v.viewTreeObserver.removeOnPreDrawListener(this)
return true
}
}
fun onCreate() {
val position = ***The tab position you want to scroll to, 29 for your case here***
tabLayout.let { it.viewTreeObserver.addOnPreDrawListener(TriggerOnceListener(it)
{ it.setScrollPosition(position, 0f, true) } ) }
}
I dived into Tab.select(), and found Android uses Tablayout.setScrollPosition() to do this scrolling. And in onCreate() the widgets have not been measured, you need to postpone the call until layout is complete.
To select the last tab, use
tabLayout.getTabAt(X).select(); where X is the last tab index
If your TabLayout is used in conjunction with a ViewPager, which is common, simply add the following in the onCreate() method in your Activity:
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout);
That some of your tabs are not being shown indicates the tabMode attribute is set to app:tabMode="scrollable".
viewpager.setItem(position) should also set the position of the tab
This solution worked for me. My situation is a little bit different though; in my case, I am using the TabLayout with a ViewPager and adding more views and calling notifyDataSetChange().
The solution is to set a callback on the observer of TabLayout and scroll when the children are actually added to the TabLayout. Here is my example:
/**
Keep in mind this is how I set my TabLayout up...
PagerAdapter pagerAdapter = new PagerAdapter(...);
ViewPager pager = (ViewPager)findViewById(...);
pager.setAdapter(pagerAdapter);
TabLayout tabLayout = (TabLayout)findViewById(...);
tabLayout.setupWithViewPager(pager);
*/
public void loadTabs(String[] topics) {
animateTabsOpen(); // Irrelevant to solution
// Removes fragments from ViewPager
pagerAdapter.clear();
// Adds new fragments to ViewPager
for (String t : topics)
pagerAdapter.append(t, new TestFragment());
// Since we need observer callback to still animate tabs when we
// scroll, it is essential to keep track of the state. Declare this
// as a global variable
scrollToFirst = true;
// Alerts ViewPager data has been changed
pagerAdapter.notifyOnDataSetChanged();
// Scroll to the beginning (or any position you need) in TabLayout
// using its observer callbacks
tabs.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
/**
We use onGlobalLayout() callback because anytime a tab
is added or removed the TabLayout triggers this; therefore,
we use it to scroll to the desired position we want. In my
case I wanted to scroll to the beginning position, but this
can easily be modified to scroll to any position.
*/
if (scrollToFirst) {
tabs.getTabAt(0).select();
tabs.scrollTo(0, 0);
scrollToFirst = false;
}
}
});
}
Here is my code for the PagerAdapter if you need it too lol:
public class PagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments;
private List<String> titles;
public PagerAdapter(FragmentManager fm) {
super(fm);
this.fragments = new ArrayList<>();
this.titles = new ArrayList<>();
}
/**
* Adds an adapter item (title and fragment) and
* doesn't notify that data has changed.
*
* NOTE: Remember to call notifyDataSetChanged()!
* #param title Fragment title
* #param frag Fragment
* #return This
*/
public PagerAdapter append(String title, Fragment frag) {
this.titles.add(title);
this.fragments.add(frag);
return this;
}
/**
* Clears all adapter items and doesn't notify that data
* has changed.
*
* NOTE: Rememeber to call notifyDataSetChanged()!
* #return This
*/
public PagerAdapter clear() {
this.titles.clear();
this.fragments.clear();
return this;
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public int getItemPosition(Object object) {
int position = fragments.indexOf(object);
return (position >= 0) ? position : POSITION_NONE;
}
}
I wonder if this is answer will be relevant since its coming very late. i actually achieved it in C# using Xamarin.
tabs.GetChildAt(0).Selected = true;
viewPager.SetCurrentItem(0, true);
tab = tabLayout.getSelectedTabPosition();
tab++;
TabLayout.Tab tabs = tabLayout.getTabAt(tab);
if (tabs != null) {
tabs.select();
}
else {
tabLayout.getTabAt(0).select();
}
if you want next tab on click event then use this code its work perfactly
I have an android application that has a single main activity that employs many fragments that switch into view. I'm not sure if that's the right way to do it, but I have inherited this project and would like to avoid doing any major refactors like changing the fragments to all be activities or something like that.
According to the android documentation, it looks like calling the setDisplayHomeAsUp(bool) function should just display the up button by default:
Set whether home should be displayed as an "up" affordance. Set this
to true if selecting "home" returns up by a single level in your UI
rather than back to the top level or front page.
The main issue is that when I use the function:
actionBar.setDisplayHomeAsUpEnabled(true);
It does not set the button that opens the navigation drawer to instead turn into an 'Up' button. It just removes the 'hamburger' ic_drawer icon from the side. The navigation drawer still opens.
Here is the custom code for the NavigationDrawerFragment (I copy+pasted the exact file that you get when you create a new application with a navigation drawer within android studio):
NavigationDrawerFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
mDrawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
});
PopulateAppDrawerList();
return mDrawerListView;
}
public void PopulateAppDrawerList() {
List<AppOption> allApps = getAllApps();
List<AppOption> filteredApps = new ArrayList<AppOption>();
for (int i = 0; i < allApps.size(); i++) {
if (allApps.get(i).getLaunchable()) {
filteredApps.add(allApps.get(i));
}
}
NavDrawerListAdapter adapter = new NavDrawerListAdapter(filteredApps, MainActivity.getInstance());
mDrawerListView.setAdapter(adapter);
mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
}
Then, I have the other fragments that all extend 'BaseAppFragment', which contains the following:
BaseAppFragment.java
public class BaseAppFragment extends Fragment {
#Override
public void onStart() {
super.onStart();
MainActivity.getInstance().onSectionAttached(this);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
} }
This is what allows me to change the title on the action bar in one single area and set whether or not it should have the back button set by default.
MainActivity.java
public void onSectionAttached(android.app.Fragment fragment) {
Class fragmentType = fragment.getClass();
ActionBar actionBar = getActionBar();
mNavigationDrawerFragment.PopulateAppDrawerList();
if (fragmentType != null) {
if (fragmentType.equals(AuthenticationFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(false);
mTitle = "Login";
} else if (fragmentType.equals(MyOptionsFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(false);
mTitle = "My Options";
} else if (fragmentType.equals(GLAuthenticationFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(false);
mTitle = "Login";
} else if (fragmentType.equals(InitialLoginFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(false);
mTitle = "Login";
} else if (fragmentType.equals(LoginFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(false);
mTitle = "Login";
} else if (fragmentType.equals(DailyOverviewFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(true);
mTitle = "Overview";
} else if (fragmentType.equals(SingleComponentFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(true);
SingleComponentFragment singleComponentFragment = (SingleComponentFragment) fragment;
if (singleComponentFragment != null && singleComponentFragment .mComponent != null) {
mTitle = String.format("Back To Day %s", singleComponentFragment.mComponent.getDay() + "");
}
else {
mTitle = "";
}
} else if (fragmentType.equals(singleDayOverviewFragment.class)) {
actionBar.setDisplayHomeAsUpEnabled(true);
mTitle = "Back To Overview";
}
}
actionBar.setTitle(mTitle);
}
The title setting works perfectly and there are no errors when the setDisplayHomeAsUpEnabled(true) is called, but it still shows no Up button. I know that right now I am not setting any type of fragment navigation hierarchy other than the addToBackStack(null) call in the Fragment Transaction, but it still seems like this code should be enough to have the up button replace the navigation drawer button.
The problem is that the navigation drawer icon hijacks the up indicator. In terms of which View in the action bar is displaying the icon, the navigation drawer icon is also the up icon. This is why you need to call actionBar.setDisplayHomeAsUpEnabled(true); for the navigation drawer icon to show.
To fix this, you need to use ActionBarDrawerToggle#setDrawerIndicatorEnabled(false). This will replace the navigation drawer icon with the up icon. From the documentation for this method:
When the indicator is disabled, the ActionBar will revert to displaying the home-as-up indicator provided by the Activity's theme in the android.R.attr.homeAsUpIndicator attribute instead of the animated drawer glyph.
Had the same problem as you, and I struggled getting a consistent Up arrow behaviour. I made this example to show how to properly do it when using a single activity with navigation drawer and multiple levels.
https://github.com/tskulbru/android-navdrawer-up-pattern-example
I have an ActionBar with multiple tabs, each linked to a fragment. The problem I have is that when I use either bar.selectTab(Tab) or bar.setSelectedNavigationItem(int), it doesn't work. Specifically, this problem occurs when the tabs get reduced down to a Spinner in the ActionBar.
There is a known bug with the ActionBar, specifically with the methods mentioned above and specifically when the ActionBar's tabs are reduced to a Spinner.
Here's my workaround. It uses reflection to drill into the ActionBar if the tabs have been reduced to a Spinner. In your Activity class, create a method like so:
/**
* A documented and yet to be fixed bug exists in Android whereby
* if you attempt to set the selected tab of an action bar when the
* bar's tabs have been collapsed into a Spinner due to screen
* real-estate, the spinner item representing the tab may not get
* selected. This bug fix uses reflection to drill into the ActionBar
* and manually select the correct Spinner item
*/
private void select_tab(ActionBar b, int pos) {
try {
//do the normal tab selection in case all tabs are visible
b.setSelectedNavigationItem(pos);
//now use reflection to select the correct Spinner if
// the bar's tabs have been reduced to a Spinner
View action_bar_view = findViewById(getResources().getIdentifier("action_bar", "id", "android"));
Class<?> action_bar_class = action_bar_view.getClass();
Field tab_scroll_view_prop = action_bar_class.getDeclaredField("mTabScrollView");
tab_scroll_view_prop.setAccessible(true);
//get the value of mTabScrollView in our action bar
Object tab_scroll_view = tab_scroll_view_prop.get(action_bar_view);
if (tab_scroll_view == null) return;
Field spinner_prop = tab_scroll_view.getClass().getDeclaredField("mTabSpinner");
spinner_prop.setAccessible(true);
//get the value of mTabSpinner in our scroll view
Object tab_spinner = spinner_prop.get(tab_scroll_view);
if (tab_spinner == null) return;
Method set_selection_method = tab_spinner.getClass().getSuperclass().getDeclaredMethod("setSelection", Integer.TYPE, Boolean.TYPE);
set_selection_method.invoke(tab_spinner, pos, true);
} catch (Exception e) {
e.printStackTrace();
}
}
Example usage of this might be:
private void delete_fragment_and_tab(String fragment_tag) {
//remove the fragment
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(getFragmentManager().findFragmentByTag(fragment_tag));
//now remove the tab from the ActionBar
//and select the previous tab
ActionBar b = getActionBar();
Tab tab = b.getSelectedTab();
bar.removeTab(tab);
select_tab(bar, bar.getNavigationItemCount() -1);
}
I have a screen which uses ViewPager + actionbar Sherlock tabs. I have a setOnPageChangeListener set on the pager and it does the following:
#Override
public void onPageSelected(final int position) {
actionBar.setSelectedNavigationItem(position);
}
This works just fine in portrait mode and even in landscape if I only have few tabs and all the tabs are displayed. However if I add few more tabs in landscape, these collapse into a single drop-down widget. When I page through the ViewPager the setSelectedNavigationItem method is executed but now it has no effect on the drop-down selection: it stays at the last selected value. Which is really bad since user is missing a visual clue: tab may say "One" but user is already on page #6.
Is there a way to programmatically change which tab to display based on the position?
P.S. I know why this happens:
Here's code from com.android.internal.app.ActionBarImpl:
public void setSelectedNavigationItem(int position) {
switch (mActionView.getNavigationMode()) {
case NAVIGATION_MODE_TABS:
selectTab(mTabs.get(position));
break;
case NAVIGATION_MODE_LIST:
mActionView.setDropdownSelectedPosition(position);
break;
default:
throw new IllegalStateException(
"setSelectedNavigationIndex not valid for current navigation mode");
}
}
And when I step through that I can see that the navigation mode is still NAVIGATION_MODE_TABS though tabs are displayed as list. Now - my knee jerk reaction is to put code into onConfigurationChanged to set navigation mode appropriately but shouldn't this happen automatically?
P.P.S. And there's Android bug filed for it already that contains the patch
Base on the Android bug I'm referencing in the question (see P.P.S.) here's workaround that indeed works. Just add it to your pager
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
#Override
public void onPageSelected(int position)
{
actionBar.getTabAt(position).select();
ViewParent root = findViewById(android.R.id.content).getParent();
findAndUpdateSpinner(root, position);
}
/**
* Searches the view hierarchy excluding the content view
* for a possible Spinner in the ActionBar.
*
* #param root The parent of the content view
* #param position The position that should be selected
* #return if the spinner was found and adjusted
*/
private boolean findAndUpdateSpinner(Object root, int position)
{
if (root instanceof android.widget.Spinner)
{
// Found the Spinner
Spinner spinner = (Spinner) root;
spinner.setSelection(position);
return true;
}
else if (root instanceof ViewGroup)
{
ViewGroup group = (ViewGroup) root;
if (group.getId() != android.R.id.content)
{
// Found a container that isn't the container holding our screen layout
for (int i = 0; i < group.getChildCount(); i++)
{
if (findAndUpdateSpinner(group.getChildAt(i), position))
{
// Found and done searching the View tree
return true;
}
}
}
}
// Nothing found
return false;
}
});
You need to add some code in the ActionBarSherlock library project in file ( ActionBarImpl.java ) see this link
I'm using the following example to impliment my viewPager:
http://code.google.com/p/viewpagerexample/issues/list
The problem with this example is that I can't figure out how to set my starting position, the default starting position is 0. Basically I wan't to be able to control if there is an available view on its left or the right.
Is there any way to control center's View current position? is there a better way to do it?
is it possible to make it circular?
I've found a way to set it's position, which is done outside of the class:
awesomePager = (ViewPager) findViewById(R.id.awesomepager);
awesomePager.setAdapter(awesomeAdapter);
awesomePager.setCurrentItem(CurrentPosition);
and it can be limited by calculating the amount of items I want to fit in to it
I have noticed that if you recreate Activity (orientation change) with ViewPager having FragmentStatePagerAdapter, then the Adapter will reuse it's Fragments. The way to stop it is:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
if (viewPager != null) {
// before screen rotation it's better to detach pagerAdapter from the ViewPager, so
// pagerAdapter can remove all old fragments, so they're not reused after rotation.
viewPager.setAdapter(null);
}
super.onSaveInstanceState(savedInstanceState);
}
but then after Activity recreation ViewPager alwayes opens page 0 first and setCurrentItem(CurrentPosition); doesn't work. Fix for that is changing page after delay:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
viewPager.setCurrentItem(newPosition);
}
}, 100);
To start with the last fragment I did this:
PagerAdapter pagerAdapter = new PagerAdapter();
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(pagerAdapter.getCount() - 1);
I came across a problem whereby if I set the current item before I set the adapter, the first item I get back will always be the one at position 0.
Make sure you do:
awesomePager.setAdapter(awesomeAdapter);
awesomePager.setCurrentItem(CurrentPosition);
and not:
awesomePager.setCurrentItem(CurrentPosition);
awesomePager.setAdapter(awesomeAdapter);
I have an array of size more than 1000 and in dymanic viewpager I was facing leftswipe stuck on firstload. The below code solved this and resulted in smooth scroll:
#Override
onResume(){
super.onResume();
viewPager.setCurrentItem(newPosition);
}
I'm using 3 fragments and on starting my app, the second (middle) fragment will be shown by default. Just I'm using the onResume function and all works great.
#Override
protected void onResume() {
super.onResume();
m_viewPager.setCurrentItem(1);
}
Using viewPager.setCurrentItem(newPosition); shows to the user the transition from the starting page to the newPosition, to prevent that from happening and show the newPosition directly as if it was the starting point, I added false to the second parameter something like this:
int newPosition = pages.size()-1; // Get last page position
viewPager.setCurrentItem(newPosition, false); // 2nd parameter (false) stands for "smoothScroll"
I encountered same problem.
When I initialize ViewPager, the indicator position was 0.
This may depends on amount of calculating for Pager contents. I use ViewTreeObserver like below.
mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
mViewPager.setCurrentItem(newPosition);
removeOnGlobalLayoutListener(mSlidingTabLayout.getViewTreeObserver(), mGlobalLayoutListener);
}
};
mSlidingLayout.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
and,
private void removeOnGlobalLayoutListener(ViewTreeObserver observer, ViewTreeObserver.OnGlobalLayoutListener listener) {
if (observer == null) return;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
observer.removeGlobalOnLayoutListener(listener);
} else {
observer.removeOnGlobalLayoutListener(listener);
}
}
In this way, also never to bother with time setting of delay.
#Override
public Object instantiateItem(ViewGroup container, int position) {
View currentPage = null;
switch(position){
case 0:
currentPage = LayoutInflater.from(context).inflate(R.layout.page0, null)
break;
case 1:
currentPage = LayoutInflater.from(context).inflate(R.layout.page1, null)
///////////// This page will be default ////////////////////
((ViewPager)container).setCurrentItem(position);
////////////////////////////////////////////////////////////
break;
case 2:
currentPage = LayoutInflater.from(context).inflate(R.layout.page2, null)
break;
return currentPage;
}