是否可以访问ViewPager正在查看的当前片段?

时间:2011-12-21 08:54:51

标签: android android-fragments android-viewpager

我有一个ViewPager和三个Fragment的应用。我正在试图找出如何让当前Fragment被查看,以便我可以得到它的论点。

我有OnPageChangeListener抓取当前页面索引,但

ViewPager.getChildAt(int position);

返回View。此View与当前Fragment之间的关系是什么?

11 个答案:

答案 0 :(得分:46)

我终于找到了适合我的an answer。基本上,您可以使用标签“android:switcher:”+ R.id.viewpager +“:0”访问viewPager页面的片段。

答案 1 :(得分:18)

我反过来解决了这个问题。 我没有从活动中搜索片段,而是在它的所有者活动的onAttach()方法中注册片段,并在onStop()方法中取消注册。 基本理念:

<强>片段:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try{
        mActivity = (IMyActivity)activity;
    }catch(ClassCastException e){
        throw new ClassCastException(activity.toString() +" must be a IMyActivity");
    }

    mActivity.addFragment(this);
}

@Override
public void onStop() {
    mActivity.removeFragment(this);
    super.onStop();
}

<强> IMyActivity:

public interface IFriendActivity {
    public void addFragment(Fragment f);
    public void removeFragment(Fragment f); 
}

<强> MyActivity:

public class MyActivity implements IMyActivity{

    [...]

    @Override
    public void addFragment(Fragment f) {
        mFragments.add(f);
    }

    @Override
    public void removeFragment(Fragment f) {
        mFragments.remove(f);
    }

}

答案 2 :(得分:5)

编辑 - 不要这样做。如果您有诱惑,请阅读评论,说明为什么这是一个坏主意。

奇怪的是,你还在努力解决这个问题:

扩展FragmentPagerAdapter。在构造函数中,构建所需的Fragments并将它们存储在Fragments的List(array / ArrayList)中。

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

然后对于getItem(int position),您可以执行类似

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

我不确定这是否是普遍接受的做法,但它对我有用。

修改

这真的不是一个好方法。如果您计划处理方向更改或您的应用程序进入后台,那么这可能会破坏您的代码。有关详细信息,请阅读此答案下方的评论。而是使用@James的回答

答案 3 :(得分:4)

是的,如果您使用FragmentStatePagerAdapter,则可以。

ViewPager vp;
//...
YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());

答案 4 :(得分:3)

请不要使用

让您的适配器扩展以下FragmentStatePagerWithCurrentAdapter类,而不是实现getItem将相同的代码实现到getItemAtIndex

ViewPager OnPageChangeListener设置为适配器的实例。

当您需要访问当前片段时,只需拨打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;
    }

}

我使用以下博文作为参考:http://tamsler.blogspot.com/2011/11/android-viewpager-and-fragments-part-ii.html

答案 5 :(得分:1)

这里已经解释过:http://developer.android.com/guide/topics/fundamentals/fragments.html

在OnCreateView中,您必须返回一个视图来为您的片段绘制UI,我认为这是关系。

此问题可能类似:Get focused View from ViewPager

答案 6 :(得分:1)

你可以这样做: - 在视图分页器适配器的类范围(例如PagerAdapter,FragmentStatePagerAdapter ...)覆盖方法instantiateItem:

@Override
public Object instantiateItem(ViewGroup container, int position) {
        final Fragment frag = (Fragment) super.instantiateItem(container, position);
        if(frag instanceof ListNoteOfTypeFragment){                
            final ListNoteOfTypeFragment listNoteOfTypeFragment = (ListNoteOfTypeFragment) frag;
            //do whatever you want with your fragment here
            listNoteOfTypeFragment.setNoteChangeListener(mListener);
        }
        return frag;
    }    

答案 7 :(得分:1)

无缝合作的确定答案(但小黑客):

页面片段布局中的某处:

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

在片段的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;

以及从ViewPager返回Fragment的方法(如果存在):

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

答案 8 :(得分:0)

Jorge Garcia's FragmentStatePagerWithCurrentAdapter是一个非常好的解决方案,但需要稍微改进一下。如果活动被破坏并重新创建以响应配置更改或类似的事件,则不会为片段管理器保存和检索的片段调用getItem。所以我在我的子类中正常覆盖getItem,并将以下内容放入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;
}

每次访问该位置的片段时都会调用instantiateItem。

答案 9 :(得分:0)

或者只是将所有碎片保存在地图中:

public class MyFragment extends Fragment implements OnPageChangeListener {

    private ViewPager viewPager;
    private FragmentStatePagerAdapter viewAdapter;
    private View rootView;
    private Map<Integer, Fragment> fragments = new HashMap<Integer, Fragment>();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        rootView = inflater.inflate(R.layout.introdution, container, false);

        viewPager = (ViewPager) rootView.findViewById(R.id.pager);
        viewAdapter = new ViewAdapter(getFragmentManager());
        viewPager.setAdapter(viewAdapter);
        viewPager.addOnPageChangeListener(this);

        return rootView;

    }

    private class ViewAdapter extends FragmentStatePagerAdapter {

        public ViewAdapter(FragmentManager fragmentManager) {
            super(fragmentManager);
        }

        @Override
        public Fragment getItem(int position) {

            Fragment result = null;

            switch (position) {
                case 0: result = Fragment1.newInstance(); break;
                case 1: result = Fragment2.newInstance(); break;
            }

            if (result != null)
                fragments.put(position, result);

            return result;

        }

        @Override
        public int getCount() {

            return 2;
        }

    }

    @Override
    public void onPageScrollStateChanged(int arg0) {
    }

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

    @Override
    public void onPageSelected(int position) {

        Fragment currentFragment = fragments.get(position);

    }

}

答案 10 :(得分:-2)

我认为使用此

有更好的方法

Log.i(TAG, "getCurrentItem " + mViewPager.getCurrentItem());

可以获取当前的显示片段页面。