片段已经在viewpager中添加了IllegalStateException [英] Fragment already added IllegalStateException in viewpager

本文介绍了片段已经在viewpager中添加了IllegalStateException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用viewpager显示图片.我基本上只需要三个片段:上一个图像进行预览,当前显示图像和下一个图像进行预览.我只想显示上一张和下一张图像的预览,当用户实际滑动到它时,它将变为完整图像.因此,我正在考虑仅使用3个片段来实现这一目标.代码如下:

I'm using viewpager to display pictures. I just need three fragments basically: previous image to preview, current display image and next image to preview. I would like to just display a preview of previous and next image, it will change to full image when user actually swipe to it. So I'm thinking of just using 3 fragment to achieve this. Code is below:

    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()来使所有三个位置在用户滑动到新页面时更新片段.

So basically, I pre-created three fragments to display previous/next preview and current image and return them for getItem(). I also notifydatasetchange() in onpageselected() to make all three position to update the fragment when user swipe to new page.

但是问题在于它会扔掉

    Fragment already added IllegalStateException

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

when the fragments are added a second time. I think it's because it's been added before. I can create a new fragment every time but I think that's wasteful. So how can I reuse the already created fragment and just update them?

谢谢, 西蒙

推荐答案

FragmentStatePagerAdapter设计建议为每个页面创建一个新的Fragment(

FragmentStatePagerAdapter design suggests creating a new Fragment for every page (see Google's example). And unfortunately you cannot readd a Fragment once it was added to a FragmentManager (what implicitly happens inside adapter), hence the exception you got. So the official Google-way is to create new fragments and let them be destroyed and recreated by the adapter.

但是,如果您想重用页面并利用ViewHolder模式的类似物,则应该坚持使用视图而不是片段.与片段不同,可以将视图从其父视图中删除并重新使用.扩展PagerAdapter并像这样实现instantiateItem():

But if you want to reuse pages and utilize an analogue of ViewHolder pattern, you should stick to views instead of fragments. Views could be removed from their parent and reused, unlike fragments. Extend PagerAdapter and implement instantiateItem() like this:

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

您应该添加一些额外的逻辑以按位置确定视图类型(因为您有3种视图类型),我想您可以弄清楚这一点.

You should add some extra logic to determine the view type by position (since you have 3 types of views), I think you can figure that out.

这篇关于片段已经在viewpager中添加了IllegalStateException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆