Android仿华为手机时钟功能
最近看到华为手机自带的时钟挺漂亮的,就想着自己做一个
先上效果图:

实现步骤:
1、添加依赖
implementation "io.reactivex.rxjava2:rxjava:2.2.3"implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
2、自定义属性(其实可以有更多自定义属性)
<!--仿华为时钟--><declare-styleable name="HuaWeiClock"><!--背景颜色--><attr name="backgroundColor" format="color" /><!--竖线颜色--><attr name="secondLineColor" format="color" /><!--秒针点的颜色--><attr name="secondPointColor" format="color" /><!--时间的颜色--><attr name="timeColor" format="color" /></declare-styleable>
3、自定义控件实现
public class HuaWeiClock extends View {/*** 背景颜色*/private int backgroundColor;/*** 秒针竖线的颜色*/private int secondLineColor;/*** 秒针红色点的颜色*/private int secondPointColor;/*** 时间的颜色*/private int timeColor;private Paint mPaint;/*** 背景宽度*/private int widthBg;/*** 背景高度*/private int heightBg;/*** 钟表半径*/private int watchRadius;/*** 秒针红点的半径*/private static final int SECOND_POINT_RADIUS = 20;/*** 线最长的长度*/private static final int LINE_MAX_LENGTH = 60;/*** 线最短的长度*/private static final int LINE_MIN_LENGTH = 30;/*** 秒刻度白线的数量*/private static final int LINE_COUNT = 120;/*** 每根针占的角度*/private static final int ONE_LINE_ANGLE = 360 / LINE_COUNT;/*** 秒针的角度*/private float angle;private String time = "00:00";/*** 长于普通秒针刻度的驼峰一侧的条数*/private static final int LONG_LINE_COUNT = 7;/*** 一侧7根长针的角度*/private static final int LONG_LINES_ANGLE = ONE_LINE_ANGLE * LONG_LINE_COUNT;public HuaWeiClock(Context context) {this(context, null);}public HuaWeiClock(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public HuaWeiClock(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HuaWeiClock);backgroundColor = typedArray.getColor(R.styleable.HuaWeiClock_backgroundColor, Color.parseColor("#003560"));secondLineColor = typedArray.getColor(R.styleable.HuaWeiClock_secondLineColor, Color.WHITE);secondPointColor = typedArray.getColor(R.styleable.HuaWeiClock_secondPointColor, Color.parseColor("#CE3228"));timeColor = typedArray.getColor(R.styleable.HuaWeiClock_timeColor, Color.WHITE);typedArray.recycle();initPaint();startTime();}/*** 初始化画笔*/private void initPaint() {mPaint = new Paint();mPaint.setAntiAlias(true);}/*** 获取时间,并通过RxJava实现动画*/@SuppressLint("CheckResult")private void startTime() {//延时0秒后每隔100毫秒,刷新一次UIObservable.interval(0, 100, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new io.reactivex.functions.Consumer<Long>() {@Overridepublic void accept(Long aLong) throws Exception {Calendar calendar = Calendar.getInstance();int second = calendar.get(Calendar.SECOND);int milliSecond = calendar.get(Calendar.MILLISECOND);angle = (float) (second * 1000 + milliSecond) * 6 / 1000f;SimpleDateFormat minuteFormat = new SimpleDateFormat("HH:mm");time = minuteFormat.format(calendar.getTime());postInvalidate();}});}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = 0;int height = 0;int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);switch (widthMode) {case MeasureSpec.AT_MOST:width = widthSize * 3 / 4;break;case MeasureSpec.EXACTLY:width = widthSize;break;case MeasureSpec.UNSPECIFIED:break;default:break;}switch (heightMode) {case MeasureSpec.AT_MOST:height = heightSize / 2;break;case MeasureSpec.EXACTLY:height = heightSize;break;case MeasureSpec.UNSPECIFIED:break;default:break;}widthBg = width;heightBg = height;watchRadius = height * 2 / 5;setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas) {drawBg(canvas);drawTickMark(canvas);drawSecondPoint(canvas);drawTime(canvas);}/*** 画背景** @param canvas 画板*/private void drawBg(Canvas canvas) {mPaint.setColor(backgroundColor);mPaint.setStyle(Paint.Style.FILL);RectF rectBg = new RectF(0, 0, widthBg, heightBg);canvas.drawRect(rectBg, mPaint);}/*** 画刻度线** @param canvas 画板*/private void drawTickMark(Canvas canvas) {mPaint.setColor(secondLineColor);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(3);for (int i = 0; i < LINE_COUNT; i++) {//角度差的绝对值float absoluteValue = Math.abs(i * ONE_LINE_ANGLE - angle);//求 刻度针线 和 秒针 之间的角度(小于180度)float differenceAngle = absoluteValue <= 180 ? absoluteValue : 360 - absoluteValue;//大于七根长线刻度的线,那么长度固定if (differenceAngle > LONG_LINES_ANGLE) {canvas.drawLine(widthBg / 2, heightBg / 2 - watchRadius, widthBg / 2, heightBg / 2 - watchRadius + LINE_MIN_LENGTH, mPaint);canvas.rotate(3, widthBg / 2, heightBg / 2);} else {canvas.drawLine(widthBg / 2, heightBg / 2 - watchRadius - (1 - differenceAngle / LONG_LINES_ANGLE) * (LINE_MAX_LENGTH - LINE_MIN_LENGTH), widthBg / 2, heightBg / 2 - watchRadius + LINE_MIN_LENGTH, mPaint);canvas.rotate(3, widthBg / 2, heightBg / 2);}}}/*** 画秒表的红点** @param canvas 画布*/private void drawSecondPoint(Canvas canvas) {mPaint.setColor(secondPointColor);mPaint.setStyle(Paint.Style.FILL);int secondPointRadiusBig = watchRadius - LINE_MIN_LENGTH - SECOND_POINT_RADIUS - 20;double pointAngle = angle * Math.PI / 180;canvas.drawCircle((float) (widthBg / 2 + secondPointRadiusBig * Math.sin(pointAngle)), (float) (heightBg / 2 - secondPointRadiusBig * Math.cos(pointAngle)), SECOND_POINT_RADIUS, mPaint);}/*** 画时间** @param canvas 画布*/private void drawTime(Canvas canvas) {mPaint.setColor(timeColor);mPaint.setStyle(Paint.Style.FILL);mPaint.setTextSize(widthBg / 7);Rect bounds = new Rect();mPaint.getTextBounds(time, 0, time.length(), bounds);Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();int baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;canvas.drawText(time, getMeasuredWidth() / 2 - bounds.width() / 2, baseline, mPaint);}}
4、布局文件中引入
<com.sjl.keeplive.huawei.HuaWeiClockandroid:id="@+id/huaWeiClock"android:layout_width="match_parent"android:layout_height="wrap_content"app:backgroundColor="#003560"app:secondLineColor="@android:color/white"app:secondPointColor="#CE3228"app:timeColor="@android:color/white" />
到这里就完成了,代码都贴出来啦.
评论
