How to stop tabs from being recreated on each activity call - java

I have an application that has an index page which has tabs for navigation. This page has multiple children pages being implemented as fragments.
Some of my children fragment views also have tabs in them for more navigation like below
The issue i am having is when i switch from one of these fragments to the other, and return to it.The tabs on that one are recreated like so
And i'm not sure how to solve this problem as it is my first time getting this serious with tabs.
Below is my code for the top-level-tab adapter
public class indexTabAdapter extends FragmentPagerAdapter
{
private List<String> titleList;
private List<Fragment> fragmentList;
public indexTabAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleList)
{
super(fm);
this.fragmentList = fragmentList;
this.titleList = titleList;
}
#Override
public Fragment getItem(int position)
{
return fragmentList.get(position);
}
#Override
public int getCount()
{
return fragmentList.size();
}
#Override
public CharSequence getPageTitle(int position)
{
return titleList.get(position);
}
}
Below here is the code for the activity class managing the top-level-tabs
#Override
protected void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index_page);
pager = (ViewPager) findViewById(R.id.indexViewPager);
tabLayout = (TabLayout)findViewById(R.id.indexTabs);
prepareDataResource();
indexTabAdapter ita = new indexTabAdapter(getSupportFragmentManager(),fragmentList,titleList);
pager.setAdapter(ita);
tabLayout.setupWithViewPager(pager);
ita.notifyDataSetChanged();
}
private void prepareDataResource()
{
fragmentList.add(new dash());
titleList.add("Dash");
fragmentList.add(new AcademicCalender());
titleList.add("Calender");
fragmentList.add(new IncidentReport());
titleList.add("Incident Report");
fragmentList.add(new Profile());
titleList.add("Profile");
fragmentList.add(new Pta());
titleList.add("PTA");
fragmentList.add(new timeTable());
titleList.add("Time Table");
fragmentList.add(new Results());
titleList.add("Results");
}
Lastly, this is the code for the lower-level-tab that keeps repeating
public class Profile extends Fragment
{
private List<String> titleList = new ArrayList<>();
private List<Fragment> fragmentList = new ArrayList<>();
private ViewPager pager;
private TabLayout tabLayout;
public Profile()
{
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.profile_view_activity,container,false);
pager = (ViewPager) view.findViewById(R.id.profileViewPager);
tabLayout = (TabLayout) view.findViewById(R.id.profileTabs);
prepareDataResource();
profileTabsAdapter rta = new profileTabsAdapter(getFragmentManager(),fragmentList,titleList);
pager.setAdapter(rta);
tabLayout.setupWithViewPager(pager);
return view;
}
private void prepareDataResource()
{
fragmentList.add(new index());
titleList.add("Home");
fragmentList.add(new immunization());
titleList.add("Immunization");
fragmentList.add(new information());
titleList.add("Information");
fragmentList.add(new records());
titleList.add("Health Records");
}
}

FragmentPagerAdapter instances your fragment once. So if you instantiate your list when declaring it as a field, it will always retain that same list, thus adding elements when the Fragment's onCreateView is called.
To avoid this, declare and instantiate both lists like this:
public class Profile extends Fragment {
private List<String> titleList;
private List<Fragment> fragmentList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//your code for views initialization
//init the lists here!
titleList = new ArrayList<>();
fragmentList = new ArrayList<>();
prepareDataResource();
//your adapter set up code
return view;
}

If you're working with ViewPager, try calling viewPager.setOffscreenPageLimit(numberOfTabs). I'm not a hundred percent sure this will work, but it won't hurt to try.
From the official Android documentation:
setOffscreenPageLimit(int limit)
Set the number of pages that should be retained to either side of the
current page in the view hierarchy in an idle state.

Related

passing data from one fragment to another fragment without changing fragment

I have one activity HomeActivity and I have HomePageFragment which have some categories with icon and title of data, when I click on any category I'm sending the clicked item Title name with bundle and opening MultipleFragment and I'm getting clicked title name from the previous fragment, on this multiple fragments I have viewpager inside it..
1) PostFragment,
2) TextFragment
now here's my main question that I want to send clicked item title name to PostFragment and TextFragment,
HomeFragment
public void onItemClick(int position) {
MultiplePost multiplePost = new MultiplePost();
Bundle args = new Bundle();
Categories categoriesClicked = categoriesList.get(position);
args.putString(Title, categoriesClicked.getTitle());
args.putString(ImageUrl, categoriesClicked.getIcon());
multiplePost.setArguments(args);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame,multiplePost)
.addToBackStack(null)
.commit();
}
MultiplePost
public class MultiplePost extends Fragment {
private TabLayout tabLayout;
private ViewPager viewPager;
private ViewPageAdapter viewPageAdapter;
private View view;
private FragmentManager mFragmentManager;
public static String title ;
public MultiplePost() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_multiple_post, container, false);
title = getArguments().getString("title");
tabLayout = view.findViewById(R.id.tablayout_id);
viewPager = view.findViewById(R.id.viewPager_id);
viewPageAdapter = new ViewPageAdapter(getChildFragmentManager());
viewPageAdapter.AddFragment(new PostFragment(), "");
viewPageAdapter.AddFragment(new TextFragment(), "");
viewPager.setAdapter(viewPageAdapter);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.photo);
tabLayout.getTabAt(1).setIcon(R.drawable.file);
PostFragment post = new PostFragment();
Bundle args = new Bundle();
args.putString("title", title);
post.setArguments(args);
getActivity().getSupportFragmentManager().beginTransaction();
.replace(R.id.main_frame, post)
.commit();// and this's changing whole fragment with PostFragment and
//so i can't see my viewpager on MultiplePost
return view;
}
}
ViewPagerAdapter
public class ViewPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> listFragment = new ArrayList<>();
private final List<String> listTitle = new ArrayList<>();
public ViewPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return listFragment.get(position);
}
#Override
public int getCount() {
return listTitle.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return listTitle.get(position);
}
public void AddFragment(Fragment fragment, String title){
listFragment.add(fragment);
listTitle.add(title);
}
}
How to send title onto PostFragment and TextFragment into viewpager

FragmentStatePagerAdapter giving blank fragments after updating

I have an Weather adapter to show the weather, the activity is split into two screens, one half a listview (different adapter), the other is tablayout with another tablayout inside to scroll through all the different pages of weather that are available
After turning off the wifi to make sure i don't receive anything and then turning on the wifi to receive the weather i get the update method called for the adapter and the list is updated, new fragments created, onViewCreated is called but the fragments display as blank and as only 1 (can't cycle through them if there are multiple).
Here is the Weather ViewPagerAdapter
public class WeatherViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments;
public WeatherViewPagerAdapter(FragmentManager fm) {
super(fm);
fragments = new LinkedList<>();
if (Storage.getInstance().getWeatherModels().size() == 0){
// Displays page but with "no weather available" message
fragments.add(WeatherFragment.newInstance(null));
}else{
for (CurrentWeatherModel model : Storage.getInstance().getWeatherModels()){
fragments.add(WeatherFragment.newInstance(model));
}
}
}
public void rediscoverWeather(){
fragments.clear();
if (Storage.getInstance().getWeatherModels().size() == 0){
fragments.add(WeatherFragment.newInstance(null));
}else{
for (CurrentWeatherModel model : Storage.getInstance().getWeatherModels()){
fragments.add(WeatherFragment.newInstance(model));
}
}
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public Parcelable saveState() {
return null;
}
}
And this is the fragment that is in the Tablayout on the side that displays the weather
public class WeatherViewPagerFragment extends Fragment {
private WeatherViewPagerAdapter adapter;
private ViewPager viewpager;
private TabLayout tabLayout;
public static WeatherViewPagerFragment newInstance(){
return new WeatherViewPagerFragment();
}
#Override
public UniqueInfo getUniqueInfo() {
return null;
}
#Override
public void update() {
adapter.rediscoverWeather();
setPage(0);
adapter.notifyDataSetChanged();
}
public void setPage(int pageNumber){
if (pageNumber >=0 && pageNumber < adapter.getCount()){
viewpager.setCurrentItem(pageNumber, true);
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.weather_view_pager, container, false);
}
private void createAdapter(){
adapter = new WeatherViewPagerAdapter(getChildFragmentManager());
viewpager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewpager);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewpager = view.findViewById(R.id.viewpager);
tabLayout = view.findViewById(R.id.sliding_tabs);
createAdapter();
}
}
The update() for WeatherViewPagerFragment gets called when its meant to, which updates the Adapter, re-doing the fragments and calling onCreateView and onViewCreated, but what i see is just a blank fragment, any suggestions why this would be happening? i figured it could be a focus issue but i haven't had any luck as of yet with fixing it

Fragment with viewpager load one time only

I have simple problem.. I have MainActivity.. inside it i have 5 fragments and i can move using bottom navigation bar without problem!
In first fragment (Profile) i have inside that tow fragment using Tablayout and Viewpager..
First Fragment (Friends) Second Fragment (Users)..
My problem when i run app and open (Profile) the tow fragments (Friends and Users)
Working 100% just in first time.. when i come back to other fragment using bottom bar and come back to friends or users is empty and not load !
I want attach some of my codes you will need it..
Profile Fragment:
mSectionsPageAdapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) v.findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
mSectionsPageAdapter.notifyDataSetChanged();
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
adapter.addFragment(new FriendsFragment(), "Friends");
adapter.addFragment(new UsersFragment(), "Online");
viewPager.setAdapter(adapter);
}
SectionsPageAdapter:
public class SectionsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}}
I try to add this in Friends Fragment and Users Fragment the problem was solved but the content duplicated in first time run only.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
}
SectionsPageAdapter:
public class SectionsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}}
A possible reason for your problems could be you are mixing up FragmentManagers.
In your Activity to handle the bottom navigation you should use Activity#getSupportFragmentManager().
But for any of the Fragments inside that activity, if you want to have children/nested fragments. You should use Fragment#getChildFragmentManager().
So in your profile fragment, while populating the two tabs pager, you should pass it Fragment#getChildFragmentManager() instead of getActivity().getSupportFragmentManager()
You can use interface to solve this problem. Implement interface in your "User" & "Friend" fragments & call the interface method when your "Profile" fragments "OnCreateView" is called. You can load data when interface method is called. For reference, Please check this link:
Communicating with Other Fragments
EDIT
Sorry,you can load data without using Interface. Here is some sample code:
Profile Fragment:
ProfileFragment extends Activity {
FriendsFragment friends;
UsersFragment users;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mSectionsPageAdapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) v.findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
mSectionsPageAdapter.notifyDataSetChanged();
friends.update();
users.update();
}
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
friends = new FriendsFragment();
users = new UsersFragment();
adapter.addFragment(friends, "Friends");
adapter.addFragment(users, "Online");
viewPager.setAdapter(adapter);
}
Friends Fragment:
FriendFragment extends Activity {
public void update(){
// load data
}
jest Use
ViewPagerAdapter(getChildFragmentManager())
getChildFragmentManager()

ViewPager setCurrentItem(position) not working after orientation change

i'm facing an issue i can't seem to resolve and i'd like some help.
My app is composed by an activity containing a fragment. After the user taps on a suggestion, activity's method onSuggestionClicked(String cardId) is called and activity's content is replaced with a new PagerFragment_new.
#Override
public void onSuggestionClicked(String cardId) {
Log.d("activity","ID:\t" + cardId);
PagerFragment_new pagerFragment = PagerFragment_new.getInstance(
Injection.provideMtgDatabase(getApplicationContext()),
activityPresenter.getAllCardExpansionIds(cardId),
this);
ActivityUtils.replaceFragment(getSupportFragmentManager(), pagerFragment, R.id.MTGRecallActivity_container);
}
PagerFragment_new contains a ViewPager to display CardInfoFragment_new
public class PagerFragment_new extends MtgRecallFragment_new implements PagerFragmentContract.View {
private View fragmentView;
private ViewPager viewPager;
private PagerFragmentContract.Presenter presenter;
private ScreenSlidePageAdapter_new adapter;
private MtgDatabase database;
private String[] printingsIds;
private ScreenSlidePageAdapter_new.ActivePresenterListener listener;
public PagerFragment_new() {
//Required empty constructor
}
public static PagerFragment_new getInstance(MtgDatabase database, String[] printingsIds, ScreenSlidePageAdapter_new.ActivePresenterListener listener) {
PagerFragment_new instance = new PagerFragment_new();
instance.setDatabase(database);
instance.setPrintingsIds(printingsIds);
instance.listener = listener;
return instance;
}
//other stuff
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
setRetainInstance(true);
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
fragmentView = inflater.inflate(R.layout.fragment_pager, container, false);
viewPager = (ViewPager) fragmentView.findViewById(R.id.PAGERFRAG_VIEWPAGER);
adapter = new ScreenSlidePageAdapter_new(getChildFragmentManager(), printingsIds, database, viewPager);
adapter.setListener(listener);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(1);
return fragmentView;
}
#Override
public void setPresenter(PagerFragmentContract.Presenter presenter) {
this.presenter = presenter;
}
}
The adapter to manage ViewPager's element's is ScreenSlidePageAdapter_new, it is responsible of instantiating CardInfoFragments.
public class ScreenSlidePageAdapter_new extends FragmentStatePagerAdapter {
private String[] printingsIds;
private String firstItemId;
private MtgDatabase database;
public ActivePresenterListener activity;
private ViewPager viewPager;
public ScreenSlidePageAdapter_new(FragmentManager fm, String[] printingsIds, MtgDatabase database, ViewPager viewPager) {
super(fm);
this.printingsIds =printingsIds;
this.database = database;
this.firstItemId = printingsIds[0];
this.viewPager = viewPager;
}
#Override
public Fragment getItem(int position) {
//todo create a bundle with cardId
Bundle bundle = new Bundle();
bundle.putString("CardID", printingsIds[position]);
bundle.putString("FirstItemId", firstItemId);
CardInfoFragment_new cardInfoFragment_new = CardInfoFragment_new.getInstance(viewPager);
cardInfoFragment_new.setArguments(bundle);
CardInfoPresenter cardInfoPresenter = new CardInfoPresenter(cardInfoFragment_new, database);
activity.setActivePresenter(cardInfoPresenter);
return cardInfoFragment_new;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
public void setListener(ActivePresenterListener listener) {
this.activity = listener;
}
#Override
public int getCount() {
return printingsIds.length;
}
public interface ActivePresenterListener {
void setActivePresenter(BasePresenter presenter);
}}
Finally, here's the code of CardInfoFragment:
public class CardInfoFragment_new extends MtgRecallFragment_new
implements CardInfoContract.View,
CardPrintingsAdapter.OnItemClickListener {
private ViewPager viewPager;
public CardInfoContract.Presenter presenter;
private View fragmentView;
private MTGCard mtgCard;
RecyclerView printingsRecyclerView;
CardPrintingsAdapter cardPrintingsAdapter;
private String firstItemId; //the first id
public CardInfoFragment_new() {
//required empty constructor
}
private void setViewPager(ViewPager viewPager) {
this.viewPager = viewPager;
}
public static CardInfoFragment_new getInstance(ViewPager viewPager) {
CardInfoFragment_new cardInfoFragment_new = new CardInfoFragment_new();
cardInfoFragment_new.setViewPager(viewPager);
return cardInfoFragment_new;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
setRetainInstance(true);
presenter.start();
String cardId = getArguments().getString("CardID");
firstItemId = getArguments().getString("FirstItemId");
mtgCard = presenter.getCardData(cardId);
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
fragmentView = inflater.inflate(R.layout.fragment_card_info_new, container, false);
setUpCardInfoView(fragmentView);
return fragmentView;
}
public void setUpCardInfoView(final View view){
//others view set-up action omitted
cardprintingsContainer = (LinearLayout) view.findViewById(R.id.CARDINFO_printingsContainer);
printingsRecyclerView = (RecyclerView)fragmentView.findViewById(R.id.CARDINFO_printings_recyclerView);
final List<String> printings = presenter.getCardPrintings(firstItemId, mtgCard.getName());
if (printings.size() < 40) {
setupPrintings(printings,printingsRecyclerView);
}
else {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout printingsRow = new LinearLayout(getContext());
printingsRow = (LinearLayout)inflater.inflate(R.layout.card_info_printings_row,printingsRow,true);
printingsRow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setupPrintings(printings, printingsRecyclerView);
}
});
ImageView printingssetImage = (ImageView)printingsRow.findViewById(R.id.CARDINFO_printingsRow_setImage);
printingssetImage.setVisibility(View.INVISIBLE);
TextView printingssetName = (TextView)printingsRow.findViewById(R.id.CARDINFO_printingsRow_setName);
printingssetName.setText("Click to see all the "+printings.size()+ " versions");
cardprintingsContainer.addView(printingsRow);
}
}
public void setupPrintings(List<String> printings, RecyclerView recyclerView) {
cardPrintingsAdapter =
new CardPrintingsAdapter(getContext(), printings);
cardPrintingsAdapter.setOnItemClickListener(this);
UnscrollableLayoutManager layoutManager = new UnscrollableLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
recyclerView.setAdapter(cardPrintingsAdapter);
recyclerView.setLayoutManager(layoutManager);
}
#Override
public void onItemClick(View itemView, int position) {
int i = viewPager.getAdapter().getCount();
viewPager.setCurrentItem(position);
}
#Override
public void onDestroy() {
presenter = null;
mtgCard = null;
super.onDestroy();
}}
When user click on a RecyclerView item, CardInfoFragment's method onItemClick(View itemView, int position) is called and the viewpager is set to current position. Everything as expected.
THE PROBLEM
When the orientation changes, fragments are able to retain their states, but viewPager.setCurrentItem(position) does nothing, and i'm not able to change displayed fragment.
I already checked:
ViewPager instance and adapters instances corresponds to those passed to Fragments
onItemClick is fired
this questions question1 question2
If i use
android:configChanges="orientation|screenSize"
in manifest it works even after config changes, but i don't want to use this option since is discouraged.
Thanks in advance!
By default, when certain key configuration changes happen on Android (a common example is an orientation change), Android fully restarts the running Activity to help it adjust to such changes.
When you define android:configChanges="keyboardHidden|orientation" in your AndroidManifest, you are telling Android: "Please don't do the default reset when the keyboard is pulled out, or the phone is rotated; I want to handle this myself. Yes, I know what I'm doing".
So use configChanges.
The use of this is discouraged, IF you don't know how to use it. But for a case like this, I would suggest you use it. IF not, still the activity will be recreated. which just takes time, resources, and I don't see why you would want that to happen.

It is possible to add/remove tabs in ViewPager at run time?

public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.v(TAG, "onCreateView");
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
// setting up the view pager and tab layout
mViewPager = (ViewPager) rootView.findViewById(R.id.view_pager);
mTabLayout = (TabLayout) rootView.findViewById(R.id.tab_layout);
PageAdapter adapter = new PageAdapter(getFragmentManager());
mViewPager.setAdapter(adapter);
mTabLayout.setupWithViewPager(mViewPager);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
return rootView;
}
My custom pager adapter looks like this:
public class PageAdapter extends FragmentStatePagerAdapter {
public PageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return new GroupTabFragment(position);
}
#Override
public CharSequence getPageTitle(int position) {
String title = "";
switch (position) {
case 0:
title = "Game"; // this is from a template, i have to
break; // return title dynamically
case 1:
title = "Movie";
break;
}
return title;
}
#Override
public int getCount() {
return 2; // the tabs number is a subject of change
} // i don't know it from the begining
}
The problem i have is that i have to add or remove a tab when a button is clicked, or something like this.
Each tab will display a classic list of objects.
Thank you.
There are 2 ways doing this although ViewPager is not suitable for dynamic removing:
1) Pass ArrayList<Fragment> data as parameter to PageAdapter
Then Adapter will look like this:
public class PageAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> data;
public PageAdapter(FragmentManager fm, ArrayList<Fragment> data) {
super(fm);
this.data = data;
}
#Override
public Fragment getItem(int position) {
return data.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
String title = "";
switch (position) {
case 0:
title = "Game"; // this is from a template, i have to
break; // return title dynamically
case 1:
title = "Movie";
break;
}
return title;
}
#Override
public int getCount() {
return data.size(); // the tabs number is a subject of change
} // i don't know it from the begining
}
to remove item you do in Activity\Fragment:
data.remove(fragmentId);
adapter.notifyDataSetChanged();
2) Recreate adapter every time you want to delete item. So you basically create new adapter with new data.
data.remove(fragmentId);
PageAdapter adapter = new PageAdapter(getFragmentManager(), data);
mViewPager.setAdapter(adapter);
Instead of using mTabLayout.setupWithViewPager(mViewPager); you can setup your tabs manually:
mTabLayout.addTab(mTabLayout.newTab().setText("Movie"));
mTabLayout.addTab(mTabLayout.newTab().setText("Game"));
mTabLayout.addTab(mTabLayout.newTab().setText("Audio"));
mTabLayout.setOnTabSelectedListener(this);
Removing is also easy: removeTabAt(int position) or removeTab(Tab tab)
Here I have found some better solution to remove all the views / fragments from the current context.
Here I have used TabLayout and ViewPage within Fragment.
So we need to clear tabs from TabLayout, views from ViewPage and fragments from FragmentManager.
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
FragmentManager fragmentManager = null;
public TabLayout tabLayout;
public ViewPager viewPager;
public ViewPagerAdapter(FragmentManager manager, TabLayout tabLayout, ViewPager pager) {
super(manager);
this.fragmentManager= manager;
this.tabLayout = tabLayout;
this.viewPager= pager;
}
public void removeAll() {
tabLayout.removeAllTabs();
viewPager.removeAllViewsInLayout();
viewPager.removeAllViews();
viewPager.setAdapter(null);
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (manager.getFragments() != null) {
manager.getFragments().clear();
}
viewPager.setAdapter(adapterPage);
viewPager.invalidate();
viewPager.requestLayout();
mFragmentList.clear();
mFragmentTitleList.clear();
}

Categories

Resources