Implement onClickListener on fragment inside FragmentStatePagerAdapter - android

Good day,
I have ViewPager, and this is adapter:
public abstract class GalleryImageAdapter extends FragmentStatePagerAdapter {
private List<? extends UrlItem> images = new ArrayList<>();
public GalleryImageAdapter(FragmentManager fm, List<? extends UrlItem> images) {
super(fm);
this.images = images;
}
#Override
public Fragment getItem(int position) {
return giveFragment(images, position);
}
public abstract Fragment giveFragment(List<? extends UrlItem> images, int position);
#Override
public int getCount() {
return images.size();
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
Fragment fragment = (Fragment) super.instantiateItem(collection, position);
return fragment;
}
}
I have a ViewPager, which represents gallery of images. I would like to handle click on current selected child (fragment) in ViewPager.
I found something about instantiateItem, but nothing about how to handle clicks in FragmentStatePagerAdapter. I got the fragment in this method but .setOnClickListener is not found

If it's not needed for your image gallery items to have their own lifecycles (and I would imagine it's not), don't use Fragments and FragmentStatePagerAdapter. Use a RecyclerView with the appropriate adapter, as explained, for example, here.

Related

Using ViewPager inside Recyclerview won't show all pages of all items

I have some sliders inside recyclerview among some other items. this is my pager adapter:
class PagerFragmentAdapter extends FragmentStatePagerAdapter {
public PagerFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
and i call setup on binding viewholder:
setup(RecyclerView.ViewHolder holder) {
pos = holder.getAdapterPosition();
if (pagerHolder == null) {
pagerHolder = (PagerHolder) holder;
viewPager = pagerHolder.getViewPager();
adapter = new PagerFragmentAdapter(fragmentManager);
viewPager.setAdapter(adapter);
pagerHolder.bindAdapter();
} else if(adapter!=null)
adapter.notifyDataSetChanged();
}
the first slider in recyclerview is OK but others are not OK!!
non of the fragments are loaded! and if i scroll it just shows first page of pager not all of them.
I have also tried creating fragments inside getItem() method but nothing changed..

get currunt item from viewpager android

I using view pager for swipe view for android app. I build view pager Dynamically. Like add and remove item. Now i want to know how to get exactly position of view pager items.For example, I have 3 items, i want to get 3rd number position when i am in 2nd or 1st item. i used viewPager.getCurrentItem() but it return where i am.
Please suggest me how to give personal ids of every viewpager items and used it in when item is background or on screen.Thanks please help me about this, i left 2 weeks already for this. Thanks in advance
public TabsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
return new MyWebBrowser();
}
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
#Override
public int getCount() {
return COUNT_TAB;
}
}
Now this code Under my fragment class, from WebView chrom class i want to set up title as website title.
#Override
public void onReceivedTitle(WebView view, String title) {
TAB_TITLE=title;
Toast.makeText(HomeActivity.this,title,Toast.LENGTH_LONG).show();
super.onReceivedTitle(view, title);
}
take a look at this Adapter:
class MyAdapter extends FragmentStatePagerAdapter
{
private final SparseArray<WeakReference<YourFragment>> mPageReferences;
public MyAdapter(FragmentManager fm) {
super(fm);
mPageReferences = new SparseArray<WeakReference<YourFragment>>();
}
#Override
public Fragment getItem(int i) {
WeakReference<YourFragment> fragment =
new WeakReference<YourFragment>(YourFragment.newInstance());
mPageReferences.put(i, fragment);
return fragment.get();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferences.remove(position);
}
#Override
public int getCount() {
return number of fragment;
}
public YourFragment getFragment(int key) {
return mPageReferences.get(key).get();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
WeakReference<YourFragment> fragment = new WeakReference<YourFragment>((YourFragment) super.instantiateItem(container,
position));
mPageReferences.put(position, fragment);
return fragment.get();
}
}
you can easily get the reference of any pages from mPageReferences BUT be careful because it may be null because it is possible that it has not created when you call it. you can use (getFragment(int key) to get the item at the position of key)
you can know the current position from the PagerAdapter.
by calling pageAdapter.getItemPosition(itemNumber)
link to the documentation

update a fragment on ViewPager based on the fragment before

I am using ViewPager with fragments and a FragmentStatePagerAdapter, i need update my second fragment based on what the user checked in the first one, what happens is that both fragments are loaded when the fragment activity is started, so doesn't matter what the user checks on the first fragment, the second will not get updated. i've tried to override de getItemPosition with the notifyDataSetChanged for call a method to update my fragment, but it appears to be called just when it's created, i need update the second fragment when the user check the options that he want in the first fragment. Thanks
public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if(mFragments.get(position) instanceof UpdateableFragment){
notifyDataSetChanged();
}
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public int getItemPosition(Object object) {
if (object instanceof UpdateableFragment) {
((UpdateableFragment) object).customize();
}
return super.getItemPosition(object);
}
}

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);
}

Android ViewPager prepend new View

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".

Categories

Resources