I have setup a list of fragments using TabLayout and ViewPager on MainActivity as such
public class MainActivity extends AppCompatActivity implements Fragment1.OnFragmentInteractionListener, Fragment2.OnFragmentInteractionListener, Fragment3.OnFragmentInteractionListener, Fragment4.OnFragmentInteractionListener
, Fragment5.OnFragmentInteractionListener{
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new CustomAdapater(getSupportFragmentManager(), getApplicationContext()));
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#51ffff"));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
switch (tab.getPosition()) {
case 0:
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#ced21f"));
break;
case 1:
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#51ffff"));
break;
case 2:
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#FF0000"));
break;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
});
}
#Override
public void onFragmentInteraction(Uri uri) {
}
private class CustomAdapater extends FragmentPagerAdapter {
private String fragments[] = {"Control", "Connection", "Log", "Others", "Others2"};
public CustomAdapater(FragmentManager supportFragmentManager, Context applicationContext) {
super(supportFragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Fragment1();
case 1:
return new Fragment3();
case 2:
return new Fragment2();
case 3:
return new Fragment4();
case 4:
return new Fragment5();
default:
return null;
}
}
#Override
public int getCount() {
return fragments.length;
}
#Override
public CharSequence getPageTitle(int position) {
return fragments[position];
}
}
}
Somehow when I transit from Fragment1 to Fragment3 and back to Fragment1, the views on Fragment1 gets reset to original state(Like it was just created).
This only happens if I transit 2 fragment away from the current Fragment. For example 2->4 or 3->1.
Everything is fine if the transition is next to each other, for example 2->3 or 1->2.
This is my first android app so do pardon me.
It seems like it is creating a new fragment instead loading of existing ones
Your fragment get destroyed due to the fact that by default viewpager retain only one fragment at a time while moving around so you can simply use
viewPager.setOffscreenPageLimit(no_of_fragment_to_retain);
or
viewPager.setOffscreenPageLimit(3); // in your case
so when you come back from 4->1 or 3->1 you will get the previous stored state of your fragment. link to docs
First :
viewPager.setAdapter(new CustomAdapater(getSupportFragmentManager(), getBaseContext()));
Now see : in get Item method of View pager evrytime when you go to new tab a new instance of fragment is created So the previous view is lost . You should retain state in your fragment class.
or a simple solution is use FragmentstatepagerAdapter instead of FragmentPagerAdapter in your Adapter class.
Let me know if it helps
Related
I have used Tab Control and RecyclerView together in Android. The way it functions is I have SearchBar in the toolbar. When the user enters the search query in the search bar. Upon hitting the search button, tab's Fragments are supposed to be loaded with data. Issues are as follows.
1) Tabs icon disappear
2) When debugging through the code found (Since I am using ViewPager with Tab Layout to implement Tabs in android) that getItem method of PagerAdapter class is called twice every time getItem is triggered.
I am stuck and don't know what to do. Not much help online as well.
1) Tab initialization Code:-
private TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout = (TabLayout)findViewById(R.id.tablayout);
tabLayout.addTab(tabLayout.newTab().setIcon(R.mipmap.craigslist_new1));
tabLayout.addTab(tabLayout.newTab().setIcon(R.mipmap.kijiji_new1));
tabLayout.addTab(tabLayout.newTab().setIcon(R.mipmap.letgo_new1));
tabLayout.addTab(tabLayout.newTab().setIcon(R.mipmap.varagesale_new1));
tabLayout.addTab(tabLayout.newTab().setIcon(R.mipmap.facebook_new1));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
drawerLayout = findViewById(R.id.drawer_layout);
}
#Override
public boolean onQueryTextSubmit(String query) {
//loadRecyclerViewData(query);
Bundle bundle = new Bundle();
bundle.putString("searchText", query);
final ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
final PageAdapter adapter = new PageAdapter(getSupportFragmentManager(), tabLayout.getTabCount(), bundle);
viewPager.setAdapter(adapter);
viewPager.setOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(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) {
}
});
return true;
}
2) PagerAdapter:-
public class PageAdapter extends FragmentStatePagerAdapter {
int mNoofTabs;
Bundle bundle;
public PageAdapter(FragmentManager fragmentManager, int NumberOfTabs, Bundle bundle)
{
super(fragmentManager);
this.mNoofTabs = NumberOfTabs;
this.bundle = bundle;
}
#Override
public Fragment getItem(int i) {
switch(i)
{
case 0 :
CraigslistFragment tab1 = new CraigslistFragment();
tab1.setArguments(bundle);
return tab1;
case 1:
KijijiFragment tab2 = new KijijiFragment();
tab2.setArguments(bundle);
return tab2;
case 2:
letgoFragment tab3 = new letgoFragment();
tab3.setArguments(bundle);
return tab3;
case 3:
VaragesaleFragment tab4 = new VaragesaleFragment();
tab4.setArguments(bundle);
return tab4;
case 4:
FacebookFragment tab5 = new FacebookFragment();
tab5.setArguments(bundle);
return tab5;
default:
return null;
}
}
#Override
public int getCount() {
return mNoofTabs;
}
}
I have an activity with 2 tabs. What im trying to do is to replace between 2 fragments when each tab is pressesd. I also have 2 fragments: fragmentOne and fragmentTwo.When tab one is pressed i want to show fragmentOne and when tab two is pressed i want to show fragmentTwo.
I'm not sure if i should create a container layout in the activity and there add the fragmentOne and fragmentTwo, or maybe there is another other way to do it?
here is my code
public class InboxActivity extends AppCompatActivity {
private TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inbox);
tabLayout = (TabLayout)findViewById(R.id.tabLayout);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
Fragment fragment;
int position = tab.getPosition();
//requests = position - 0
//invitations = position - 1
switch (position){
case 0:
break;
case 1:
break;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
when case is 0 i want to show fragmentOne
when case i 1 i want to show fragmentTwo
How should i do that?
You can do it as follow:
public void onTabSelected(TabLayout.Tab tab) {
Fragment fragment = null;
switch (tab.getPosition()) {
case 0:
fragment = new FirstFragment();
break;
case 1:
fragment = new SecondFragment();
break;
}
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.simpleFrameLayout, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
Here is a tutorial for more information
Use a ViewPager instead.
Set an adapter in the view pager and use it with a TabLayout using
tabLayout.setupWithViewPager(viewPager);
i am developing an android app which has four fragments with tablayout and each fragment has connection error dialog box.
first problem is,when i start my app,four fragments work
simultaneously at the same time.So,when i occur connection error four
dialog boxes are shown in first fragment When i switch to second tab
it doesn't show his dialog box because his dialog is shown in first
fragment.
second problem is,i create that fragments with swipe refresh layout
to fetch data from server.I call onRefresh method in onCreate method.
when i start my app,first fragment data is loaded from server but
when i switch first tab to second tab,it is not loaded his data from
server but when i switch first tab to third tab,it is work.
Also,when i switch second tab to third tab,it is not loaded data from
server but when i switch second tab to fourth tab,it is work. It is
only work when i switch tabs with one tab differ. Is there anyway to
solve that problems.
I searched this problems from internet but i didn't get my problems answer.
Please anyone help me.Thanks in advance.....
Sorry for my poor english
this is tablyout code
viewPager = (ViewPager) findViewById(R.id.viewpagerMain);
tabLayout = (TabLayout) findViewById(R.id.tablayoutMain);
tabLayout.addTab(tabLayout.newTab().setText("Noticeboard"));
tabLayout.addTab(tabLayout.newTab().setText("News"));
tabLayout.addTab(tabLayout.newTab().setText("Events"));
tabLayout.addTab(tabLayout.newTab().setText("Result"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager(), tabLayout.getTabCount()));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
viewPager.setOffscreenPageLimit(0);
tabLayout.setOnTabSelectedListener(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) {
}
});
This is MyAdapter class
class MyAdapter extends FragmentStatePagerAdapter {
int num_of_tab;
public MyAdapter(FragmentManager fm, int num_of_tab) {
super(fm);
this.num_of_tab = num_of_tab;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
NoticeBoardFragment noticeBoardFragment = new NoticeBoardFragment();
return noticeBoardFragment;
case 1:
NewsFragment newsFragment = new NewsFragment();
return newsFragment;
case 2:
EventsFragment eventsFragment = new EventsFragment();
return eventsFragment;
case 3:
ResultFragment resultFragment = new ResultFragment();
return resultFragment;
default:
return null;
}
}
#Override
public int getCount() {
return num_of_tab;
}
}
Override setUserVisibleHint in each fragment and write your dialog box code in if(isVisibleToUser) instead of Oncreate. This should solve your problem
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
//dialog box code here
}
}
i have a view pager in tabLayout that getting it's content from a JSON
each page has differ contents
all i want to do is to get each page content once
is there a way to do this
thanks in advance
Yes it's possible. My answer is not from an official source but it's from my previous experience.
Create your ViewPager as a member of the Activity:
private ViewPager pager;
Then inside onCreate() method, initialize your ViewPager:
pager=(ViewPager)findViewById(R.id.pager);
Initialize your tablayout and and a tab selected listener:
tabLayout.addOnTabSelectedListener(
new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
switch (tab.getPosition())
{
case 0:
pager.setCurrentItem(0,true);
break;
case 1:
pager.setCurrentItem(1,true);
break;
case 2:
pager.setCurrentItem(2,true);
break;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
switch (tab.getPosition())
{
case 0:
pager.setCurrentItem(0,true);
break;
case 1:
pager.setCurrentItem(1,true);
break;
case 2:
pager.setCurrentItem(2,true);
break;
}
}
}
);
Set the an adapter to your ViewPager:
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
Create a private inner class MyPagerAdapter that extends FragmentPagerAdapter:
private class MyPagerAdapter extends FragmentPagerAdapter
{
private Tab1 tab1;private Tab2 tab2;private Tab3 tab3;
//Tab1,Tab2,Tab3 representing your respective fragments
public MyPagerAdapter(FragmentManager fm) {
super(fm);
//initialize all your fragments at once inside the constructor
tab1=new Tab1();
tab2=new Tab2();
tab3=new Tab3();
}
#Override
public int getCount() {
return 3;
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
//Return each fragment according to a position
switch (position)
{
case 0:
return tab1;
case 1:
return tab2;
case 2:
return tab3;
}
return null;
}
}
That's how I handled my case. Good coding.
I have a fragment with TabLayout, which looks like this:
Code, where it is created:
public class CalendarActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_calendar);
SimpleDateFormat sdf = new SimpleDateFormat("EEE dd-MM", new Locale("en", "GB"));
TabLayout tabLayout = findViewById(R.id.tabs);
final ViewPager viewPager = findViewById(R.id.viewPager);
tabLayout.addTab(tabLayout.newTab().setText("today"));
tabLayout.addTab(tabLayout.newTab().setText("tomorrow"));
tabLayout.addTab(tabLayout.newTab().setText(sdf.format(new Date(((new Date()).getTime() + 2*86400000)))));
tabLayout.addTab(tabLayout.newTab().setText(sdf.format(new Date(((new Date()).getTime() + 3*86400000)))));
tabLayout.addTab(tabLayout.newTab().setText(sdf.format(new Date(((new Date()).getTime() + 4*86400000)))));
tabLayout.addTab(tabLayout.newTab().setText(sdf.format(new Date(((new Date()).getTime() + 5*86400000)))));
tabLayout.addTab(tabLayout.newTab().setText(sdf.format(new Date(((new Date()).getTime() + 6*86400000)))));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
PageAdapterCalendar adapter = new PageAdapterCalendar (getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(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) {
}
});
}
Adapter code:
public class PageAdapterCalendar extends FragmentStatePagerAdapter {
int mNumOfTabs;
public PageAdapterCalendar (FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch(position){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
fragment = CalendarFragment.newInstance();
break;
}
return fragment;
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
newinstance() in Calendar fragment:
public static Fragment newInstance() {
CalendarFragment fragment = new CalendarFragment();
return fragment;
}
I need each of my tabs to behave the same and use the same layout, but I only need to send them info about the date (same as it's in their title), so they would get different data from database. I have tried bundles and tags, but it didn't work as I expected - Bundles were added all to each tab and tags are not loaded on onCreate() part (I think?), so they were empty.
In your newInstance method try to pass in the relevant information for each fragment you are creating as parameters. You just need to pass in what little information is necessary so that fragment knows where to get its data from in your database. Then from there create a bundle (eg mBundle) and put all those values into that bundle and call fragment.setArguments(mBundle). Then in your fragment onCreate method parse that bundle to get your data and go from there.
It seems like a lot of steps but this method ensures that the data persists across all lifecycle events
For an example see Best practice for instantiating a new Android Fragment