I can only use the ViewPager to page backward and can not page forward.
I'm writint an banner,but I can only use the ViewPager to page backward and can not page forward.
This is the adapter I wrote.
class MyPagerAdapter extends PagerAdapter {
@Override
public Object instantiateItem(ViewGroup container, int position) {
int p = position % mImgRes.length;
container.addView(mListView.get(p));
return mListView.get(p);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getCount() {
return 100;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
This is an error message.
07-29 20:45:02.098 20791-20791/com.example.myfirstpro E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.example.myfirstpro, PID: 20791
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:4465)
at android.view.ViewGroup.addView(ViewGroup.java:4301)
at android.support.v4.view.ViewPager.addView(ViewPager.java:1505)
at android.view.ViewGroup.addView(ViewGroup.java:4242)
at android.view.ViewGroup.addView(ViewGroup.java:4215)
at com.example.myfirstpro.MainFragment$MyPagerAdapter.instantiateItem(MainFragment.java:62)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:1034)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1216)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1116)
at android.support.v4.view.ViewPager$3.run(ViewPager.java:273)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:892)
at android.view.Choreographer.doCallbacks(Choreographer.java:704)
at android.view.Choreographer.doFrame(Choreographer.java:637)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:878)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5628)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:853)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:737)
The program will crash when I roll forward.
This is in addition to the code other than the adapter.@Hong Duan
private ViewPager mVpScroll;
private int mImgRes[] = new int[] {
R.drawable.banner01,
R.drawable.banner02,
R.drawable.banner03
};
private List<View> mListView = new ArrayList<>();
private LayoutInflater mInfalte;
public MainFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
for (int i = 0; i < mImgRes.length; i++) {
View inflate = inflater.inflate(R.layout.fragment_main_scroll_item, null);
ImageView ivBanner = (ImageView) inflate.findViewById(R.id.iv_scroll);
ivBanner.setImageResource(mImgRes[i]);
mListView.add(inflate);
}
mInfalte = inflater;
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mVpScroll = (ViewPager) view.findViewById(R.id.vp_scroll);
mVpScroll.setAdapter(new MyPagerAdapter());
}
As the error message shows, the root cause is a child
Viewis added twice. But why this only happens when you swipe backward? I've made a test project and I think I find the reason :)When
ViewPagerscrolls, it will recycle items using itsPagerAdapter's methods:instantiateItemanddestroyItem, whenViewPagerwants to show a new item,instantiateItemis called, whenViewPagerscrolls away, the view which off the screen will be destroyed by methoddestroyItem.By default, the
ViewPagerwill keep1more item on each side for smooth scrolling, which means there are at most3items keep by theViewPager.The problem is, you are using:
to implement a "loop"
ViewPager, that means ifmImgRes.length == 3, the position 3 will show the sameViewat position 0.Now think about your case:
when
ViewPagerinited, the item0and1(right side item) are added byinstantiateItem;then scroll right a page, the item
1is shown, and the item2is added, now the item0(left side item),1,2(right side item) are kept;scroll right a page again, the item
2is shown, the item3is added, the item0is destroyed by methoddestroyItem, now the item1(left side item),2,3(right side item, the same item to0) are kept;Everything works fine if
instantiateItemanddestroyItemwork as expected, and it does work when you scroll to the right("forward"), but it does not work when you scroll to the left("backward") because the order of wheninstantiateItemanddestroyItemare executed is different! See the log:when you scroll to the right,
destroyItemexecuted first, theninstantiateItem, so it works fine, but when you scroll to the left,instantiateItemexecuted first, so when the last line of log printed, the item0is added the second time, because the item3(which share the sameViewwith item0) has not been destroyed yet, then it crashes :)The interesting thing is that if
mImgRes.length > 3, it will work fine, because when there are 4 items, it's not too late whendestroyItemexecute.So, if you want to implement
ViewPagerwith the "loop" feature, you have to think about how to work around this issue.