Viewpager + FragmentStatePagerAdapter + Fragment not working - android

I have a FragmentList with some items. If I click an item the appropriate Fragment will open which contains a Viewpager. No problem so far but if I go back to the List and click the item again the method getItem(int position) is not called anymore.
Here a link with a similar problem:
Display fragment viewpager within a fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_fragment_runtime, container, false);
mViewPager = (ViewPager) view.findViewById(R.id.pager);
indicator = (TitlePageIndicator) view.findViewById(R.id.indicator);
MyFragmentPagerAdapter mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getActivity().getSupportFragmentManager());
mViewPager.setAdapter(mMyFragmentPagerAdapter);
indicator.setViewPager(mViewPager);
return view;
}
class MyFragmentPagerAdapter extends FragmentStatePagerAdapter implements TitleProvider {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public String getTitle(int position) {
return muxbusTitles[position];
}
#Override
public Fragment getItem(int location) {
return muxbusFragmentList.get(location);
}
#Override
public int getCount() {
return muxbusTitles.length;
}
}
return view;
}
Edit:
If someone is interested,the solution was to extends from PagerAdapter instead of FragmentStatePagerAdpater because the Viewpager is already in a Fragment..

I did have similar problem and after scratching my head for quite some time i made an my own understanding (assumption) that ViewPager is keeping the reference of its child fragments into memory even the hosted Fragment or Activity is destroyed (didn't tested with Activity). So i wrote this method freeFragmentsFromViewPager(). You need to call it from onDestroy() of your Fragment.
/**
* This method free the child fragments from ViewPager as ViewPager keeps the reference
* of child fragments into memory and next time when you again come to visit view pager it won't show the fragment layout
* because it has the reference to the fragment whilst the fragment's view was already destroyed.
*/
private void freeFragmentsFromViewPager()
{
for(int i = 0; i < TabsFragmentPagerAdapter.fragments.length; i++)
{
Fragment fragment = TabsFragmentPagerAdapter.fragments[i];
if(fragment != null)
{
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();
TabsFragmentPagerAdapter.fragments[i] = null;
}
}
}
And this is my Adapter code
public class TabsFragmentPagerAdapter extends FragmentPagerAdapter
{
public static final int NUM_TABS = 3;
public static Fragment[] fragments = new Fragment[NUM_TABS];
public TabsFragmentPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position)
{
Log.e("TabsFragmentPagerAdapter", "getItem");
Fragment fragment = TabsFragmentFactory.newInstace(position);
fragments[position] = fragment;
return fragment;
}
#Override
public int getCount()
{
return NUM_TABS;
}
#Override
public CharSequence getPageTitle(int position)
{
return TabsFragmentFactory.getName(position);
}

Related

What thread which Android use when fragment recreate from scratch?

I have a ViewPager.When some data changed,i set the adapter for the ViewPager again by call ViewPager.setAdapter(new Adapter).What i wonder is,the Fragment is re-create (it jump on onDestroyView and then onCreateView) and my Edittext cannot set again the text.And if i remove all Fragment from FragmentTransaction and then setAdapter,the Fragment create a new one -> my Edittext set the text well.So is Fragment recreate itselft NOT from UI thread? ( Because i try the edditext.post and my edditext from first scenario work).Here is the code
Adapter:
public class PagerAdapter extends FragmentPagerAdapter {
private final ArrayList<Fragment> fmAct;
public PagerAdapter(FragmentManager supportFragmentManager, ArrayList<Fragment> fm) {
super(supportFragmentManager);
fmAct = fm;
}
#Override
public Fragment getItem(int position) {
return fmAct.get(position);
}
#Override
public int getCount() {
return fmAct.size();
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public CharSequence getPageTitle(int position) {
return ((PrFragment) getItem(position)).getFragmentName();
}
what i do when re-set the adapter
fm.clear();
fragmentAttendanceCome = new FragmentAttendanceCome();
fragmentAttendanceCome.setFragmentName(getString(R.string.title_attendance));
fragmentAttendanceCome.setParentActivity(this);
fragmentAssessment = new FragmentAssessment();
fragmentAssessment.setFragmentName(getString(R.string.daily_evaluation));
fragmentAssessment.setParentActivity(this);
fragmentInfo = new FragmentInfo();
fragmentInfo.setParentActivity(this);
fragmentInfo.setFragmentName(getString(R.string.title_infomation));
fm.add(fragmentAttendanceCome);
fm.add(fragmentAssessment);
fm.add(fragmentInfo);
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager(), fm));
This is my fragment :
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
textview.setText(data)
// i already Bind it but i lazy to copy it,everything work well
}

getItem in FragmentStatePagerAdapter never called when instantiating from a Fragment

I'm using a Fragment on my Activity that will have a picture "swiper". I've created a FragmentStatePagerAdapter which I'm trying to call from this Fragment and for some reason my getItem() method is never being called.
I've searched and found that I need to use getChildFragmentManager() when instantiating my FragmentStatePagerAdapter because I'm calling it from a Fragment. I've tried this as well as getSupportFragmentManager() with no luck from either.
Any ideas?
here's my Fragment that I'm using on my MainActivity with the method that shoudl setup the FragmentStatePagerAdapter:
public class PhotoFlipper extends Fragment {
// properties and fields
// primitive types
String currentImage;
int friendShareType = 0;
ImageView share;
ViewPager pager;
PhotoFlipperItemAdapter pagerAdapter;
LatLng itemPosition;
Activity activity;
FragmentActivity fragActivity;
public ArrayList<MarkerModel> picsAndVids;
// end properties and fields
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View photoFlipperFragmentView = inflater.inflate(R.layout.photo_flipper_layout, container, false);
InitializeFragment(photoFlipperFragmentView);
return photoFlipperFragmentView;
}
private void InitializeFragment(View photoFlipperFragmentView) {
activity = getActivity();
fragActivity = (FragmentActivity)activity;
pager = (ViewPager)photoFlipperFragmentView.findViewById(R.id.photoflipper_pager);
share = (ImageView)photoFlipperFragmentView.findViewById(R.id.photoflipper_share);
share.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
IPictureFlipper iPictureFlipper = (IPictureFlipper)activity;
iPictureFlipper.ShareVideoOrImage(friendShareType, itemPosition, currentImage);
}
});
}
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
pager.setVisibility(View.GONE);
}
}
public void SetTappedPicture(int index) {
pagerAdapter = new PhotoFlipperItemAdapter(getChildFragmentManager(), picsAndVids, picsAndVids.size());
pager.setAdapter(pagerAdapter);
pager.setCurrentItem(index);
pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
});
}
}
And here's my FragmentStatePagerAdapter:
public class PhotoFlipperItemAdapter extends FragmentStatePagerAdapter {
ArrayList<MarkerModel> _markers;
int NUM_PAGES;
String TAG = "home";
public PhotoFlipperItemAdapter(FragmentManager fm, ArrayList<MarkerModel> markers, int numpages){
super(fm);
Log.d(TAG,"in adapter in constructor");
_markers = markers;
NUM_PAGES = numpages;
}
#Override
public Fragment getItem(int position) {
Log.d(TAG,"in adapter in get item");
Fragment fragment = PhotoFlipperItemFragment.create(position, _markers);
return fragment;
}
#Override
public int getCount() {
Log.d(TAG,"in adapter in get count: "+NUM_PAGES);
return NUM_PAGES;
}
}
logcat is showing me that NUM_PAGES is > 0 so that's not my issue. I see my log in the constructor and in getCount() but nothing in getItem().
TIA
I got this sorted out. I was hiding my fragment in my InitializeActivity() right after I added it to my FragmentManager so it was never fully building the Fragment with the ViewPager etc.
I'm going to have to come up with a different solution for hiding/showing the fragment but that was my problem.

Android fragment empty in viewpager when I come back in

I have a navigation drawer in which there is a ViewPager that extends a Fragment. When i click the item of drawer i open the viewpager in which there are three fragments. It works perfectly. but if i click again the same drawer item to open the viewpager another one time, the viewpager is empty.. I can see the tabs but not the fragments in there. This is the Viewpager:
public class ViewPagerManager extends Fragment {
public static ViewPagerManager instance = null;
Toolbar toolbar;
public static PagerSlidingTabStrip tabs;
public MyPagerAdapter adapter;
public ViewPager pager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_tabbed, container, false);
instance = this;
adapter = new MyPagerAdapter(getFragmentManager());
pager = (ViewPager)view.findViewById(R.id.pager);
tabs = (PagerSlidingTabStrip)view.findViewById(R.id.tabs);
pager.setAdapter(adapter);
tabs.setViewPager(pager);
pager.setOffscreenPageLimit(3);
adapter.notifyDataSetChanged();
pager.invalidate();
return view;
}
public class MyPagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = { "One", "Two", "Three" };
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
// Top Rated fragment activity
return new FragmentOne();
case 1:
// Games fragment activity
return new FragmentTwo();
case 2:
// Games fragment activity
return new FragmentThree();
}
return null;
}
}
}
Is it normal? How can i solve? If could help i'm using PagerSlidingTabStrip library.
Use this code
adapter = new MyPagerAdapter(getChildFragmentManager());
instead of
adapter = new MyPagerAdapter(getFragmentManager());
Try to redraw the last selected page when you return to the fragment. I think the viewpager is not cached and you need to reselect the last item. You can override the onresume method.

Access to view into Fragment

I'm trying to start an animation when the fragment is showed on screen(I'm working with a ViewPager).
This a part of my code
public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
private Map<Integer, String> mFragmentTags;
private FragmentManager mFragmentManager;
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
mFragmentManager = fm;
mFragmentTags = new HashMap<Integer, String>();
}
public ScreenSlidePageFragment getFragment(int position) {
String tag = mFragmentTags.get(position);
if (tag == null)
return null;
return (ScreenSlidePageFragment) mFragmentManager.findFragmentByTag(tag);
}
#Override
public Fragment getItem(int position) {
return ScreenSlidePageFragment.create(position);
}
#Override
public int getCount() {
return NUM_PAGES;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object obj = super.instantiateItem(container, position);
if (obj instanceof Fragment) {
// record the fragment tag here.
Fragment f = (Fragment) obj;
String tag = f.getTag();
mFragmentTags.put(position, tag);
System.out.println("holi");
}
return obj;
}
}
public class ScreenSlideActivity extends FragmentActivity {
(...)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
(...)
SimpleOnPageChangeListener mPageChangelistener = new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When changing pages, reset the action bar actions since they are dependent
// on which page is currently active. An alternative approach is to have each
// fragment expose actions itself (rather than the activity exposing actions),
// but for simplicity, the activity provides the actions in this sample.
ScreenSlidePageFragment currentFgm = mPagerAdapter.getFragment(position);
Animation animacion = AnimationUtils.loadAnimation(ScreenSlideActivity.this, R.anim.glasses);
currentFgm.getView().findViewById(R.id.image).startAnimation(animacion);
invalidateOptionsMenu();
}
(...)
The problem is when onPageSelected is called returns a NullPointer Exception in
currentFgm.getView().findViewById(R.id.image).startAnimation(animacion);
How could I start the animation when the fragment is showed on screen?
If you are trying to add animation to the ViewPager then you can implement the ViewPager.PageTransformer interface and supply it to the view pager to display a different animation than the default screen slide animation.
ViewPager mPager = (ViewPager) findViewById(R.id.pager);
...
mPager.setPageTransformer(true, new CustomTransformer());
You will find here two examples of PagerTransformers.

Fragments in viewpager

I have viewpager with some fragments and i set to each fragment my model class according which UI of fragment should be edited. That model class i set to fragment at constructor before i add that fragment to FragmentStatePagerAdapter. My problem is that after rotating screen or when system kills my application and i restore it, my fragment are recreated by system and my model class instance is lost. Even if I set new FragmentStatePagerAdapter, fragments created by system are visible. Is there any right way of achive that i create new instances of my fragments and place them into viewpager? I tried so many thinks like removing fragments from FragmentManager, adding Adapter to viewpager again, change FragmentStatePagerAdapter only to FragmentPagerAdapter and nothing helped.
My activity class with loading model classes in loader from some resource:
List<Fragment> visibleFragment = new ArrayList<Fragment>();
for (Screen screen : wizard.screens) {
if (screen.visible) {
visibleFragment.add(new ScreenUI(screen));
}
}
viewPager.setAdapter(null);
viewPager.setAdapter(new WizardPagerAdapter(getSupportFragmentManager(), visibleFragment));
My FragmentStatePagerAdapter
public class WizardPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments;
private final int count;
public WizardPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
count = mFragments.size();
}
#Override
public Fragment getItem(int index) {
return mFragments.get(index);
}
#Override
public int getCount() {
return count;
}
}
try add in Manifest android:configChanges="orientation|keyboardHidden|screenSize" to activity.
OR something like that
public class ViewPagerTaskAdapter extends FragmentStatePagerAdapter {
Map<Integer, FragmentViewTask> fragmentsTask = new HashMap<Integer, FragmentViewTask>();
#Override
public Fragment getItem(int arg0) {
FragmentViewTask myFragment = FragmentViewTask.newInstance(arg0,
tasks.get(arg0));
fragmentsTask.put(arg0, myFragment);
return myFragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
fragmentsTask.remove(position);
}
public FragmentViewTask getFragment(int key) {
return fragmentsTask.get(key);
}
#Override
public int getCount() {
if (tasks != null)
return tasks.size();
return 0;
}
}
Have you tried using onRetainInstance(true) on your Fragments?
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}

Categories

Resources