【问题标题】:I can only use the ViewPager to page backward and can not page forward我只能使用 ViewPager 向后翻页,不能向前翻页
【发布时间】:2017-07-29 13:22:25
【问题描述】:

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: 致命例外:主要 进程:com.example.myfirstpro,PID:20791 java.lang.IllegalStateException:指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。 在 android.view.ViewGroup.addViewInner(ViewGroup.java:4465) 在 android.view.ViewGroup.addView(ViewGroup.java:4301) 在 android.support.v4.view.ViewPager.addView(ViewPager.java:1505) 在 android.view.ViewGroup.addView(ViewGroup.java:4242) 在 android.view.ViewGroup.addView(ViewGroup.java:4215) 在 com.example.myfirstpro.MainFragment$MyPagerAdapter.instantiateItem(MainFragment.java:62) 在 android.support.v4.view.ViewPager.addNewItem(ViewPager.java:1034) 在 android.support.v4.view.ViewPager.populate(ViewPager.java:1216) 在 android.support.v4.view.ViewPager.populate(ViewPager.java:1116) 在 android.support.v4.view.ViewPager$3.run(ViewPager.java:273) 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:892) 在 android.view.Choreographer.doCallbacks(Choreographer.java:704) 在 android.view.Choreographer.doFrame(Choreographer.java:637) 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:878) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5628) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:853) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:737)

前滚时程序会崩溃。

这是除了适配器以外的代码。@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());
}

【问题讨论】:

  • 你只想做一个方向对吗?
  • 使用FragmentStatePagerAdapter 而不是PagerAdapter
  • 看我的这个答案会帮助你:stackoverflow.com/a/45389635/5743202
  • 您必须在 instantiateItem 上扩展视图,然后添加到容器中,但您在已经有父级的容器中添加视图。
  • 请出示mListViewmImgRes的代码?

标签: android android-viewpager android-banner


【解决方案1】:

如错误消息所示,根本原因是子 View 添加了两次。但是为什么这只发生在你向后滑动时?我做了一个测试项目,我想我找到了原因:)

ViewPager滚动时,它将使用PagerAdapter的方法回收项目:instantiateItemdestroyItem,当ViewPager想要显示一个新项目时,instantiateItem被调用,当@987654328 @滚动,离开屏幕的视图将被方法destroyItem销毁。

默认情况下,ViewPager 将在每一侧保留 1 更多项目以平滑滚动,这意味着最多有 3 项目保留ViewPager

问题是,你正在使用:

int p = position % mImgRes.length;

要实现一个“循环”ViewPager,这意味着如果mImgRes.length == 3,位置 3 将在位置 0 处显示相同的 View

现在想想你的情况:

  • ViewPager初始化时,01(右边的项目)被instantiateItem添加;

  • 然后向右滚动一页,显示项目1,并添加项目2,现在项目0(左侧项目),12(右侧边项)被保留;

  • 再次向右滚动一页,显示项目2,添加项目3,项目0被方法destroyItem销毁,现在项目1(左侧item), 2, 3(右边的item,与0相同的item) 被保留;

如果instantiateItemdestroyItem 按预期工作,一切正常,并且当您向右滚动(“向前”)时它确实有效,但当您向左滚动(“向后”)时它不起作用因为instantiateItemdestroyItem的执行顺序不同!查看日志:

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(与项目View 共享相同的View)还没有被销毁,然后它崩溃了:)

有趣的是,如果mImgRes.length &gt; 3,它会正常工作,因为当有4个项目时,destroyItem执行还为时不晚。

所以,如果你想用“循环”功能实现ViewPager,你必须考虑如何解决这个问题。

【讨论】:

  • 非常感谢,现在我知道哪里错了。我可以写这样的代码可以是一个循环。private int mImgRes[] = new int[] { R.drawable.banner01, R.drawable.banner02, R.drawable.banner03, R.drawable.banner01, R.drawable.banner02, R.drawable.banner03 };
猜你喜欢
  • 1970-01-01
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2020-07-29
相关资源
最近更新 更多