Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IllegalStateException in ViewPager with Views #3

Open
trofimchyk opened this issue Nov 27, 2013 · 20 comments
Open

IllegalStateException in ViewPager with Views #3

trofimchyk opened this issue Nov 27, 2013 · 20 comments

Comments

@trofimchyk
Copy link

IllegalStateException (java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.) when navigate from the last page to the first page or from the first page to the last page.

@HeGanjie
Copy link

Cache the 2 extra view, this works for me:

private final List<ImageView> looperViews = new ArrayList<ImageView>(8);
SparseArray<ImageView> cache = new SparseArray<ImageView>(2);

@Override
public void destroyItem(ViewGroup container, int pos, Object object) {
    container.removeView((View) object);
}

@Override
public Object instantiateItem(ViewGroup container, int pos) {
    ImageView page = looperViews.get(pos);
    if (page.getParent() != null) {
        ImageView cachedView = (ImageView) cache.get(pos);
        if (cachedView == null) {
            cachedView = createView(page.getDrawable());
            cache.put(pos, cachedView);
        }
        container.addView(cachedView, 0);
        return cachedView;
    } else {
        container.addView(page, 0);
        return page;
    }
}

private ImageView createView(Drawable drawable) {
    ImageView imgView = (ImageView) inflater.inflate(R.layout.looping_item, null);
    imgView.setImageDrawable(drawable);
    return imgView;
}

@ihenk
Copy link

ihenk commented Sep 25, 2014

I have the same problem, after trying many ways, still could not solve the problem.

@HeGanjie
Copy link

@ihenk This is my current solution. I don't save views, it will create when it needed:

public final List<Map<String, Object>> looperItems;

@Override
public void destroyItem(ViewGroup container, int pos, Object object) {
    container.removeView((View) object);
}

@Override
public Object instantiateItem(ViewGroup container, int pos) {
    final ImageView v = new ImageView(ctx);
    v.setScaleType(ScaleType.FIT_XY);

    Map<String, Object> map = looperItems.get(pos);
    if (map == null) {
        v.setImageResource(R.drawable.img_ad_default);
    } else {
        String imgUrl = map.get("titleImg");
        Picasso.with(ctx).load(imgUrl).error(R.drawable.img_ad_default).into(v);
    }
    container.addView(v, 0);
    return v;
}

@ihenk
Copy link

ihenk commented Sep 25, 2014

👍 谢谢!这个问题折腾我一天了,终于搞定了。我有试过InfiniteViewPager,但是只支持四个Item以上才行,用了很多方法修改还是不行。同时,我也用了很多方法改LoopViewPager,但是还是没有成功。看你地址是佛山,所以就直接用中文了... :)

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie 你的方法好像有一些问题,我多次尝试后发现,会存在图片加载错位...

@HeGanjie
Copy link

@ihenk 贴代码看一下,又或者是你的 getCount() 有问题?

@Override
public int getCount() { return looperItems.size(); }

@Override
public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; }

@ihenk
Copy link

ihenk commented Sep 25, 2014

public class NetworkViewPagerAdapter extends PagerAdapter {

private List<String> mUrls;
private DisplayImageOptions options;
protected ImageLoader imageLoader;
private ImageLoadingListener animateFirstListener;

public NetworkViewPagerAdapter(List<String> urls) {
    super();
    if (urls != null) {
        this.mUrls = urls;
    } else {
        this.mUrls = new ArrayList<String>();
    }
    options = DefaultDisplayImageOptions
            .getDefaultDisplayImageOptions(EduApplication.getInstance());
    animateFirstListener = new DefaultAnimateFirstDisplayListener();
    imageLoader = ImageLoader.getInstance();
}

@Override
public int getCount() {
    return mUrls.size();
}

@Override
public boolean isViewFromObject(View view, Object object) {
    return view == object;
}

@Override
public int getItemPosition(Object object) {
    return super.getItemPosition(object);
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    container.removeView((View) object);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
    ImageView view = new ImageView(EduApplication.getInstance());
    view.setScaleType(ScaleType.FIT_XY);
    view.setId(position);
    imageLoader.displayImage(mUrls.get(position), view, options,
            animateFirstListener);
    container.addView(view);
    return view;
}

}

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie 我用的是ImageLoader加载图片,options有设置默认图片的,所以这一块不会有问题...

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie public class DefaultDisplayImageOptions {
public static DisplayImageOptions getDefaultDisplayImageOptions(
Context context) {
//返回图片加载前的默认值
return new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_default)
.showImageForEmptyUri(R.drawable.ic_default)
.showImageOnFail(R.drawable.ic_default)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.displayer(
new RoundedBitmapDisplayer(context.getResources()
.getDimensionPixelSize(R.dimen.icon_rounded)))
.build();
}

}

@HeGanjie
Copy link

@ihenk 你先换回 android.support.v4.view.ViewPager,调通之后再替换回这个库。

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie 我试过了,用Android自带的ViewPager任何问题的...

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie 你有修改LoopPagerAdapterWrapper及LoopViewPager本身吗?

@HeGanjie
Copy link

@ihenk 没有哦 😖

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie 你那里有这个单独的DEMO吗?如果有的话,不知道是否方便发送一份至[email protected] (不方便的话,也没有关系的,还是谢谢你 :) )。主要这个已经搞了我一天了,今天其他什么也没有干,实在是不甘心>_< ...

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie 我发现一个规律是,如果未循环滚动的话,图片一直会显示正常,一旦循环滚动,就不正常了....

@HeGanjie
Copy link

@ihenk container.addView(view) 改成 container.addView(v, 0) 试试

@ihenk
Copy link

ihenk commented Sep 25, 2014

@HeGanjie 我找到原因了,

// mVpPictureHeader.setAdapter(new LoopPagerAdapterWrapper(adapter));之前用得是这包话,写错了
mVpPictureHeader.setAdapter(adapter);//正确

@TracyZhangLei
Copy link

can not call adapter.notifyDataSetChanged(), using setAdapter(new Adapter()) for instead

@OtzOrz
Copy link

OtzOrz commented Dec 21, 2016

@TracyZhangLei Thank you very much !

@goldingking
Copy link

goldingking commented May 25, 2017

The instantiateItem callback need return a new object but a reference to the same project twice, for there is reuse somewhere.
Just the first one and last position need to be reused, so we can return a new object for those.

in the instantiateItem method of your adapter, you can write like this:

if (position == 0) {
    first = new TextView(context);
    first.setText("" + position);
    container.addView(first);
    return first;
} else if (position == NUM_ITEMS - 1) {
    last = new TextView(context);
    last.setText("" + position);
    container.addView(last);
    return last;
} else {
    container.addView(views.get(position));
    return views.get(position);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants