【问题标题】:GridLayoutManager spanSizeLookup bugGridLayoutManager spanSizeLookup 错误
【发布时间】:2015-08-07 18:56:43
【问题描述】:

我遇到GridLayoutMangersetSpanSizeLookup 的问题,当活动的方向发生变化时,我正在更改跨度计数,同时检查特定位置是否是某种类型,这在方向变化上非常有效,我唯一的问题是,我正在使用zxing 库进行条形码扫描,每当单击button 时,我都会打开zxing 默认意图并从中检索日期,但是当zxing 打开时,它会转到@ 987654327@,我当前的活动方向是portrait,这给了我布局管理在仅打开Xzing 意图时抛出的IllegalArgumentException,崩溃日志是这样的
java.lang.IllegalArgumentException: Item at position 0 requires 2 spans but GridLayoutManager has only 1 spans.
如果我旋转手机,则不会出现此问题,仅当我启动 Xzing 意图时才会发生,我无法真正弄清楚如何解决此问题,因为它困扰着我。这是我的spanSizeLookup -

manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
     @Override
     public int getSpanSize(int position) {
        return adapter.getHolders().get(position).getLabelHolder() != null ? getResources().getInteger(R.integer.span) : 1;
     }
});

span 基于屏幕尺寸,因此可以是 1-2、2-3 和 3-4。我重复一遍这不会给我任何方向更改错误,只有当我打开zxing时才会出现错误@
P.S 如果我打开zxing intent 而我的活动是在landspace 上,则不会发生崩溃。

编辑

似乎只是启动 zxing 导致此问题的默认意图,我有一个 activity 在它启动后它转到 landscape 并且 exception 没有发生,作为我所做的解决方法,是我创建了一个activity 来处理barcode 扫描,延迟1 秒来启动intent,就好像我没有这样做一样,它会抛出相同的exception

编辑 2

我刚刚发现,即使没有 setSpanSpizeLookup,崩溃仍然会发生。只需致电manager.setSpanCount(getResources().getInteger(R.integer.span))

【问题讨论】:

    标签: android zxing android-recyclerview gridlayoutmanager


    【解决方案1】:

    这是在GridLayoutManager.layoutChunk()中引发异常的源代码

    final int spanSize = getSpanSize(recycler, state, pos);
    if (spanSize > mSpanCount) {
        throw new IllegalArgumentException("Item at position " + pos + " requires " +
               spanSize + " spans but GridLayoutManager has only " + mSpanCount
               + " spans.");
    }
    

    您的 spanSize 是否大于您的 spanCount?尝试调试并可能更改您的 spanCount 并查看它是如何工作的。

    ----更新----

    有几种方法可以在列表和网格之间切换。

    1. 只改变 spanCount。

      更改 spanCount 后,您必须致电 LayoutManager.requestLayout()。否则您的应用可能会崩溃。

    2. 仅更改 SpanSizeLookUp。

      private class CustomSpanSize extends GridLayoutManager.SpanSizeLookup {
      
        private static final int LIST_SPAN_SIZE = 1;
        private static final int GRID_SPAN_SIZE = 2;
      
        private int mSpanSize = LIST_SPAN_SIZE;
      
        public void asList() {
          mSpanSize = LIST_SPAN_SIZE;
        }
      
        public void asGrid() {
          mSpanSize = GRID_SPAN_SIZE;
        }
      
        @Override
        public int getSpanSize(int position) {
          return mSpanSize;
        }
      }
      

      然后像这样使用它

      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      
        mLayoutManager = new GridLayoutManager(this, 2);
      
        mCustomSpanSize = new CustomSpanSize();
        mLayoutManager.setSpanSizeLookup(mCustomSpanSize);
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(mLayoutManager);
      
        ...
      }
      
      public void someFunction() {
        if (changed) {
          mCustomSpanSize.asList();
        } else {
          mCustomSpanSize.asGrid();
        }
        // use this to update the layout
        mAdapter.notifyDataSetChanged();
        // or you can use this to update the layout
        mLayoutManager.requestLayout();
      }
      

      这种方式即使你忘记拨打notifyDataSetChangedrequestLayout也不会崩溃

    【讨论】:

    • 嗨,Trey,感谢您的回答,如果您通读了我的问题,如果我手动旋转手机,则不会发生该异常,但是当我午餐 zxing 意图时会发生这种情况,这反过来又使我当前的活动进行景观和崩溃,这让我很困惑,如果我旋转它,它不会崩溃
    • 嗨,k0sh,请问您的 GridLayoutManager 何时只有 1 个跨度。
    • 当有一个项目,例如,我们称它为 SEPARATOR
    • 抱歉回复晚了。您可以发布一些示例代码供我调试吗?我需要一些可以重现崩溃的代码。
    • 您的示例代码没有错。更改 spanCount 后,您必须致电 requestLayout。特别是当您尝试将 spanCount 更改为更小时。更改 spanSize 以在列表和网格之间切换是另一种方式。一种安全的方式。如果您忘记requestLayout,它不会崩溃。您也可以致电Adapter.notifyDataSetChanged() 更新 spanSize。
    【解决方案2】:

    编辑:调用 setSpanCount() 并将其设为比该跨度更大的数字吗? 也许需要更多代码。

    听起来可能是并发修改错误。尽量不要使用每 sé 的延迟,而是在 UI 线程上运行修改。这将阻止 UI 尝试访问列表。

    if(adapter.getHolders().get(position).getLabelHolder() != null)
        return getResources().getInteger(R.integer.column);
    else 
        return 1;
    

    那么getResources().getInteger(R.integer.column) 是什么?

    那不是每次都是同一个数字吗?

    【讨论】:

    • getResources().getInteger(R.integer.column) 取决于我提到的方向,它可以是 2,3,4,具体取决于设备的大小和设备的方向
    • 啊,明白了。属性名称有点混乱。
    • 有点像,因为我将那个 attr 与不同的东西一起使用,所以我没有创建新的 attr 来重复使用它:p,我不确定我是否尝试过你的解决方案,但是我将立即检查并更新您
    • 你读过那个文档吗?这不是很明显。 developer.android.com/reference/android/support/v7/widget/… ...因为一旦您转动设备列,方向就会改变。它们仍然是列。清如泥。
    • 安迪,让我们把事情放在一起好吗? spanSizeLookup 旨在自定义 gridmanager 的每一行以及如何确定第一行是否应该显示两个或一个,如果您阅读我的第二个更新,即使没有setspansizelookup 崩溃仍然发生。我想我知道我在做什么
    【解决方案3】:

    令人惊讶的是,我遇到了同样的问题,刚刚找到了解决方案。在使用构造函数中传递的 spanCount 初始化 GridLayoutManager 后,我们的应用程序将崩溃。但是,如果我在构造对象后setSpanCount(),它可以工作! :O

    我们使用的是 RecyclerView 23.0.1。希望这对某人有所帮助。

    【讨论】:

      【解决方案4】:

      回答这个问题为时已晚,但是在我从事的最新项目中,我遇到了同样的问题,经过一些真正的调试后,我发现了问题的原因,但不知道为什么会导致它。

      zxing Library intent 它实际上在调用startActivityForResult 之前调用了CLEAR_TOP,这就是问题所在,在修改zxing Intent 的源代码以删除该特定行之后,崩溃就消失了.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-25
        相关资源
        最近更新 更多