目标
我想实现一个倒数计时器,该计时器仅从左到右滚动数字(而不是图形)。

效果
效果看起来像是数字从左侧放大,向中间变慢,然后向右侧缩小。

注释
因为我已经在使用TimerTask每秒执行代码,所以我可以使用它来触发下一个数字,以在水平滚动的textview中滚动。

可以将它实现为scrollview内的textview吗?寻找一个开始的代码示例。

最佳答案

使用动画将是最简单的解决方案。您可以创建自己的文件,也可以尝试组合多个 TranslateAnimations ScaleAnimations

这意味着将每个数字放入其自己的TextView中,而不是使用滚动 View 。

然后,您可以使用 Interpolator 控制到中间的加速度。插值器是Android处理宽松的方式。您可能需要 AccelerateDecelerateInterpolator 来加快/减慢效果。

您可以使用 AnimationSet 将多个动画应用到同一 View 。弄清楚如何组合一个好的AnimationSet将是项目中最具挑战性的部分。确保注意“填充”属性。实际上,经过一段时间的尝试,我认为自定义动画比使用现成的动画更简单。

您可以派生实现此版本非常简单的 my GitHub project 。 4月17日及之前,我使用了多个预制动画。如果您查看的是最新版本,则会看到自定义动画。

在设置一个动画的持续时间后,每个动画的时间安排都将由其自己决定。上一个号码结束后, Handler 调用下一个号码。我认为这比必须每隔X秒调用一个函数来更新所有内容要整洁一些。

功能概述:

  • Activity ( CountDownActivity.java )可以看到所有内容。
  • Activitiy的布局XML有一个用于开始倒数的按钮。
  • 一旦开始倒计时,该按钮就会消失。倒数完成后,它会重新出现。
  • 该 Activity 包含一个 Handler ( MotionHandler.java )。 Handler 控制数字的移动和计时。
  • 处理程序使用 AnimationSet 移动数字
  • AnimationSet是传入的依赖项
  • 这是为了提高灵活性。只需传入另一个AnimationSet即可更改数字移动方式
  • AnimationSet由四个动画组成,一个是自定义动画(请参见下文)。
  • AnimationSet使用共享的 AccelerateDecelerateInterpolator ,它似乎工作得很好。还有其他选项,包括编写自己的选项。
  • 处理程序使用 delayed message 来开始下一个数字
  • 使用自定义监听器( MotionHandler >> CountdownListener)完成倒计时时,处理程序通知 Activity 。
  • 旋转设备将重新开始倒数。

  • 注意-以前我在一个AnimationSet中使用了四个现成的Animation,我已编辑为仅包含一个自定义Animation ...您可以根据自己的喜好调整其算法。

    此自定义动画使用 Cycloid 使数字显得越来越大。
    /**
     * A custom animation to move and scale the numbers.
     *
     */
    public class NumberAnimation extends Animation
    {
        final public static float MINIMUM = 3;
        private int mHorizontal;
        private int mScaling;
    
        public NumberAnimation(int horizontalMovement, int scaling)
        {
            mHorizontal = horizontalMovement;
            mScaling = scaling;
        }
    
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t)
        {
            // Cycloid repeats every 2pi - scale interpolatedTime to that
            double time = 2 * Math.PI * interpolatedTime;
            // Cycloid function
            float currentScale = (float) (mScaling * (1 - Math.cos(time))) + MINIMUM;
            Matrix matrix = t.getMatrix();
            matrix.preScale(currentScale, currentScale);
            matrix.postTranslate(mHorizontal * interpolatedTime, 0);
        }
    }
    

    关于android - 如何实现水平滚动倒数计时器?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10131767/

    10-11 22:19