Android ViewPager在设置当前项目/页面时抛出IndexOutOfBounds异常

时间:2012-02-22 21:04:52

标签: android android-viewpager

我有一个包含三个项目的ViewPager。我正在尝试将ViewPager设置为查看最右边的页面(这将是第二个元素)。这是返回一个IndexOutOfBounds异常,虽然我知道索引应该在边界内。这是确切的堆栈:

02-22 12:22:50.256: E/AndroidRuntime(384): FATAL EXCEPTION: main
02-22 12:22:50.256: E/AndroidRuntime(384): java.lang.IndexOutOfBoundsException: index=1 count=0
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.addInArray(ViewGroup.java:2050)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.addViewInner(ViewGroup.java:1994)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.addViewInLayout(ViewGroup.java:1958)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.addViewInLayout(ViewGroup.java:1939)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.support.v4.view.ViewPager.addView(ViewPager.java:917)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.addView(ViewGroup.java:1828)
02-22 12:22:50.256: E/AndroidRuntime(384):  at us.tagverse.pagertest.MasterActivity$PAdapter.instantiateItem(MasterActivity.java:518)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.support.v4.view.PagerAdapter.instantiateItem(PagerAdapter.java:110)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:649)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.support.v4.view.ViewPager.populate(ViewPager.java:783)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1016)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.View.measure(View.java:8313)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1017)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.widget.LinearLayout.measureVertical(LinearLayout.java:386)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.View.measure(View.java:8313)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.View.measure(View.java:8313)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.View.measure(View.java:8313)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewRoot.performTraversals(ViewRoot.java:839)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.os.Handler.dispatchMessage(Handler.java:99)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.os.Looper.loop(Looper.java:123)
02-22 12:22:50.256: E/AndroidRuntime(384):  at android.app.ActivityThread.main(ActivityThread.java:3683)
02-22 12:22:50.256: E/AndroidRuntime(384):  at java.lang.reflect.Method.invokeNative(Native Method)
02-22 12:22:50.256: E/AndroidRuntime(384):  at java.lang.reflect.Method.invoke(Method.java:507)
02-22 12:22:50.256: E/AndroidRuntime(384):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-22 12:22:50.256: E/AndroidRuntime(384):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-22 12:22:50.256: E/AndroidRuntime(384):  at dalvik.system.NativeStart.main(Native Method)

请注意原因是java.lang.IndexOutOfBoundsException: index=1 count=0。这意味着页面/项目的计数为0,我请求的索引为1.这些都不是真的。以下是我调用ViewPager并请求给定页面的方式:

ViewPager pager = (ViewPager) findViewById(R.id.ma_viewcontainer);
PAdapter adapter = new PAdapter();
pager.setAdapter(adapter);
pager.setCurrentItem(2);

请注意,此调用不会产生任何错误,并且正确地将当前项设置为中间项(索引1):

ViewPager pager = (ViewPager) findViewById(R.id.ma_viewcontainer);
PAdapter adapter = new PAdapter();
pager.setAdapter(adapter);
pager.setCurrentItem(1);

我在视图寻呼机中有3个项目。这是我的完整PAdapter类,它扩展了PagerAdapter类:

private class PAdapter extends PagerAdapter implements TitleProvider {

    private int COUNT = 3;

    private static final int SETTINGS_ACTIVITY = 0;
    private static final int MAIN_ACTIVITY = 1;
    private static final int FRIEND_LIST_ACTIVITY = 2;

    @Override
    public int getCount() {
        return COUNT;
    }

    @Override
    public Object instantiateItem(View collection, int position) {
        LinearLayout layout = new LinearLayout(getApplicationContext());
        LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        switch(position) {
        case MAIN_ACTIVITY :
            layout = (LinearLayout) inflater.inflate(R.layout.main, null, false);
            initMainLayout(layout);
            break;
        case SETTINGS_ACTIVITY :
            layout = (LinearLayout) inflater.inflate(R.layout.settings, null, false);
            initSettingsLayout(layout);
            break;
        case FRIEND_LIST_ACTIVITY :
            layout = (LinearLayout) inflater.inflate(R.layout.friend_list, null, false);
            initFriendListLayout(layout);
            break;
        }
        ((ViewPager)collection).addView(layout, position);
        return layout;
    }

    @Override
    public void destroyItem(View collection, int position, Object view) {
        ((ViewPager)collection).removeView((LinearLayout)view);
    }

    @Override
    public boolean isViewFromObject(View v, Object o) {
        return v == (LinearLayout)o;
    }

    @Override
    public void finishUpdate(View arg0) {
        //no need
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
        //no need
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void startUpdate(View arg0) {
        //no need
    }

    @Override
    public String getTitle(int position) {
        Resources res = getApplicationContext().getResources();
        switch(position) {
        case MAIN_ACTIVITY :
            return res.getString(R.string.app_name);
        case SETTINGS_ACTIVITY :
            return res.getString(R.string.settings);
        case FRIEND_LIST_ACTIVITY :
            return res.getString(R.string.friend_list);
        default :
            return null;
        }
    }
}

((ViewPager)collection).addView(layout, position);导致崩溃。

如你所见,有三个项目。使用参数为0或1的setCurrentItem()可以正常工作,但是2会导致这个奇怪的错误。我已经没有想法来解决它......不幸的是,ViewPager似乎存在于Android的一些未知领域。如果有人对如何解决这个问题有一些了解,那将非常感激。谢谢!

编辑:根据Shereef的建议,我尝试通过collection.getChildCount()记录子计数,并得到以下结果:

02-22 15:20:42.274: E/children count(645): count: 0
02-22 15:20:42.454: E/children count(645): count: 1
02-22 15:20:42.594: E/children count(645): count: 2

这很有趣。这告诉我的是它创建一个空的PagerAdapter并一次添加一个。对于三个可见视图(中心,左侧和右侧),instantiateItem()被调用3次。所以我在instantiateItem()方法中添加了这段代码:

if(((ViewPager)collection).getChildCount() ==  2) {
    ((ViewPager)collection).setCurrentItem(2);
}

因此,只有将计数设置为2才会将页面设置为2(这是一个hacky解决方案,不能完全解决问题,但值得一试)。我得到了一个类似的错误堆栈,首先指向该行:((ViewPager)collection).setCurrentItem(2);,然后是((ViewPager)collection).addView(layout, position);

希望这有助于提供一些见解。

2 个答案:

答案 0 :(得分:24)

我认为你不能做((ViewPager)collection).addView(layout, position)。这取决于您的屏幕外页面限制,我相信默认值为1。我假设你只使用3个视图,所以你可以在你的`onCreate(或你拨打电话的任何地方)做viewPager.setOffscreenPageLimit(3);之类的事情,以避免每次离开时每个视图都被刷新。

您将在一些教程中看到((ViewPager) collection).addView(view, 0);中使用了instantiateItem()。在过去几周里我和ViewPagers工作了很多,并且使用0作为位置 - 所有时间似乎都很好。

答案 1 :(得分:7)

我看到崩溃日志,我发现它在实例化项目中崩溃了。 我完全不知道哪一行,因为我没有你的行号

但如果我是一个博彩人,我敢打赌:

  ((ViewPager)collection).addView(layout, position);

当集合中没有页面时,尝试在位置1添加视图时崩溃 也许检查collection.getchildcount()(可能方法名称错误)并插入最大值(位置,计数)

即用以下位置替换位置:

count > position ? position : count

编辑:

((ViewPager)collection).addView(layout, ((ViewPager)collection).getChildCount() > position ? position : ((ViewPager)collection).getChildCount())

P.S。从我的手机发帖抱歉可怕的格式化

请注意

 02-22 12:22:50.256: E/AndroidRuntime(384): at us.tagverse.pagertest.MasterActivity$PAdapter.instantiat 

MasterActivity.java:518

我复制的那一行末尾的数字,然后找出它是哪一行,然后才知道哪一行发生了崩溃

编辑:P.S。关于你的解决方案

我认为您的解决方案仅在实例化实例化实例化3个页面之后设置当前项目,但即使它们未实例化,我的行也会使其工作。