片段已在viewpager中添加了IllegalStateException

时间:2015-05-17 23:31:44

标签: android-fragments android-viewpager illegalstateexception fragmentstatepageradapter

我使用viewpager来显示图片。我基本上只需要三个片段:前一个要预览的图像,当前的显示图像和下一个要预览的图像。我想只显示上一张和下一张图片的预览,当用户实际滑动到它时,它会变为完整图像。所以我想到只使用3个片段来实现这一目标。代码如下:

    private class ImagePagerAdapter extends FragmentStatePagerAdapter implements ViewPager.OnPageChangeListener {
    private ImageFragment mImageFragment;
    private ImagePreviewFragment mPreviousPreviewFragment;
    private ImagePreviewFragment mNextPreviewFragment;

    public ImagePagerAdapter(FragmentManager fm, ImageFragment image, ImagePreviewFragment previous, ImagePreviewFragment next) {
        super(fm);
        mImageFragment = image;
        mPreviousPreviewFragment = previous;
        mNextPreviewFragment = next;
    }

    @Override
    public Fragment getItem(int position) {
        if (position == mPager.getCurrentItem()) {
            mImageFragment.display(position);
            return mImageFragment;
        }

        if (position < mPager.getCurrentItem()) {
            mPreviousPreviewFragment.display(position - 1);
            return mPreviousPreviewFragment;
        }
        mNextPreviewFragment.display(position + 1);
        return mNextPreviewFragment;
    }


    @Override
    public int getCount() {
        return 100;
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        Log.d(TAG, "onPageScrolled");
    }

    @Override
    public void onPageSelected(final int position) {
        Log.d(TAG, "onPageSelected " + position);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                notifyDataSetChanged();
            }
        }, 500);
    }


    @Override
    public void onPageScrollStateChanged(int state) {
        Log.d(TAG, "onPageScrollStateChanged " + state);
    }

    @Override
    public int getItemPosition(Object item) {
        return POSITION_NONE;
        //return POSITION_UNCHANGED;
    }
}

基本上,我预先创建了三个片段来显示上一个/下一个预览和当前图像,并将它们返回给getItem()。我还在onpageselected()中使用notifydatasetchange()来使用户滑动到新页面时更新片段的所有三个位置。

但问题是它会抛出

    Fragment already added IllegalStateException

第二次添加片段时。我认为这是因为它之前被添加过了。我每次都可以创建一个新片段,但我觉得这很浪费。那么如何重用已经创建的片段并更新它们呢?

谢谢, 西蒙

1 个答案:

答案 0 :(得分:3)

FragmentStatePagerAdapter设计建议为每个页面see Google's example创建一个新的Fragment。不幸的是,一旦将Fragment添加到FragmentManager(适配器内隐含的内容),您就无法读取PagerAdapter,因此您将面临例外。所以官方的谷歌方式是创建新的片段,让它们被适配器销毁和重新创建。

但是如果你想重用页面并使用ViewHolder模式的模拟,你应该坚持使用视图而不是片段。与片段不同,视图可以从其父级中删除并重用。像这样扩展instantiateItem()并实施@Override public Object instantiateItem(ViewGroup container, final int position) { //determine the view type by position View view = viewPager.findViewWithTag("your_view_type"); if (view == null) { Context context = container.getContext(); view = LayoutInflater.from(context).inflate(R.layout.page, null); view.setTag("your_view_type"); } else { ViewGroup parent = (ViewGroup) item.getParent(); if (parent != null) { parent.removeView(item); } } processYourView(position, view); container.addView(view, MATCH); return view; }

        drop_persona1.Items.Clear();
        string valor = drop_area.SelectedValue;

            List<string> allUsers = new List<string>();

       PrincipalContext ctx2 = new PrincipalContext(ContextType.Domain, "xxxxxxxx",
                                                        valor);


            UserPrincipal qbeUser2 = new UserPrincipal(ctx2);
            qbeUser2.Enabled = true; // activo para autenticacion

            PrincipalSearcher srch2 = new PrincipalSearcher(qbeUser2);
            srch2.QueryFilter = qbeUser2;    

            foreach (var found2 in srch2.FindAll().OrderBy(x=> x.DisplayName))
            {
                ListItem lst_user = new ListItem(found2.DisplayName, found2.SamAccountName);
                drop_persona1.Items.Insert(drop_persona1.Items.Count, lst_user);
            }

        //}
    }

您应该添加一些额外的逻辑来按位置确定视图类型(因为您有3种类型的视图),我想您可以解决这个问题。