Android酷炫计时器

背景

最近刷到一张计时器效果图(如图),而个人项目中正需要一个沉浸式的计时器页面,就把这种效果实现。下面就分享一下实现过程。

在这里插入图片描述

分析

效果图可以分为三层:

  • 第一层:最底层的紫色模糊光晕效果
  • 第二层:是由蓝色、浅红色、白色、淡蓝色、紫色、深紫色等颜色的圆或椭圆组成
  • 第三层:倒计时文字

整体的效果会通过自定义view来实现,所以对自定义view不是很熟悉的小伙伴,可以看一下大神写的这篇文章:

没见过这么详细的,自定义控件图形探索!

第一层

紫色模糊光晕效果。Paint.setMaskFilter(MaskFilter maskfilter)方法,可以用来对图像添加遮罩滤镜效果。MaskFilter类有两个子类BlurMaskFilter和EmbossMaskFilter,前者为模糊遮罩滤镜而后者为浮雕遮罩滤镜。如果对此方法不熟悉,可以看下这篇文章:

详解Paint的setMaskFilter(MaskFilter maskfilter)

//设置画笔
mLightPaint = new Paint();
// 抗锯齿效果
mLightPaint.setAntiAlias(true);
// 设置颜色
mLightPaint.setColor(0xFF5A00FF);
// 半径
mLightRadius = (int) getResources().getDimension(R.dimen.dp_105);
// 设置模糊遮罩滤镜
mLightPaint.setMaskFilter(new BlurMaskFilter(mLightRadius, BlurMaskFilter.Blur.OUTER));

绘制

int cx = getWidth() / 2;
int cy = getHeight() / 2;
canvas.drawCircle(cx, cy, mLightRadius, mLightPaint);

第二层

蓝色、浅红色、白色、淡蓝色、紫色、深紫色等颜色的圆或椭圆。为方便描述对第二层的图像按颜色进行分类,大体如下:

在这里插入图片描述

大体可以看出来蓝色和深紫色是圆形,只是半径和中心点不一样。而其他颜色图像都是椭圆,大小和中心点有所差异。进过多次调整,找到最接近的绘制效果。

计算图形大小及偏移:

//蓝色圆半径及中心点
mBlueRadius = (int) getResources().getDimension(R.dimen.dp_105);
mBlueCx = w / 2;
mBlueCy = h / 2;
//浅红色椭圆大小及偏移
int lightW = (int) getResources().getDimension(R.dimen.dp_210);
int lightH = (int) getResources().getDimension(R.dimen.dp_187);
int paddingX = (w - lightW) / 2;
int paddingY = (h - lightH) / 2;
mLightRedRect = new RectF(paddingX, paddingY, w - paddingX, h - paddingY);
//白色椭圆大小及偏移
lightW = (int) getResources().getDimension(R.dimen.dp_166);
lightH = (int) getResources().getDimension(R.dimen.dp_147);
paddingX = (w - lightW) / 2;
paddingY = (h - lightH) / 2;
mWhiteRect = new RectF(paddingX, paddingY, w - paddingX, h - paddingY);
//浅蓝色椭圆大小及偏移
lightW = (int) getResources().getDimension(R.dimen.dp_206);
lightH = (int) getResources().getDimension(R.dimen.dp_185);
paddingX = (w - lightW) / 2;
paddingY = (h - lightH) / 2;
mLightBlueRect = new RectF(paddingX, paddingY, w - paddingX, h - paddingY);
//紫色椭圆大小及偏移
lightW = (int) getResources().getDimension(R.dimen.dp_195);
lightH = (int) getResources().getDimension(R.dimen.dp_200);
paddingX = (w - lightW) / 2;
paddingY = (h - lightH) / 2;
mPurpleRect = new RectF(paddingX, paddingY, w - paddingX, h - paddingY);
//深紫色圆半径
mDarkPurpleRadius = (int) getResources().getDimension(R.dimen.dp_96);

绘制

//绘制
canvas.save();
mRingPaint.setColor(mLightRedColor);
int translateY;
int translateX = (int) getResources().getDimension(R.dimen.dp_2);
canvas.translate(-translateX, -translateX);
canvas.rotate(mLightRedRotate, cx, cy);
canvas.drawOval(mLightRedRect, mRingPaint);
canvas.restore();

canvas.save();
mRingPaint.setColor(mWhiteColor);
translateX = (int) getResources().getDimension(R.dimen.dp_15);
canvas.translate(-translateX, -translateX);
canvas.rotate(mWhiteRotate, cx, cy);
canvas.drawOval(mWhiteRect, mRingPaint);
canvas.restore();

canvas.save();
mRingPaint.setColor(mLightBlueColor);
translateX = (int) getResources().getDimension(R.dimen.dp_2);
canvas.translate(translateX, 0);
canvas.rotate(mLightBlueRotate, cx, cy);
canvas.drawOval(mLightBlueRect, mRingPaint);
canvas.restore();

canvas.save();
mRingPaint.setColor(mPurpleColor);
translateY = (int) getResources().getDimension(R.dimen.dp_2);
canvas.translate(0, translateY);
canvas.rotate(mPurpleRotate, cx, cy);
canvas.drawOval(mPurpleRect, mRingPaint);
canvas.restore();

mRingPaint.setColor(0xFF1E1C42);
canvas.drawCircle(cx, cy, mDarkPurpleRadius, mRingPaint);

第三层

倒计时文字绘制。倒计时功能使用CountDownTimer实现,每隔一秒刷新。

设置文字大小,计算基线:

//文字画笔参数设置
mTextPaint = new Paint();
mTextSize = getResources().getDimension(R.dimen.sp_32);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(mTextColor);
mTextPaint.setAntiAlias(true);
//计算文字基线
Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
mTextBaseLine = getHeight() / 2f - metrics.descent + (metrics.bottom - metrics.top) / 2;

绘制

int minute = (int) (mMillisUntilFinished / 1000 / 60);
int second = (int) (mMillisUntilFinished / 1000 % 60);
String text = (minute < 10 ? ("0" + minute) : minute) + ":" + (second < 10 ? ("0" + second) : second);
mTextPaint.measureText(text);
float textWidth = mTextPaint.measureText(text);
canvas.drawText(text, (getWidth() - textWidth) / 2, mTextBaseLine, mTextPaint);
changeRotate();

使用

public void setTime(long millis) {
    reset();
    mResetMillis = millis;
    mTotalMillis = millis;
    mMillisUntilFinished = mTotalMillis;
    invalidate();
}

public void start() {
    mCountDownTimer = new CountDownTimer(mTotalMillis, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            mMillisUntilFinished = millisUntilFinished;
            invalidate();
        }

        @Override
        public void onFinish() {
            reset();
        }
    };
    mCountDownTimer.start();
}

public void reset() {
    if (mCountDownTimer != null) {
        mCountDownTimer.cancel();
        mCountDownTimer = null;
        mTotalMillis = mResetMillis;
        mMillisUntilFinished = mTotalMillis;
        invalidate();
    }
}

最终效果

在这里插入图片描述

效果和原图效果大体差不多。

源码地址:https://github.com/Jallv/JTodo/blob/master/app/src/main/java/com/jal/todo/widget/FocusCountDownView.java

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值