【问题标题】:Linking two NumberPicker views with onValueChanged causes unpredictable crashes使用 onValueChanged 链接两个 NumberPicker 视图会导致不可预知的崩溃
【发布时间】:2014-07-31 04:01:45
【问题描述】:

我创建了一个包含两个 NumberPicker 视图的对话框。第一个包含组列表,第二个包含所选组中的项目:

Group         Group Items
  1            2: Group 2 Item 2
 [2]          [3: Group 2 Item 3]
  3            4: Group 2 Item 4

我连接到第一个 NumberPicker 中的 setOnValueChangedListener 以填充第二个 NumberPicker。

  mNumberPickerGroup.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
        @Override
        public void onValueChange(NumberPicker numberPicker, int from, int to) {
            int size = mData.getItemsForGroup(to).size();
            String[] strings = mData.getItemTitlesForGroup(to);

            mNumberPickerItems.setMinValue(1);
            mNumberPickerItems.setValue(1);

            mNumberPickerItems.setMaxValue(size);
            mNumberPickerItems.setDisplayedValues(strings);

        }
    });

这基本上是可行的 - 直到在某些情况下,在设置 setDisplayedValues 字符串时,多次更改组会导致 NumberPicker 类崩溃。

错误是数字选择器中的数组索引越界异常,与我传入的字符串数组有关。我在上面的更新代码中设置了一个断点,并验证了字符串数组在数字选择器上设置的最小值和最大值之间的项目数量始终是正确的大小,所以这让我很难过。

  java.lang.ArrayIndexOutOfBoundsException: length=22; index=22
        at android.widget.NumberPicker.ensureCachedScrollSelectorValue(NumberPicker.java:1768)
        at android.widget.NumberPicker.initializeSelectorWheelIndices(NumberPicker.java:1583)
        at android.widget.NumberPicker.setMaxValue(NumberPicker.java:1390)
        at uk.co.my.app.fragments.GroupMarkUptoDialog.updateItemPicker(MarkUptoDialog.java:99)

我将开始阅读 NumberPicker 中发生的事情,以确定我是否使用错误,但欢迎提出任何建议。 “ensureCachedScrollSelectorValue”让我觉得我需要在用新数据更新之前以某种方式重置数字选择器,但我不确定。

谁能看到我在这里做错了什么?

我意识到 NumberPicker 并不是真正的字符串选择器,所以如果有人对如何实现这种 UI 有更好的建议,我会全力以赴。否则,我将尝试实现某种去抖动器,以便在组选择器上的所有活动完成后更新项目选择器。

【问题讨论】:

  • 您找到解决问题的方法了吗?我目前面临同样的问题
  • 我找到了解决办法,在处理onValueChange之前,调用setDisplayedValues为null
  • 也为我工作。不知道为什么,或者它是否是一个“好”的解决方案,但它确实有效。 +1

标签: android


【解决方案1】:

当你 setDisplayedValue(String[]) 多次时会发生这种情况。

如果string[]的长度大于当前的getMaxValue(),就会发生异常!

我的解决方案

使用

picker.setMaxValue(0);

之前

picker.setDisplayedValues(stringArr);

我的代码

cityPicker.setMaxValue(0);
    try {
        cityPicker.setDisplayedValues(citySet.toArray(new String[citySet.size()]));
    } catch (Exception e) {
        Log.e("Ninja", "cityPicker.setDisplayedValues(citys) occurs Error. province is " + province);
    }
    cityPicker.setMaxValue(citySet.size() - 1);

【讨论】:

  • 哦...非常感谢您的原因...但是这个解决方案不起作用
  • 感谢cmets,好多年没写Android代码了^^。如果您有解决方案,您可以上传解决方案。
【解决方案2】:

如果您使用从 1 开始的索引,则使用:

        int size = mData.getItemsForGroup(to-1).size();

使用它来更改第二个选择器(如果当前值高于最大值,它将设置为新的最大值):

        int i = mNumberPickerItems.getValue();
        int max = strings.length;
        if (i > max)
            i = max;
        mNumberPickerItems.setMinValue(1);
        mNumberPickerItems.setMaxValue(1);
        mNumberPickerItems.setDisplayedValues(strings);
        mNumberPickerItems.setMaxValue(max);
        mNumberPickerItems.setValue(i);

并尝试使用值作为索引,即

        minValue=0 
        maxValue=strings.length-1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-23
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多