I am trying to set up sliding tabs on top of an activity. I want this result :
I'm following the explanations of this example : http://developer.android.com/samples/SlidingTabsBasic/project.html
And I'm also looking at this video : https://www.youtube.com/watch?v=tRg_eDfQ8fk
I'm doing so because of this post : Action bar navigation modes are deprecated in Android L
I have 3 fragments for each of my tab. Each inflates a different layout and do different things. Now I need to connect them to my PageAdapter. I've already used an adaptor for a ListView. I used getView with the position to do my work
However with this PageAdapter I'm not sure what I need to proceed. Should I use this method to create my fragment :
public Object instantiateItem(ViewGroup container, int position) {
and if so, how should it be done ?
Thank you.
You must implement a FragmentPagerAdapter like this:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment();
case 1:
return new TwoFragment();
case 2:
return new ThreeFragment();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
and set it to viewpager adapter:
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
Related
I am trying to implement viewPager2 with variable number of fragments, and not sure on the correct / best approach and couldn't find any good examples to copy!
The fragments in my viewpager depend on the properties of the object being displayed - the first 2 are always present, but there are 4 more that may or may not be present - i.e. the FragmentStateAdapter does not know how many fragments there will be or which ones will be present until runtime.
My initial approach was to have a List that I passed to my FragmentStateAdapter which looked like this:
public class busDetailFragmentAdapter extends FragmentStateAdapter {
private final List<Fragment> fragmentList;
public busDetailFragmentAdapter(#NonNull Fragment fragmentActivity, List<Fragment> fragmentList) {
super(fragmentActivity);
this.fragmentList = fragmentList;
}
// return fragments at every position
#NonNull
#Override
public Fragment createFragment(int position) {
return fragmentList.get(position);
}
#Override
public int getItemCount() {
return fragmentList.size();
}
}
I then simply added fragments to my list with tabFragments.add(new busDetailInfoFrag()); and notified the fragmentadapter that an item had been inserted.
This worked fine until I navigated away from the parent fragment and then used the back button - the app crashed with a "Fragment already added" error.
I found something in the docs creating about new fragments and not reusing fragment. So, I modified my adapter to use a list of strings rather than a list of fragments, and am looking up the position against this list and using a switch statement to create the correct fragment.
public class busDetailFragmentAdapter extends FragmentStateAdapter {
private final List<String> fragmentList;
public busDetailFragmentAdapter(#NonNull Fragment fragmentActivity, List<String> fragmentList) {
super(fragmentActivity);
this.fragmentList = fragmentList;
}
// return fragments at every position
#NonNull
#Override
public Fragment createFragment(int position) {
switch (fragmentList.get(position)){
case "info":
return new busDetailInfoFrag();
case "location":
return new busDetailLocationFrag();
//More cases as needed
default:
return new missingFrag();
}
}
#Override
public int getItemCount() {
return fragmentList.size();
}
}
This is working as I need it to, but just wondering if this is the best/correct approach or if there's a better way!
As the title suggests, is it possible to replace two fragments while in a third one, for example pressing a button in fragment 3 replaces fragment 1 with fragment 2, while all 3 are inside a ViewPager? For simpler understanding, this is what my PagerAdapter looks like:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
int numberOfTabs;
public SectionsPagerAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.numberOfTabs=numberOfTabs;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
switch(position){
case 0:
CreateEventFragmentPage1 tab1 = new CreateEventFragmentPage1();
return tab1;
case 1:
CreateEventFragmentPage2 tab2 = new CreateEventFragmentPage2();
return tab2;
case 2:
CreateEventFragmentPage3 tab3 = new CreateEventFragmentPage3();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
// Show 3 total pages.
return numberOfTabs;
}
}
Any and all advice will be highly appreciated.
As this is an adapter FragmentPagerAdapter so there is must be an notifyChanged method or similar
And i suppose it will works as notifyDataSetChanged with Recyclerview
Another reason for this that surrounded fragments of the current are not fully be destroyed
In addition rewrite method getItem(int position) to perform logic of reordering your fragments
Also try out to use an FragmentStatePagerAdapter
I have a PagerAdapter which creates 3 fragments.
In the MainActivity I set the ViewPager like this:
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(2);
pager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
the pager.setOffScreenPageLimit(2) is from here https://stackoverflow.com/a/11852707/1662033, to make sure OnViewCreated is called once for each fragment.
Here is my PagerAdapter class:
public class PagerAdapter extends FragmentPagerAdapter {
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Home";
case 1:
return "Live";
case 2:
return "Gallery";
default:
return null;
}
}
#Override
public int getCount() {
return 3;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new HomeFragment();
case 1:
return new LiveFragment();
case 2:
return new GalleryFragment();
default:
return null;
}
}
}
In the current code: all of the fragments's onCreateView, onActivityCreated etc are called once, at the beginning and that's it.
The issue I am having is - in one of the fragments (LiveFragment) I have a custom view which connects to a camera and shows the live stream.
What I want is - to inflate the view of LiveFragment only when the user navigates to the fragment, instead of how its now - its inflated at the beginning with the other fragments.
Is there a way to call onCreateView only when fragment is chosen?
FragmentPagerAdapter creates all the Fragments and has all of them in memory at all time. i.e. All your Fragments are created only once and you can navigate around them.
FragmentStatePagerAdapter creates and has only 3 Fragments (the current Fragment and the left and right Fragments to the current one) in memory at any given time, by default. You cannot reduce that number. However, you can increase the number Fragments in memory by using the viewpager.setOffScreenPageLimit().
Since you have only 3 Fragments, all your 3 fragments are created when the Viewpager is initialised. You can track which Fragment is currently visible on the screen using viewpager.addOnPageChangeListener(). Using this you can change the View of your LiveFragment from dummy one to actual View only when the Fragment is currently visible.
I am trying to create a program with TabLayout and an option menu which when selected can add or delete the tab along with the fragment. I can delete the tab but I am not able to understand what else needs to be done because I have to delete the fragments that the tab holds, more over I may also have to rearrange the position of the fragments which I just can't seem to figure out. Could you please help me with this ?
under mainAcitivity this is how I add tabs
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tab1= tabLayout.newTab().setText("TAB 1");
tabLayout.addTab(tab1);
tab2 = tabLayout.newTab().setText("TAB 2");
tabLayout.addTab(tabKantipur);
This is the FragmentstatePagerAdapter
public class TabPagerAdapter extends FragmentStatePagerAdapter {
int tabCount;
public TabPagerAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.tabCount = numberOfTabs;
}
#Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return NewsFragment.newInstance("data for fragment 1");
case 1:
return NewsFragment.newInstance("data for fragment 2");
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
Basically here NewsFragment is the fragment whose new instance is used in the tabs. Under onActivityResult I am getting the data that has been requested from the options Menu to add or delete fragmetns
mpagerAdapter = new TabPagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
removedTab = ..data received from ooption menu
// here I want to remove the Tab & the fragments (tab1 & its fragment)
if (removeTab == "tab1") {
tabLayout.removeTab(tab1);
mpagerAdapter.notifyDataSetChanged();
}
}
As I do this only the first tab gets removed I would like to know how to remove the associated fragment too.
You don't have to explicitly delete the fragment, you can remove the fragment.
You can remove the tab and do notifyDataSetChanged on the viewPagerAdapter instance.It will take care of removing the fragment.
I had asked a similar question using fragmentarray for which i got it to work . this is the link, Issue: Logic to find the position of a fragment in a fragment arraylist?
So I have a section_home layout that shows a picture. Then I made another layout called section_home_two that shows a different picture. In my code I have a class called HomeFragment for the section_home layout. The second java class is called PreviewsFragment for the section_home_two layout.
Is there anyway you can make HomeFragment swipe horizontally to PreviewsFragment? Is there anyway to merge them?
I would suggest that you use a ViewPager to swipe between the fragments.
Follow the instructions at http://developer.android.com/training/animation/screen-slide.html to get the ViewPager working, and then change the number of pages to 2:
private static final int NUM_PAGES = 2;
And use this PagerAdapter instead of the one in the sample:
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0)
return new HomeFragment(); // The ViewPager will show this fragment first
else
return new PreviewsFragment; // and will allow you to swipe to this one and back.
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
This will allow you to swipe horizontally back and forth between the two fragments. if you're using a factory method to create your fragments, use that instead of the return new HomeFragment(); and return new PreviewsFragment(); lines.