ViewPager finish on last fragment scroll - android

I have created default activity provided by eclipse with 3 Tabs and ViewPager. My question is, how can I make ViewPager, if I scroll on the 3rd Tab to the right (that would mean on the 4th Tab), to close the activity ?

What if you added a transparent / Thank You / Credits / whatever 4th tab and then did something like:
mViewPager.setOnPageChangeListener(this);
which would then allow you to do something like:
#Override
public void onPageSelected(int position) {
if(position >= mPagerAdapter.getCount()-1)
finish();
}

You can try this:
ViewPager Tab;
Tab = (ViewPager)findViewById(R.id.pager);
Tab.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
if(position==4)
{
finish();
}
}
});
Tab.setAdapter(TabAdapter);

Related

Difference between these 2 swiping tabs implementations?

I have a working code for having 3 tabs, with 3 fragments that you can either horizontally swipe between to change, or you can click on the tab to go to the requested fragment.
However, I wanted to do some tweaks to my design, and I went over to the Android Developer's website: Creating swipe views with tabs
, and it looks completely different than mine. Now I wonder if I should use the code in the developer's website, or keep my own.
Right now I am using ViewPager + TabLayout.
So simple, yet working.
This also makes me wonder, how come this simple code works, but in the official documentation there's a long story. It just makes me think that if I keep my code in the current design, I might encounter some big problems in the future.
Or - if it works - then it works?
MainActivity.java:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find the view pager that will allow the user to swipe between fragments
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
// Create an adapter that knows which fragment should be shown on each page
TabsAdapter adapter = new TabsAdapter(this, getSupportFragmentManager());
// Set the adapter onto the view pager
viewPager.setAdapter(adapter);
// Find the tab layout that shows the tabs
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
// Connect the tab layout with the view pager. This will
// 1. Update the tab layout when the view pager is swiped
// 2. Update the view pager when a tab is selected
// 3. Set the tab layout's tab names with the view pager's adapter's titles
// by calling onPageTitle()
tabLayout.setupWithViewPager(viewPager);
}
}
TabsAdapter.java:
public class TabsAdapter extends FragmentPagerAdapter {
/** Context of the app */
private Context mContext;
public TabsAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
/**
* Return the {#link Fragment} that should be displayed for the given page number.
*/
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new NbFragment();
} else if (position == 1) {
return new LksFragment();
} else {
return new ChtFragment();
}
}
/**
* Return the total number of pages.
*/
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return mContext.getString(R.string.category_nb);
} else if (position == 1) {
return mContext.getString(R.string.category_lks);
} else {
return mContext.getString(R.string.category_cht);
}
}
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/primary_color"
android:orientation="vertical"
tools:context="com.example.barebones.barebones.MainActivity">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
style="#style/CategoryTab"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
And you can see it is completely different than the one on their website. How could it be? I would love to get some clarification, because as a beginner, I feel lost in this sea of information. Which method should I use in order to have swiping tabs that represent different fragments?
I'm lost what you're trying to solve here. Are you perhaps trying to make it so that when you swipe horizontally, respectively changing fragments, your tab layout is updated as well? If so. I have a snippet down below, which you may have to adjust based on your variable names.
protected void initializeNavigationTransition() {
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
tabs_bottom_nav.getTabAt(i).select();
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
tabs_bottom_nav.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
updateTabIconOnSelect(current_tab, tab.getPosition());
current_tab = tab.getPosition();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
I'll have an additional note that it is possible for fragments to refresh, meaning it will be reinitialized, which might be something you do not want, especially if you're displaying data unto these fragments, which you are fetching from your API or over the network, after swiping a couple of times to different fragments if you have probably at least 4 fragments within the view pager. Hence you would need to prevent the view pager from refreshing the fragments by using the code below
viewPager.setOffscreenPageLimit(4); // 4 is the number of fragments within your view pager
viewPager.setAdapter(sectionsPagerAdapter);
I believe the cause of fragments refreshing is caused by the viewpager trying to save memory

tab indicator not moving when swiping but moves on selection

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);

Android: Updating tab content

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!

Changing viewPager swipe direction

I'm using TabLayout and viewPager with an option to swipe the viewPager to the left or right in order to navigate between pages.
My problem is, that my application is RTL based (right-to-left) and the swipe direction is reversed.
I'm trying to change the swipe direction from the default to the reversed version.
I've been searching alot on the web and couldn't find a way how to do it.
I'm using android.support.v4.view.ViewPager;
and this is how I initialize my TabLayout with the viewPager:
// View Page Adapter
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
//View Page Adapter Configuration
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
viewPager.setOffscreenPageLimit(3);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
Summary: Currently, When I'm swiping the viewPager to the left, it shows the next page.
in RTL, when you swipe the viewPager to the right, it shows the next page.
It might be hard to understand, but here it is.
Swiping right shows the next page
while I need swiping right to show the previous page.
It is the very simple techniqe to change the swipe direction of the Viewpager.
There are two simple step which have to follow you,
1. Change the rotation of the View pager,
viewpager.setRotationY(180);
2. Then again change the direction of the each item view in adapter,
itemView.setRotationY(180);
This is 100% worked for me.
I faced the same problem month ago but I think I found a great solution.
Change your TabLayout direction to ltr in xml:
<android.support.design.widget.TabLayout
android:id="#+id/tl_activity_main"
android:layout_below="#id/toolbar_activity_main"
android:layoutDirection="ltr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/DisionTabLayout" />
Create custom adapter for ViewPager and override methods getItem(int position) and getPageTitle(int position):
#Override
public Fragment getItem(int position) {
if (mIsRtlOrientation && mTabs != null && mTabs.length > 0) {
return mTabs[mTabs.length - position - 1].getFragment();
} else {
return mTabs[position].getFragment();
}
}
#Override
public int getCount() {
return mTabs.length;
}
#Override
public CharSequence getPageTitle(int position) {
if (mIsRtlOrientation && mTabs != null && mTabs.length > 0) {
return mTabs[mTabs.length - position - 1].getTitle();
} else {
return mTabs[position].getTitle();
}
}
Set the adapter to ViewPager and then apply this ViewPager to TabLayout.
private void setAdapters() {
// initialize adapter
mTabsAdapter = new TabsAdapter(getSupportFragmentManager(), mTabs, true);
// set adapter to ViewPager
vp.setAdapter(mTabsAdapter);
// set ViewPager to TabLayout
tl.setupWithViewPager(vp);
// if RTL orientation, go to last item
vp.setCurrentItem(vp.getAdapter().getCount() - 1, false);
}
i know it's late but this is a smart question. as #CommonsWare said it's the matter of reversing the order of items in getItem() method in page adapter. but this isn't enought. as you reverse the order in getitem() method you should also NOT reverse the order in getPageTitle() method. something like this:
public static class AppSectionsPagerAdapter extends FragmentStatePagerAdapter {
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new page1();
case 1:
return new page2();
case 2:
return new page3();
}
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "page 3 title";
case 1:
return "page 2 title";
case 2:
return "page 1 title";
}
}
#Override
public int getCount() {
return 3;
}
}
now comes the tricky part. you should use this simple method which converts zero based index order reversed using max index and current index.
public int calculateReverse(int maxIndex,int currentIndex){
return maxIndex-currentIndex;
}
than you should use this method in onTabSelected() like this: be aware you should use your own max index:
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(calculateReverse(2,tab.getPosition()));
}
the second part is to change page listener on page adapter. once again you should use your own max index number:
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(calculateReverse(2,position)); // reversing the tab selection
}
});
i tried to be as descriptive as i can. hope this helps :)
If you are using viewpager2 with fragments. you can use.
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/pager"
android:layout_width="0dp"
android:layout_height="0dp"
**android:orientation="vertical"**
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
I hope this helps somebody.
Yout can use ViewPager2, It support right to left direction. to make it possible:
Add android:supportsRtl="true" in app Manifest
Make viewpager2's parent viewgroup layout direction ltr (android:layoutDirection="ltr")
Now set viewpager2's layoutDirection ltr (android:layoutDirection="rtl")
also set adapter's layout to layoutDirection ltr (android:layoutDirection="ltr")
So I found that the easiest way for this to work for ViewPager (1)
is just to invert the array of items, and then before displaying set the current item of the pager at [array size] position.

One Fragment with multi inner fragments for many tabs

I want a tab layout in which, on every tab there are two fragments, One above showing a progress of a task that is completed by giving input in 3 tabs, from start to end, and another main fragment below that progress fragment that will be taking input.
That makes a title and detail in every tab, title fragment same and detail fragment (input fragment different on each tab)!
I tried all methods for two days :(
My Solution
i tried a layout that contains two framelayout for main fragment that is added into two tabs from ViewPager,showed here:
public static class ScreenSlidePagerAdapter extends
FragmentStatePagerAdapter {
public static ArrayList<Fragment> tabs_fragments = new ArrayList<Fragment>(
3);
public ScreenSlidePagerAdapter(FragmentManager fm,
ArrayList<Fragment> tabs) {
super(fm);
ScreenSlidePagerAdapter.tabs_fragments = tabs;
}
#Override
public Fragment getItem(int arg0) {
return tabs_fragments.get(arg0);
}
#Override
public int getCount() {
return tabs_fragments.size();
}
#Override
public int getItemPosition(Object object) {
if (tabs_fragments.contains(object)) {
return POSITION_UNCHANGED;
}
return POSITION_NONE;
}
public static void setItem(Fragment fr, int position) {
if (position <= 2 && position >= 0) {
tabs_fragments.remove(position);
tabs_fragments.add(position, fr);
} else
Log.d("adding tab", "wrong tab position to add fragment at");
}
}
On activity start i do this, see i get tab position that is used in main fragment for loading detail fragment for different tab positions:
mPager = (ViewPager) findViewById(R.id.pager);
// fragments for pagers
ArrayList<Fragment> tabs = new ArrayList<Fragment>();
tabs.add(new FrEventDetails());
tabs.add(new FrEventDetails());
tabs.add(new FrRuleSave());
mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager(), tabs);
mPager.setAdapter(mPagerAdapter);
bar = getActionBar();
bar.setTitle("Add Rule");
bar.setSubtitle("select event for rule");
bar.setDisplayShowTitleEnabled(true);
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.setDisplayHomeAsUpEnabled(true);
bar.addTab(bar.newTab().setText("Select Event")
.setTabListener(new TabListener(mPager)));
bar.addTab(bar.newTab().setText("Select Action")
.setTabListener(new TabListener(mPager)));
bar.addTab(bar.newTab().setText("Save Rule")
.setTabListener(new TabListener(mPager)));
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When swiping between pages, select the
// corresponding tab.
if (bar.getSelectedNavigationIndex() != position)
bar.setSelectedNavigationItem(position);
tab = position;
}
and then when this fragment is attaching to activity I add a progress layout (title( for one frame-layout and based on the selected tab, add another fragment for detail frame layout(for input).
showed here:
public class FrEventDetails extends Fragment {
Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = (Context) activity;
int tab = AddRule1.tab;
android.app.FragmentTransaction ft = activity.getFragmentManager()
.beginTransaction();
ft.add(R.id.fr_rule_progress_container, new FrProgress());
if (tab == 1) {
ft.replace(R.id.fr_event_input_container, new FrActionSelect(),
"cell1_1").commit();
} else if (tab == 0) {
ft.replace(R.id.fr_event_action_container, new FrEventSelect(),
"cell1_2").commit();
}
}
NOTE* layout for this main fragment is simple containing two framelayouts.
result : It shows on start a title and detail beautifully on first tab, but on second tab, only main fragment and,
when i swipe to third fragment and come back, second fragment is filled beautifully (after 1 second of showing) but 1st fragment is now empty.
i can't understand what to do with this.
please give some solution to this tearful problem of two days
To Show all Tabs at the same time in start, increase PagerOffSetLimit (to 2 in this case for 3 tabs)
For refreshing state of fragment or calling some methods on your fragment in the tab beside your current tab, use the Pager.instantiateItem method.
One second delay is because you have on the animateLayoutChanges in your xml.

Categories

Resources