Android 实现倒计时动画效果

想要实现的效果图如下:

点击“倒计时开始”按钮,会出现从10到0的倒计时动画。说是动画,其实并不是用animation等来制作,而仅仅是用TextView更新文字的方式来实现动画效果,很esay,直接上图。



第一步:制作圆形背景图

在android中,我们会用shape定义各种各样的形状,它能实现渐变色、虚线/分割线、边框、半透明、半透明阴影效果。圆形背景图为矢量图,先上代码:

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/white" />
    <stroke
        android:width="4dp"
        android:color="@color/white" />
    <padding
        android:top="1dp"
        android:left="2dp"
        android:right="2dp"
        android:bottom="1dp"/>
    <size
        android:width="20dp"
        android:height="20dp" />
</shape>

解释
  • solid 实心填充颜色,十六进制颜色值,这里设置了60%半透明度白色的效果
  • stroke 描边,外边框,可以设置颜色和宽度.同时,该属性也可以用来画虚线,通过设置dashGap和dashWidth两个属性控制虚线间隔和长度
  • padding 内容距离边框的值
  • size 指定大小,shape为oval模式时,width和height相等时,代表正圆,否则de为椭圆

第二步:规划布局文件,设置TextView的背景

按照文初看到的效果图,布局文件中需要有一个可点击的Button,和一个可以变更数字的TextView。

  • 首先,隐藏TextView的显示,只显示一个“倒计时开始”的Button。
  • 点击“倒计时开始”后,将Button隐藏,将TextView显示出来。
    代码罗列如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@color/gray"
  android:gravity="center"
  tools:context="com.example.server.testapplication.MainActivity">

  <TextView
      android:id="@+id/count_text"
      android:layout_width="350dp"
      android:layout_height="350dp"
      android:background="@drawable/circle"
      android:gravity="center"
      android:textColor="@color/black"
      android:textSize="240sp"
      android:visibility="gone" />

  <Button
      android:id="@+id/count_button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:gravity="center"
      android:text="倒计时开始..." />
</RelativeLayout>
  • 第三步:实现代码逻辑,用Handler实现动态更新TextView内容

  • 初始化控件
  • 设置Button的监听方式为内部类监听,原理是通过子线程发送消息,在主线程中更新UI。
  • 定义Handler内部类用于接收并处理来自子线程的消息,并判断当前的count值若大于0,继续延时发送消息,直到数字变为0.

    package com.example.server.testapplication;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
        private static final int START_COUNTING = 1;
        private static final int COUNT_NUMBER = 10;
    
        private Button mCountDown;
        private TextView mStartCount;
        private MyHandler mHandler = new MyHandler();
        private ButtonListener mButtonListener = new ButtonListener();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
        }
    
        private void init() {
            mCountDown = (Button) findViewById(R.id.count_button);
            mCountDown.setOnClickListener(mButtonListener);
            mStartCount = (TextView) findViewById(R.id.count_text);
        }
    
        private class ButtonListener implements View.OnClickListener {
    
            @Override
            public void onClick(View v) {
                mCountDown.setVisibility(View.GONE);
                mStartCount.setVisibility(View.VISIBLE);
    
                Message msg = mHandler.obtainMessage();
                msg.what = START_COUNTING;
                msg.obj = COUNT_NUMBER;
                mHandler.sendMessageDelayed(msg, 10);
            }
        }
    
        private class MyHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
    
                switch (msg.what) {
                    case START_COUNTING:
                        int count = (int) msg.obj;
                        mStartCount.setText(count + "");
                        if (count > 0) {
                            Message msg1 = obtainMessage();
                            msg1.what = START_COUNTING;
                            msg1.obj = count - 1;
                            sendMessageDelayed(msg1, 500);
                        }
                        break;
    
                    default:
                        break;
                }
            }
        };
    
    }

    END

    如果你一不小心,已经看完了,恭喜你,并没有彩蛋。
    我只能祝福你成为
    一个年轻的梦想者,
    热爱代码,
    不受束缚!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在 Android实现倒计时动画,可以参考以下步骤: 1. 创建一个自定义 View,并在其中实现倒计时动画的绘制逻辑。 2. 在 View 中添加一个计时器,每隔一段时间更新倒计时的数值,并调用 invalidate() 方法刷新界面。 3. 在绘制逻辑中,根据当前的倒计时数值计算出圆环的弧度,并使用 Canvas 绘制圆环和数字。 4. 可以添加一些动画效果,例如圆环的渐变填充色、数字的放大缩小等等,增强视觉效果。 以下是一个简单的示例代码,仅供参考: ``` public class CountDownView extends View { private static final long COUNT_DOWN_INTERVAL = 1000; // 倒计时间隔,默认为 1 秒 private static final int DEFAULT_COUNT_DOWN_TIME = 60; // 默认倒计时时间为 60 秒 private Paint mPaint; private RectF mRectF; private float mSweepAngle; private int mCountDownTime; private long mStartTime; private boolean mIsCountingDown; public CountDownView(Context context) { this(context, null); } public CountDownView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CountDownView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 初始化画笔 mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(10); // 初始化圆弧矩形 mRectF = new RectF(); // 初始化倒计时时间 mCountDownTime = DEFAULT_COUNT_DOWN_TIME; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 计算圆弧矩形 int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int size = Math.min(width, height); int padding = 10; mRectF.set(padding, padding, size - padding, size - padding); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制圆弧 mPaint.setColor(Color.GRAY); canvas.drawArc(mRectF, 0, 360, false, mPaint); mPaint.setColor(Color.BLUE); canvas.drawArc(mRectF, -90, mSweepAngle, false, mPaint); // 绘制数字 mPaint.setColor(Color.BLACK); mPaint.setTextSize(50); String text = String.valueOf(mCountDownTime); Rect textBounds = new Rect(); mPaint.getTextBounds(text, 0, text.length(), textBounds); canvas.drawText(text, mRectF.centerX() - textBounds.width() / 2, mRectF.centerY() + textBounds.height() / 2, mPaint); } public void startCountDown() { if (mIsCountingDown) { return; } mIsCountingDown = true; mStartTime = System.currentTimeMillis(); post(countDownRunnable); } public void stopCountDown() { mIsCountingDown = false; removeCallbacks(countDownRunnable); } private Runnable countDownRunnable = new Runnable() { @Override public void run() { long elapsedTime = System.currentTimeMillis() - mStartTime; int remainingTime = mCountDownTime - (int) (elapsedTime / COUNT_DOWN_INTERVAL); if (remainingTime >= 0) { mSweepAngle = (float) remainingTime / mCountDownTime * 360; invalidate(); postDelayed(this, COUNT_DOWN_INTERVAL); } else { stopCountDown(); } } }; } ``` 使用时可以调用 startCountDown() 方法开始倒计时,调用 stopCountDown() 方法停止倒计时

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值