改变NumberPicker滚动速度

3

无法相信我在Stack Overflow上没有找到有关此问题的答案...

我正在制作一个定时器,在NumberPicker小部件中选择时间。问题是需要滚动10-13次才能到底部。

我查看了文档,但没有找到任何信息。

String[] minsecvalues = new String[61];

for(int i=0; i < minsecvalues.length; i++){
        minsecvalues[i] = Integer.toString(i);
}

NumberPicker mSecondsPicker = (NumberPicker) v.findViewById(R.id.np_seconds_picker);
mSecondsPicker.setMaxValue(60);
mSecondsPicker.setMinValue(0);
mSecondsPicker.setWrapSelectorWheel(true);
mSecondsPicker.setDisplayedValues(minsecvalues);

//supposed to change scroll speed but doesn't work
mSecondsPicker.setOnLongPressUpdateInterval(8000);
//This method looks promising but my app crashes when I run it
//mSecondsPicker.scrollBy(0, 20);
4个回答

1

默认的NumberPicker小部件中没有公共访问摩擦级别的方法。

您可以使用此自定义NumberPickerView。英文安装说明在这里

它提供了以下方法来控制摩擦力,正好符合您的需求:

//double the default scroll friction level
mNumberPickerView.setFriction(2 * ViewConfiguration.get(mContext).getScrollFriction());

默认的滚动摩擦值为0.015f,并且可以在这里找到。

这是一个很棒的库,但缺点是它缺乏EditText功能,即无法通过键入来选择所需的值。 - undefined

1

我看到了一些与此相关的问题(例如这里这里)。

与最大滚动速度相关的NumberPicker变量默认设置为私有。幸运的是,我们可以使用反射来访问和更改这些值。为什么这个类没有公共方法来改变像滚动速度这样基本的东西,这超出了我的理解范围。

在NumberPicker的源代码中找到这个private int mMaximumFlingVelocity变量,链接在这里

假设numberPicker是我们的NumberPicker:

// Can set this value to anything to modify our scroll speed, where a value
// between 0 and 1 makes the scroll speed slower, and anything greater than
// 1 makes it faster (e.g. a factor of 2 makes it twice as fast)
final double scrollSpeedFactor = 2;

// Surrounding by try/catch is required here because Class.getDeclaredField
// can throw a NoSuchFieldException and Field.get can throw an IllegalAccessException
try {
    // Our private field is accessed with getDeclaredField
    Field field = numberPicker.getClass().getDeclaredField("mMaximumFlingVelocity");

    // We make the field accessible
    field.setAccessible(true);

    // Get the value
    int maxVelocityValue = (int) field.get(numberPicker);

    // Set a new velocity value based on our scrollSpeedFactor
    int newVelocityValue = (int) (maxVelocityValue * scrollSpeedFactor);

    // Set the new velocity
    field.setInt(numberPicker, newVelocityValue);
} 
catch (NoSuchFieldException | IllegalAccessException e) {
    e.printStackTrace();
}

从 API 级别 31 开始,字段“mMaximumFlingVelocity”是被列入黑名单的非 SDK API(https://developer.android.com/about/versions/12/non-sdk-12#new-blocked 列出了“Landroid / widget / NumberPicker;-> mMaximumFlingVelocity:I”),这意味着它不能通过反射正常访问(如 https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces#results-of-keeping-non-sdk 中所述将抛出 NoSuchFieldException)。然而,有办法绕过这种限制,例如在 https://dev59.com/RlMI5IYBdhLWcg3wi8Ab#55970138 中描述的方法。 - undefined

0

我也找不到解决方案,但我只是想澄清一下为什么。

mSecondsPicker.setOnLongPressUpdateInterval(8000);

它并不按照你的期望工作。这个方法的description是“设置在长按上下按钮时数字递增和递减的速度。”这意味着它只影响当你按住上下按钮时的滚动速度,而不是控制滑动速度。我相信默认的NumberPicker中的“上下”按钮是指高亮或选定数字上方和下方的数字。


0
我的ScrollPicker库可能对这里有所帮助,但不幸的是它不能让“选择器轮”“包裹”,因此无法循环显示列表。
虽然你不能通过代码设置滚动速度,但也没必要,因为你可以在一次刷动中到达这60个项目的末尾。这就是我认为它仍然适合你的原因。你可以通过你在刷动上的速度来控制刷动速度。
以下是你需要做的:
1. 使用ScrollPicker而不是NumberPicker
2. 用setItems(..)在代码中设置你的集合。不需要使用setMinValue、setMaxValue或转换为字符串,只需设置你的整数集合即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接