如何更改NumberPicker的值与animation?

我为Android创build了一个应用程序,其中有一个NumberPicker。 而且我需要改变这个NumberPicker的值,但是像一个平滑的animation一样,当你触摸它并改变它的值。

例如,假设当前值为1,它将会是5,我希望NumberPicker从1旋转到2,然后旋转到3,依此类推。 但是我希望它不仅能立即改变价值!

如果我使用下面的代码:

numberPicker.setValue(5); 

它的值会立即变为5,但是我希望它从1到5滚动,就像手动触摸它并旋转一样。

  • 带有数字选择器的Android PreferenceActivity对话框
  • Android NumberPicker - 负数
  • 更改NumberPicker分隔线颜色
  • 具有格式化的Android NumberPicker不会在第一次呈现时进行格式化
  • 你怎么在android中显示一个2位的NumberPicker?
  • 在NumberPicker中的最小值和最大值之间的块转换
  • 带有Formatter的Android NumberPicker在第一次渲染时不格式化
  • 我通过refelction解决了它

      /** * using reflection to change the value because * changeValueByOne is a private function and setValue * doesn't call the onValueChange listener. * * @param higherPicker * the higher picker * @param increment * the increment */ private void changeValueByOne(final NumberPicker higherPicker, final boolean increment) { Method method; try { // refelction call for // higherPicker.changeValueByOne(true); method = higherPicker.getClass().getDeclaredMethod("changeValueByOne", boolean.class); method.setAccessible(true); method.invoke(higherPicker, increment); } catch (final NoSuchMethodException e) { e.printStackTrace(); } catch (final IllegalArgumentException e) { e.printStackTrace(); } catch (final IllegalAccessException e) { e.printStackTrace(); } catch (final InvocationTargetException e) { e.printStackTrace(); } } 

    作品完美。 我不知道为什么这个方法是私人的

    我不相信这是本地支持。 我想到了一个手动的“混乱”的方式:

    您可以使用迭代调用的NumberPicker的scrollBy(int x,int y)函数来产生animation效果。

    有些事情要考虑到:

    • scrollBy(x,y)适用于像素。 由于Android已经有了所有不同的屏幕密度,你应该做的是首先猜测(我会做试验和错误)与滚动到连续值对应的“dp”距离,并将其转换为像素以便用它。
    • scrollBy(x,y)的第一个参数应该取值为0,以防不明显

    我自己并没有在Android中制作animation,但自从Honeycomb以来,有一个非常好的API,可能很容易做到这一点。

    我很抱歉,但这是我能想到的最简单的!

    编辑:从'dp'转换为像素:

     private float pxFromDp(float dp) { return dp * this.getContext().getResources().getDisplayMetrics().density; } 

    你必须做的是用不同的'dp'值调用scrollBy(0,pxFromDp(dp)),直到你得到一个将NumberPicker移动一个数字的确切的值。 一旦你得到这个值,你可以创build你的animation方法,当向上移动X号码将滚动X倍这个Dp距离。

    如果你不完全理解,请再问一次:)

    感谢@passsy。 启发他的答案:这个解决scheme支持多个递增/递减步骤 。 此外,可以执行启动延迟多个编号(无需额外的编码)

     class IncreaseValue { private int counter = 0; private final NumberPicker picker; private final int incrementValue; private final boolean increment; private final Handler handler = new Handler(); private final Runnable fire = new Runnable() { @Override public void run() { fire(); } }; /*public*/ IncreaseValue(final NumberPicker picker, final int incrementValue) { this.picker = picker; if (incrementValue > 0) { increment = true; this.incrementValue = incrementValue; } else { increment = false; this.incrementValue = -incrementValue; } } /*public*/ void run(final int startDelay) { handler.postDelayed(fire, startDelay); // This will execute the runnable passed to it (fire) // after [startDelay in milliseconds], ASYNCHRONOUSLY. } private void fire() { ++counter; if (counter > incrementValue) return; try { // refelction call for // picker.changeValueByOne(true); final Method method = picker.getClass().getDeclaredMethod("changeValueByOne", boolean.class); method.setAccessible(true); method.invoke(picker, increment); } catch (final NoSuchMethodException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) { Log.d(TAG, "...", e); } handler.postDelayed(fire, 120); // This will execute the runnable passed to it (fire) // after 120 milliseconds, ASYNCHRONOUSLY. Customize this value if necessary. } } 

    用法:

     // Suppose picker1 as a NumberPicker IncreaseValue increasePicker1 = new IncreaseValue(picker1, 10); // So picker1 will be increased 10 steps. increasePicker1.run(0); // Increase immediately. If you want to run it from onCreate(), onStart() or ... of your activity, you will probably need to pass a positive value to it (eg 100 milliseconds). 

    NumberPicker里面有私有方法,

     changeCurrentByOne(boolean increment) 

    你可以公开并使用它。 当按下NumberPicker的向上向下箭头时,您可以看到此方法正在执行。 也许这不是你正在寻找的,因为这种方法不能给予animation的太多控制,但它比setValue更好。 没有任何animationsetValue对用户来说看起来很糟糕。