In the android documentation on FragmentStatePagerAdapter it is explained that the adapter can be set up like this:
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
return MyFragment.newInstance();
}
}
I would like to use this, however, I would also like to manage the Fragments that were added with a FragmentManager. How can I do this? My approach is throwing a NullPointerException.
public static class MyAdapter extends FragmentStatePagerAdapter {
private FragmentManager mFragmentManager;
public MyAdapter(FragmentManager fm) {
super(fm);
mFragmentManager = fm;
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
mFragmentManager.beginTransaction()
.add(MyFragment.newInstance(), MyFragment.TAG).commit();
return mFragmentManager.findFragmentByTag(MyFragment.TAG);
}
}
How can I do this?
You write your own PagerAdapter implementation from scratch. FragmentPagerAdapter and FragmentStatePagerAdapter will do their own fragment transactions, colliding with yours.
Related
public class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
int s = this.fragments.size();
return this.fragments.size();
}
}
Text here:
if i go from tab4 to tab2 than first control go to tab2 than it go to tab1. i could not understand how can it go to tab1?
I can see you're trying to cache the fragments into memory by using the this context. But you're not supposed to, FragmentPagerAdapter class should do it for you. Google webpage and sample # FragmentPagerAdapter. Look at sample code on that page.
Code snippet:
#Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
Notes:
Notice the call to method newInstance. Implement it in your Fragment.
Need to define a fragment subclass, sample uses ArrayListFragment.
I have a problem while changing fragments in my viewpager. In specific, my fragment is replaced with an empty one.
Here's some code:
public void replaceFragment() {
supportManager.getFragments().set(1,getNewFragment()));
pageAdapter.notifyDataSetChanged();
menuControl.setView(1);//this just changes the fragment to be shown
}//here is where i change the fragment
//and here is the adapter
public class SimplePageAdapter extends FragmentPagerAdapter{
final List<Fragment> fragment;
final FragmentManager fragmentManager;
public SimplePageAdapter(FragmentManager fm, List<Fragment> fragment) {
super(fm);
fragmentManager = fm;
this.fragment=fragment;
}
#Override
public Fragment getItem(int arg0) {
return fragment.get(arg0);
}
#Override
public int getCount() {
return fragment.size();
}
#Override
public int getItemPosition(Object o) {
return POSITION_NONE;//I read that this is for making notifyDataSet work
}
}
I created an activity, when I start an activity which implements viewpager, the viewpager created various fragments. I want to use different layouts for each fragment, but the problem is that the fragments is not show inside viewpager.
DataActivity.java
public class DataActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
ViewPager myViewPager;
MyPagerAdapter myPagerAdapter;
super.onCreate(savedInstanceState);
setContentView(R.layout.data_activity);
myViewPager = (ViewPager) findViewById(R.id.viewpager);
mytPagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
myViewPager.setAdapter(myPagerAdapter);
}
private class MyPagerAdapter extends FragmentPagerAdapter{
int numberOfPages = 5;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int index) {
return DataFirstFragment.newInstance();
}
#Override
public int getCount() {
return numberOfPages;
}
}
}
DataFirstFragment is not shown inside viewpager
Anyone can help me please...!
I found solution for above problem, Only replce this
return DataFirstFragment.newInstance();
with:
return new DataFirstFragment();
In Below code i don't see where do you add fragment to adaptor ? ?
private class MyPagerAdapter extends FragmentPagerAdapter{
int numberOfPages = 5;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int index) {
return DataFirstFragment.newInstance();
}
#Override
public int getCount() {
return numberOfPages;
}
}
SO when viewPager asks adaptor to get item , it does not have anything.
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);
}
I want to prepend a new View as first page of my ViewPager.
My adapter looks like this:
public class PagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragments;
public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int index) {
return fragments.get(index);
}
#Override
public int getCount() {
return fragments.size();
}
public void add(int i, ImageFileObject imageFile) {
ImageViewFragment f = new ImageViewFragment();
f.setImage(imageFile);
fragments.add(0, f);
notifyDataSetChanged();
}
public void add(ImageFileObject imageFile) {
ImageViewFragment f = new ImageViewFragment();
f.setImage(imageFile);
fragments.add(f);
notifyDataSetChanged();
}
}
But when calling add(0, aImageFile) the item is not prepended to the fragment list. (It's not even appended).
Any ideas?
Update: The problem that you described in comment is real, I missed it in first testing. After analyzing the source code of FragmentPagerAdapter I realized that all we need to do is to Override getItemId() in a way that it won't return same id for different fragment items. E.g. current default implementation would just return position as an id for fragment which won't work for this case:
public long getItemId(int position) {
return position;
}
I am updating this answer, please have a look. As before I have tested this code and the problem you described is not happening now.
Only thing you need is not to keep reference of fragments by yourself in List, This is done for you by FragmentPagerAdapter. And as far as I know its not a good practise either. And also even if you return POSITION_NONE from getItemPosition() as suggested by other answer(s), you will end up with Exception
Caused by: java.lang.IllegalStateException: Can't change tag of fragment.
This is because you are trying to reposition alive Fragments in your List by adding a fragment at 0th index (which causes other fragments to reposition) and ViewPager assigns tags based on position.
Keeping all this in mind, here is a tested and working modified adapter:
public class PagerAdapter extends FragmentPagerAdapter {
public static class FragmentInfo {
public String classz;
public ImageFileObject imageFile;
public static long IDS;
public long id;
public FragmentInfo(){
id = IDS++;
}
}
private final List<FragmentInfo> fragments;
private Context context;
public PagerAdapter(FragmentManager fm, List<FragmentInfo> fragments,
Context context) {
super(fm);
this.fragments = fragments;
this.context = context;
}
#Override
public Fragment getItem(int index) {
FragmentInfo info = fragments.get(index);
ImageViewFragment frag = (ImageViewFragment) Fragment.instantiate(
context, info.classz, /* null arguments*/ null);
frag.setImage(info.imageFile);
return frag;
}
#Override
public long getItemId(int position) {
return fragments.get(position).id;
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public void add() {
FragmentInfo f = new FragmentInfo();
f.classz = ImageViewFragment.class.getName();
fragments.add(0, f);
notifyDataSetChanged();
}
}
Please change your code accordingly.
The problem is actually with notifyDataSetChanged. Just add to your Adapter:
public int getItemPosition(Object object) {
return POSITION_NONE;
}
However, I think you will get other problems when the Adapter actually tries to call getItem again. These problems will be in the lines of "Fragment Already Added".