Is it possible to access the current Fragment bein

2019-01-10 14:05发布

I have an app with a ViewPager and three Fragments. I'm trying to figure out how to get the current Fragment being viewed so I can get at its arguments.

I have an OnPageChangeListener grabbing the current page index, but

ViewPager.getChildAt(int position);

returns a View. What's the relationship between this View and the current Fragment?

11条回答
甜甜的少女心
2楼-- · 2019-01-10 14:12

Edit - Don't do this. If you're tempted to, read the comments for why it's a bad idea.

On the odd-chance you're still trying to solve this problem:

Extend FragmentPagerAdapter. In the constructor, build the Fragments you need and store them in a List (array/ArrayList) of Fragments.

private final int numItems = 3;
Fragment[] frags;

public SwipeAdapter (FragmentManager fm) {
    super(fm);

    //Instantiate the Fragments
    frags = new Fragment[numItems];

    Bundle args = new Bundle();
    args.putString("arg1", "foo");

    frags[0] = new MyFragment();
    frags[1] = new YourFragment();
    frags[2] = new OurFragment();
    frags[2].setArguments(args);
}

Then for getItem(int position), you can do something like

public Fragment getItem(int position) {
    return frags[position];
}

I'm not sure if this is the generally accepted way of doing it but it worked for me.

Edit

This is really not a good way to go. If you plan on handling orientation changes or your app going into the background, then this will probably break your code. Please read the comments below this answer for more info. Rather use @James 's answer

查看更多
别忘想泡老子
3楼-- · 2019-01-10 14:12

PLEASE DON'T USE THIS

Make your adapter extend the following FragmentStatePagerWithCurrentAdapter class and instead of implementing getItem implement the same code into getItemAtIndex

Set the ViewPager OnPageChangeListener, to the instance of the adapter.

When you need to access the current Fragment you just call adapter.getCurrentItem().

package your.package;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.SparseArray;
import android.view.ViewGroup;

public abstract class FragmentStatePagerWithCurrentAdapter 
extends FragmentStatePagerAdapter 
implements OnPageChangeListener {
    int currentPage = 0;

    private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>();

    public FragmentStatePagerWithCurrentAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public final Fragment getItem(int index) {
        Fragment myFragment = getItemAtIndex(index);
        mPageReferenceMap.put(index, myFragment);
        return myFragment;
    }

    public abstract Fragment getItemAtIndex(int index);

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {

        super.destroyItem(container, position, object);

        mPageReferenceMap.remove(Integer.valueOf(position));
    }

    public Fragment getCurrentItem() {
        return mPageReferenceMap.get(currentPage);
    }

    @Override
    public void onPageScrollStateChanged(int arg0) {

    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {

    }

    @Override
    public void onPageSelected(int newPageIndex) {
        currentPage = newPageIndex;
    }

}

I used as reference the following blog post: http://tamsler.blogspot.com/2011/11/android-viewpager-and-fragments-part-ii.html

查看更多
在下西门庆
4楼-- · 2019-01-10 14:13

Definitive answer that works seamlessly (but small hack):

somewhere in page fragment's layout:

<FrameLayout android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:id="@+id/fragment_reference">
     <View android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/>
</FrameLayout>

in fragment's onCreateView():

...
View root = inflater.inflate(R.layout.fragment_page, container, false);
ViewGroup ref = (ViewGroup)root.findViewById(R.id.fragment_reference);
ref.setTag(this);
ref.getChildAt(0).setTag("fragment:" + pageIndex);
return root;

and method to return Fragment from ViewPager, if exists:

public Fragment getFragment(int pageIndex) {        
        View w = mViewPager.findViewWithTag("fragment:" + pageIndex);
        if (w == null) return null;
        View r = (View) w.getParent();
        return (Fragment) r.getTag();
}
查看更多
孤傲高冷的网名
5楼-- · 2019-01-10 14:14

Yes, it's possible if you are using FragmentStatePagerAdapter.

ViewPager vp;
//...
YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
查看更多
在下西门庆
6楼-- · 2019-01-10 14:20

I finally found an answer that worked for me. Basically, you can access the fragment for a viewPager page by using the tag "android:switcher:"+R.id.viewpager+":0".

查看更多
你好瞎i
7楼-- · 2019-01-10 14:21

Jorge Garcia's FragmentStatePagerWithCurrentAdapter is a very good solution but it needs a minor improvement. In case the activity gets destroyed and re-created in response to a configuration change or something like that the getItem will not be called for the fragments that were saved and retrieved by the fragment manager. So I override getItem normally in my subclass and I put the following in the FragmentStatePagerWithCurrentAdapter

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object item = super.instantiateItem(container, position);
    if ( item instanceof Fragment ) {
        pageReferenceMap.put(position, (Fragment)item);
    }
    return item;
}

The instantiateItem is called every time the fragment in that position is accessed.

查看更多
登录 后发表回答