我只能用ViewPager向后翻页,不能向前翻页
I can only use the ViewPager to page backward and can not page forward
我只能用ViewPager向后翻页,不能向前翻页
running image
我正在写横幅,但是我只能用ViewPager向后翻页,不能向前翻页。
这是我写的适配器。
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);
}
}
这是一条错误消息。
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.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)
前滚时程序会崩溃
这是除了适配器以外的代码。@段洪
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());
}
如错误消息所示,根本原因是子 View
添加了两次。但为什么只有当你向后滑动时才会发生这种情况?我做了一个测试项目,我想我找到了原因:)
当 ViewPager
滚动时,它将使用其 PagerAdapter
的方法回收项目:instantiateItem
和 destroyItem
,当 ViewPager
想要显示新项目,instantiateItem
被调用,当ViewPager
滚动离开时,离开屏幕的视图将被方法destroyItem
销毁。
默认情况下,ViewPager
将在每一侧保留 1
个项目以便平滑滚动,这意味着最多 3
项由 ViewPager
.
保存
问题是,您正在使用:
int p = position % mImgRes.length;
实现一个"loop"ViewPager
,这意味着如果mImgRes.length == 3
,位置3将在位置0显示相同的View
。
现在想想你的情况:
当 ViewPager
初始化时,0
和 1
(右侧项)由 instantiateItem
;
添加
然后向右滚动一页,显示项目1
,并添加项目2
,现在是项目0
(左侧项目) , 1
, 2
(右侧项)保留;
再次向右滚动一页,显示项目2
,添加项目3
,项目0
被方法[=16]销毁=], 现在项目 1
(左侧项目), 2
, 3
(右侧项目, 与 0
相同的项目)被保留;
如果 instantiateItem
和 destroyItem
按预期工作,一切正常,当您向右滚动时它确实有效("forward"),但当您滚动时它不起作用左边("backward")因为instantiateItem
和destroyItem
的执行顺序不一样!查看日志:
07-30 22:00:04.385 26064-26064/com.example.test D/xxxxx: instantiateItem: 0
07-30 22:00:04.388 26064-26064/com.example.test D/xxxxx: instantiateItem: 1
07-30 22:00:17.693 26064-26064/com.example.test D/xxxxx: instantiateItem: 2
07-30 22:00:18.743 26064-26064/com.example.test D/xxxxx: destroyItem: 0
07-30 22:00:18.744 26064-26064/com.example.test D/xxxxx: instantiateItem: 3
07-30 22:00:26.477 26064-26064/com.example.test D/xxxxx: instantiateItem: 0 < -- crash!!!
07-30 22:00:18.743 26064-26064/com.example.test D/xxxxx: destroyItem: 3
当你向右滚动时,destroyItem
先执行,然后instantiateItem
,所以它工作正常,但是当你向左滚动时,instantiateItem
先执行,所以当打印的最后一行日志,第二次添加了项目0
,因为项目3
(与项目0
共享相同的View
)还没有被销毁然而,然后它崩溃了:)
有趣的是,如果mImgRes.length > 3
,它会正常工作,因为当有4个项目时,destroyItem
执行时还不算太晚。
因此,如果您想使用 "loop" 功能实现 ViewPager
,则必须考虑如何解决此问题。
我只能用ViewPager向后翻页,不能向前翻页
running image
我正在写横幅,但是我只能用ViewPager向后翻页,不能向前翻页。
这是我写的适配器。
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);
}
}
这是一条错误消息。
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.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)
前滚时程序会崩溃
这是除了适配器以外的代码。@段洪
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());
}
如错误消息所示,根本原因是子 View
添加了两次。但为什么只有当你向后滑动时才会发生这种情况?我做了一个测试项目,我想我找到了原因:)
当 ViewPager
滚动时,它将使用其 PagerAdapter
的方法回收项目:instantiateItem
和 destroyItem
,当 ViewPager
想要显示新项目,instantiateItem
被调用,当ViewPager
滚动离开时,离开屏幕的视图将被方法destroyItem
销毁。
默认情况下,ViewPager
将在每一侧保留 1
个项目以便平滑滚动,这意味着最多 3
项由 ViewPager
.
问题是,您正在使用:
int p = position % mImgRes.length;
实现一个"loop"ViewPager
,这意味着如果mImgRes.length == 3
,位置3将在位置0显示相同的View
。
现在想想你的情况:
当
添加ViewPager
初始化时,0
和1
(右侧项)由instantiateItem
;然后向右滚动一页,显示项目
1
,并添加项目2
,现在是项目0
(左侧项目) ,1
,2
(右侧项)保留;再次向右滚动一页,显示项目
2
,添加项目3
,项目0
被方法[=16]销毁=], 现在项目1
(左侧项目),2
,3
(右侧项目, 与0
相同的项目)被保留;
如果 instantiateItem
和 destroyItem
按预期工作,一切正常,当您向右滚动时它确实有效("forward"),但当您滚动时它不起作用左边("backward")因为instantiateItem
和destroyItem
的执行顺序不一样!查看日志:
07-30 22:00:04.385 26064-26064/com.example.test D/xxxxx: instantiateItem: 0
07-30 22:00:04.388 26064-26064/com.example.test D/xxxxx: instantiateItem: 1
07-30 22:00:17.693 26064-26064/com.example.test D/xxxxx: instantiateItem: 2
07-30 22:00:18.743 26064-26064/com.example.test D/xxxxx: destroyItem: 0
07-30 22:00:18.744 26064-26064/com.example.test D/xxxxx: instantiateItem: 3
07-30 22:00:26.477 26064-26064/com.example.test D/xxxxx: instantiateItem: 0 < -- crash!!!
07-30 22:00:18.743 26064-26064/com.example.test D/xxxxx: destroyItem: 3
当你向右滚动时,destroyItem
先执行,然后instantiateItem
,所以它工作正常,但是当你向左滚动时,instantiateItem
先执行,所以当打印的最后一行日志,第二次添加了项目0
,因为项目3
(与项目0
共享相同的View
)还没有被销毁然而,然后它崩溃了:)
有趣的是,如果mImgRes.length > 3
,它会正常工作,因为当有4个项目时,destroyItem
执行时还不算太晚。
因此,如果您想使用 "loop" 功能实现 ViewPager
,则必须考虑如何解决此问题。