Remove a fragment of a specific index from a view pager - android

Im trying to remove a fragment from a specific index. But that is really happening is the viewpager and pagerAdapter are just hiding the last fragment.
This is the code:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<String> data_fragment;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
data_fragment = new ArrayList<>();
data_fragment.add(0, "Página 0");
}
public void addNewFragmentData(String data) {
// int last_position = data_fragment.size();
data_fragment.add(data);
notifyDataSetChanged();
}
public void removeFragmentData(int index) {
// destroyItem(container, position, object);
data_fragment.remove(index);
notifyDataSetChanged();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
// #Override
// public void destroyItem(ViewGroup container, int position, Object object)
// {
// data_fragment.remove(position);
// super.destroyItem(container, position, object);
// }
#Override
public Fragment getItem(int position) {
Log.i("paginas", "getItem");
return LienzoFragment.newInstance(position);
}
#Override
public int getCount() {
return data_fragment.size();
}
#Override
public CharSequence getPageTitle(int position) {
return data_fragment.get(position);
}
}
As you see, I'm trying to avoid retain any fragment object. My approach is just keep the title and then each fragment manage its own save/restore state by itself.
int tab_selected = mViewPager.getCurrentItem();
mSectionsPagerAdapter.removeFragmentData(tab_selected);
//mSectionsPagerAdapter.destroyItem(mViewPager, tab_selected, mViewPager.getChildAt(tab_selected));
mViewPager.removeViewAt(tab_selected);
mViewPager.setCurrentItem(tab_selected-1, true);

Related

Android: How to set tag to fragments in FragmentPagerAdapter?

Here's the inner class that contains fragments and changes fragment views on swipe. This class is defined in an Activity.
private class ViewPagerAdapter extends FragmentPagerAdapter {
private int count;
ViewPagerAdapter(FragmentManager fm, int count) {
super(fm);
this.count = count;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new FriendsListFragment();
case 1:
Bundle bundle = new Bundle();
bundle.putString(Keys.TAG, ChatListFragment.class.getSimpleName());
ChatListFragment chatListFragment = new ChatListFragment();
chatListFragment.setArguments(bundle);
return chatListFragment;
case 2:
return new MoreFragment();
default:
return null;
}
}
#Override
public int getCount() {
return count;
}
}
Here I would like to add a code that sets tags to each fragment, so that I can recognize which fragment I'm at.
I searched quite much, and I haven't found a proper answer for this question, so please help.
You can override the setPrimaryItem method of your FragmentPagerAdapter.
private class ViewPagerAdapter extends FragmentPagerAdapter {
protected int currentPosition = -1;
protected Fragment currentFragment;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// ....
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
this.currentPosition = position;
if (object instanceof Fragment) {
this.currentFragment = (Fragment) object;
}
}
public int getCurrentPosition() {
return currentPosition;
}
public Fragment getCurrentFragment() {
return currentFragment;
}
}
Just use getCurrentPosition or getCurrentFragment methods to get information about current Fragment.

Infinite FragmentStatePagerAdapter with different fragment classes

I came across a strange issue in my project.
I have implemented infinite viewpager adapter using FragmentStatePagerAdapter
Code for same is:
public class DashBoardAdapter extends FragmentStatePagerAdapter {
ArrayList<AbstractFragment> fragments;
private int MAXFRAGMENTS=0;
public DashBoardAdapter(FragmentManager fm, ArrayList<AbstractFragment> fragments) {
super(fm);
this.fragments = fragments;
MAXFRAGMENTS=fragments.size();
}
#Override
public AbstractFragment getItem(int position) {
return fragments.get(position%MAXFRAGMENTS);
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
#Override
public CharSequence getPageTitle(int position) {
return fragments.get(position%MAXFRAGMENTS).getTitle();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
int virtualPosition = position % MAXFRAGMENTS;
return super.instantiateItem(container, virtualPosition);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
int virtualPosition = position % MAXFRAGMENTS;
super.destroyItem(container, virtualPosition, object);
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
MAXFRAGMENTS = fragments.size();
}
}
And the Main Activitycode(Function only) is something like this:
public void initializeViewPager()
{
verticalViewPager = (VerticalViewPager) findViewById(R.id.verticalviewpager);
enabledPages=new ArrayList<>();
enabledPages.addAll(getEnabledPages(false));
adapter=new DashBoardAdapter(getSupportFragmentManager(),enabledPages);
verticalViewPager.setAdapter(adapter);
verticalViewPager.setPageTransformer(true, new PageTransformer());
verticalViewPager.setCurrentItem(999+position);
verticalViewPager.setOffscreenPageLimit(1);
verticalViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(adapter!=null)
title.setText(adapter.getPageTitle(position));
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
private ArrayList<AbstractFragment> getEnabledPages(boolean a)
{
ArrayList<AbstractFragment> fragments=new ArrayList<>();
fragments.add(FragmentAttendance.newInstance(fragments.size()));
fragments.add(FragmentCompensation.newInstance(fragments.size()));
if(a)
fragments.add(FragmentTimeOff.newInstance(fragments.size()));
if(a)
fragments.add(FragmentCalendar.newInstance(fragments.size()));
if(a)
fragments.add(FragmentPeople.newInstance(fragments.size()));
if(a)
fragments.add(FragmentProvisions.newInstance(fragments.size()));
position = fragments.size()-(999+position)%fragments.size();
return fragments;
}
Layout of activity contains just a Viewpager.
And the Fragments, I have used is just copy of below fragment with different names
public class FragmentAttendance extends AbstractFragment {
public static final String ARG_SECTION_NUMBER = "section_number";
String title ="Testing";
public static FragmentAttendance newInstance(int sectionNumber) {
FragmentAttendance fragment = new FragmentAttendance();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public FragmentAttendance() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.card_attendance, container, false);
return rootView;
}
#Override
public String getTitle() {
return title;
}
}
Layout of fragment has just LinearLayout with a TextView.
The code is running superb if I am adding fragments more than three fragments. Howsoever as soon as the number of added fragments gets below four. My code Works in strange behavior.
Some of errors are Fragment already initialised
Other are Forward scrolling shows fragement View Howsoever when I scroll backward No view appears.
The working code can be tested by passing true to getEnabledPages(true);
And the non working code can be tested by passing false to getEnabledPages(false);
Please someone help me in this strange behaviour.

Calling notifyDataSetChanged

I am trying to update a view pager using FragmentPagerAdapter. Every time I call notifyDataSetChanged from my adapter I get a force close with this error "java.lang.IllegalStateException: Recursive entry to executePendingTransactions".
Any pointers on this would be helpful I have posted code below and I will post 2 links to 2 other questions I have had on this topic after this. Updating this ViewPager has been giving me a serious headache so any advice would be appreciated.
Removing Tabs using FragmentPagerAdapter ,
https://stackoverflow.com/questions/32834861/adding-and-removing-tabs-using-fragmentpageradapter
public void setTabsToSHow() {
Toast.makeText(getActivity(), Integer.toString(listOfTitles.size()), Toast.LENGTH_LONG).show();
mViewPager.getAdapter().notifyDataSetChanged();
}
class TabPageAdapter extends FragmentPagerAdapter {
public TabPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
return super.instantiateItem(container, position);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case JudgeActivity.JUDGE_MAIN:
if (mMainFragment == null) {
mMainFragment = JudgeMainFragment.newInstance();
}
return mMainFragment;
case JudgeActivity.JUDGE_VERDICTS:
if (mVerdictFragment == null) {
mVerdictFragment = JudgeVerdictFragment.newInstance();
}
return mVerdictFragment;
case JudgeActivity.JUDGE_CLASSIFY:
if (mClassifyFragment == null) {
mClassifyFragment = JudgeClassifyFragment.newInstance();
}
return mClassifyFragment;
case JudgeActivity.JUDGE_SIDEBAR:
if (mSidebarFragment == null) {
mSidebarFragment = JudgeSidebarFragment.newInstance((SidebarCall) mActivity);
}
return mSidebarFragment;
}
return null;
}
#Override
public int getCount() {
return listOfTitles.size();
}
#Override
public int getItemPosition(Object object) {
Toast.makeText(getActivity(), "itempostioton",Toast.LENGTH_SHORT).show();
return POSITION_NONE ;
}
#Override
public CharSequence getPageTitle(int position) {
// return CONTENT[position % CONTENT.length].toUpperCase(Locale.US);
//Notify data set changed can only be called from inside this class
notifyDataSetChanged();
return listOfTitles.get(position);
}
}
Remove notifyDataSetChanged(); from public CharSequence getPageTitle(int position) method
Secondly, do not return from case statements, rather do assignment to local variable and finally return the fragment. Use break after every case block.

how to get info when fist page loaded in ViewPager?

I want to update container fragment base on data inside the page fragment in ViewPager. I used this solution Retrieve a Fragment from a ViewPager and it works fine when I swipe the view.
But I cannot figure out how to get hint (callback) if first page is loaded. At the beginning? Of course onPageSelected is called but when I try to get fragment I got null.
Data data = null;
mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
#Override
public void onPageSelected(int position) {
PageFragment page = MyPagerAdapter.getPageFragment(position);
if(page != null)
data = page.getData();
else
Log.w(TAG,"page is null"); //i get it at first time. :(
}
});
Below MyPageAdapter which I use (accordint to Retrieve a Fragment from a ViewPager)
public class MyPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<PageFragment> registeredFragments = new SparseArray<PageFragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return ...;
}
#Override
public Fragment getItem(int position) {
return PageFragment.newInstance(...);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public PageFragment getPageFragment(int position) {
return registeredFragments.get(position);
}
}

FragmentManager contains fragment from viewpager after state loss

On state loss or screen rotation and when my boolean flag is true, I want to recreate my screen. However, the fragment manager still has the previous fragment attached and it gets loaded.
What can I do to get rid of that fragment?
public class ViewPagerAdapter extends FragmentPagerAdapter {
private String[] mData;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
mData= new String[0];
}
#Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putInt("key", position);
Fragment fragment = new MyFragment();
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return mData.length;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public CharSequence getPageTitle(int position) {
return mData[position];
}
public void setData(String[] data) {
mData= data;
}
}
Piece of code in Activity onCreate()
mViewPagerAdapter = new ViewPagerAdapter(getFragmentManager());
mViewPagerAdapter.setData(data);
viewPager.setAdapter(mViewPagerAdapter);
You may override instantiateItem() to detect screen rotation like a Fragment can.
Code example:
#Override
public boolean isViewFromObject(View view, Object o) {
return o == view;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = getActivity().getLayoutInflater().inflate(R.layout.pager_item,
container, false);
return view;
}
Note: instantiateItem() occurs upon screen rotation. Activity does not detect that. The hint is that the class does not have onCreateView() like the fragment class.

Categories

Resources