Android仿小米时钟效果

我在一个[博客] android高仿小米时钟(使用Camera和Matrix实现3D效果)上面看到了小米时钟实现.特别感兴趣.就认真的看了一遍.并自己敲了一遍.下面说下我自己的理解和我的一些改进的地方效果真的特别棒就发布了自己的时钟应用。

先上图(电脑没有gif截图软件.大家凑合看.哪个软件好也可以给我推荐下)

话不多说,首先自定义控件XimiClockView继承view  并做一些初始化的操作
看到的漂亮时钟图片我自己画的效果图(以后妈妈再也不用担心我迟到了)

public XimiClockView(Context context) {
  super(context);
  init(context, null);
 }

 public XimiClockView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init(context, attrs);
 }

 public XimiClockView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(context, attrs);
 }

 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 public XimiClockView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
  super(context, attrs, defStyleAttr, defStyleRes);
  init(context, attrs);
 }

 /**
  * 进行一些初始化的操作
  *
  * @param context
  * @param attrs
  */
 private void init(Context context, AttributeSet attrs) {
  if (attrs == null) return;
  TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyClockView);
  backGroundColor = array.getColor(R.styleable.MyClockView_clockBackColor, Color.parseColor("#2078A8"));
  drakColor = array.getColor(R.styleable.MyClockView_clockDarkColor, Color.parseColor("#96C2D8"));
  lightColor = array.getColor(R.styleable.MyClockView_clockLightColor, Color.parseColor("#ffffff"));
  array.recycle();//注意这里别忘了调用recycle()方法,[原因](http://www.cnblogs.com/kissazi2/p/4049982.html)
  //设置背景色
  setBackgroundColor(backGroundColor);
  //文本画笔
  textPaint = new Paint();
  textPaint.setColor(drakColor);
  textPaint.setTextSize(25);
  textRect = new Rect();
 }

然后在onSizeChange方法中调用获取时钟半径,和一些其他的计算

 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  //获取时钟的半径
  mRadius = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom()) / 2;
  //为了防止时钟旋转的时候超出了界限,默认加一个padding值
  defaultPadding = 0.12f * mRadius;
  //圆弧的宽度
  mCircleWidth = 0.012f * mRadius;
  //圆环的宽度
  mCircleRingWidth = 0.12f*mRadius;
  paddingLeft = w / 2 - mRadius + getPaddingLeft() + defaultPadding;
  paddingTop = h / 2 - mRadius + getPaddingTop() + defaultPadding;
  paddingRight = w / 2 - mRadius + getPaddingRight() + defaultPadding;
  paddingBottom = h / 2 - mRadius + getPaddingBottom() + defaultPadding;
  mSweepGradient = new SweepGradient(w / 2,h / 2 ,new int[]{drakColor,lightColor},new float[]{0.75f,1f});
 }

画Text

@Override
 protected void onDraw(Canvas canvas) {
  mCanvas = canvas;
  drawTimeText();
 }

 /**
  * 画12 /3 /6 /9时间
  */
 private void drawTimeText() {
  String str = "12";
  textPaint.getTextBounds(str, 0, str.length(), textRect);
  int lengthTextWidth = textRect.width();
  int textHeight = textRect.height();
  int width=getWidth();
  int height=getHeight();
  mCanvas.save();//保存画布的状态
  mCanvas.drawText(str, width / 2-lengthTextWidth/2,paddingTop+textHeight,textPaint);
  str="3";
  textPaint.getTextBounds(str, 0, str.length(), textRect);
  int smallTextWidth = textRect.width();
  mCanvas.drawText("3",width-paddingRight-lengthTextWidth/2-smallTextWidth/2,height/2+textHeight/2,textPaint);
  mCanvas.drawText("6",width / 2-smallTextWidth/2,height-paddingBottom,textPaint);
  mCanvas.drawText("9",paddingLeft,height/2+textHeight/2,textPaint);
  mCanvas.restore();//取出画布的状态
 }

崩溃写完了,我发表时候提示我没有登录,然后发表异常,然后我一刷新没了,,,又重新写一遍,

接下来画圆弧

 /**
  * 画圆弧
  */
 private void drawCircleArc() {
  mCanvas.save();
  mCirclePaint.setStyle(Paint.Style.STROKE);//设置空心模式
  mCirclePaint.setStrokeWidth(mCircleWidth);//设置圆弧宽度
  mCircleRectF.set(paddingLeft + textRect.width() / 2, paddingTop + textRect.height() / 2, getWidth() - paddingRight - textRect.width() / 2, getHeight() - paddingBottom - textRect.height() / 2);
  for (int x = 0; x < 4; x++) {
  //圆弧分四段来画,一段话80度
   mCanvas.drawArc(mCircleRectF, 5 + 90 * x, 80, false, mCirclePaint);
  }
  mCanvas.restore();
 }

画刻度

/**
  * 画圆环和刻度
  */
 private void drawCircleRing() {
  mCanvas.save();
  //画圆环
  mCircleRingRectF.set(paddingLeft+textRect.height()/2+1.5f*mCircleRingWidth,paddingTop+textRect.height()/2+1.5f*mCircleRingWidth,getWidth()-paddingRight-textRect.height()/2-1.5f*mCircleRingWidth,
    getHeight()-paddingBottom-textRect.height()/2-1.5f*mCircleRingWidth);
  mMatrix.setRotate(mDegreeS-90,getWidth()/2,getHeight()/2);
  mSweepGradient.setLocalMatrix(mMatrix);
  mCircleRingPaint.setStyle(Paint.Style.STROKE);
  mCircleRingPaint.setStrokeWidth(mCircleRingWidth);
  mCircleRingPaint.setShader(mSweepGradient);
  mCanvas.drawArc(mCircleRingRectF,0,360,false,mCircleRingPaint);
  //画刻度
  mScaleLinePaint.setStrokeWidth(0.1f*mCircleRingWidth);//设置线的宽度
  for (int i=0;i<200;i++){
   //画刻度线
   mCanvas.drawLine(getWidth()/2,paddingTop+textRect.height()/2+mCircleRingWidth,getWidth()/2,paddingTop+textRect.height()/2+2*mCircleRingWidth,mScaleLinePaint);
   mCanvas.rotate(1.8f,getWidth()/2,getHeight()/2);//旋转角度
  }
  mCanvas.restore();
 }

画秒针

 /**
  * 画秒针
  * 秒针针是不规则的图形
  * 就用到了Path这个类
  *
  */
 private void drawSoundHand() {
  mCanvas.save();
  path.reset();
  mCanvas.rotate(mDegreeS,getWidth()/2,getHeight()/2);//旋转的角度和旋转的圆心
  path.moveTo(getWidth()/2,paddingTop+textRect.height()/2+0.27f*mRadius);//开始的点
  path.lineTo(getWidth()/2+0.03f*mRadius,paddingTop+textRect.height()/2+0.31f*mRadius);//直线到这个位置
  path.lineTo(getWidth()/2-0.03f*mRadius,paddingTop+textRect.height()/2+0.31f*mRadius);//直线到这个位置
  path.close();
  mCanvas.drawPath(path,mSoundHandPaint);
  mCanvas.restore();
 }

画时针

 /**
  * 画时针
  */
 private void drawHourHand() {
  mCanvas.save();
  mCanvas.rotate(mDegreeH,getWidth()/2,getHeight()/2);
  hourHandPath.reset();
  hourHandPath.moveTo(getWidth()/2-0.02f*mRadius,getHeight()/2);
  hourHandPath.lineTo(getWidth()/2-0.01f*mRadius,getHeight()/2-0.35f*mRadius);
  //贝塞尔曲线
  hourHandPath.quadTo(getWidth()/2,getHeight()/2-0.38f*mRadius,getWidth()/2+0.01f*mRadius,getHeight()/2-0.35f*mRadius);
  hourHandPath.lineTo(getWidth()/2+0.02f*mRadius,getHeight()/2);
  hourHandPath.close();
  mCanvas.drawPath(hourHandPath,mHourHandPaint);
  mCanvas.restore();
 }

画分针

 /**
  * 画分针
  */
 private void drawMinnuteHand() {
  mCanvas.save();
  mCanvas.rotate(mDegreeM,getWidth()/2,getHeight()/2);
  mMinutePath.reset();
  mMinutePath.moveTo(getWidth()/2-0.012f*mRadius,getHeight()/2);
  mMinutePath.lineTo(getWidth()/2-0.006f*mRadius,getHeight()/2-0.40f*mRadius);
  mMinutePath.quadTo(getWidth()/2,getHeight()/2-0.43f*mRadius,getWidth()/2+0.006f*mRadius,getHeight()/2-0.40f*mRadius);
  mMinutePath.lineTo(getWidth()/2+0.012f*mRadius,getHeight()/2);
  mMinutePath.close();
  mCanvas.drawPath(mMinutePath,mMinutePaint);
  //画圈圈盖着时针的尾部
  mCanvas.drawCircle(getWidth()/2,getHeight()/2,0.03f*mRadius,mMinutePaint);
  mCanvas.drawCircle(getWidth()/2,getHeight()/2,0.015f*mRadius,mCircleMinPaint);
  mCanvas.restore();
 }

上我的measure的方法

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  setMeasuredDimension(getMeasure(widthMeasureSpec), getMeasure(heightMeasureSpec));
 }

 private int getMeasure(int measureSpec) {
  int result;
  int mode = MeasureSpec.getMode(measureSpec);
  int size = MeasureSpec.getSize(measureSpec);
  if (mode == MeasureSpec.EXACTLY) {
   result = size;
  } else {
   result = 800;
   if (mode == MeasureSpec.AT_MOST) {
    result = Math.min(result, size);
   }
  }
  return result;
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android多功能时钟开发案例(实战篇)

    上一篇为大家介绍的是Android多功能时钟开发基础内容,大家可以回顾一下,Android多功能时钟开发案例(基础篇) 接下来进入实战,快点来学习吧. 一.时钟 在布局文件中我们看到,界面上只有一个TextView,这个TextView的作用就是显示一个系统的当前时间,同时这个时间还是一秒一秒跳的,要实现一秒一秒的跳就需要我们每隔一秒就要刷新一下,同时我们这里还考虑了切换到另一个Tab的时候,这个时间就不跳动了,这样就会减少这个对系统的占用,考虑到了这点我们在这里用到了Handler,通过han

  • Android 仿日历翻页、仿htc时钟翻页、数字翻页切换效果

    废话不多说,效果图: 自定义控件找自网络,使用相对简单,具体还没有来得及深入研究,只是先用笨方法大概实现了想要的效果,后续有空会仔细研究再更新文章, 本demo切换方法是用的笨方法,也就是由新数字和旧数字相比较来切换数字变换的,大致使用方法如下: //获取输入框中的数字 int newNumber = Integer.parseInt(etInput.getText().toString()); //获取个.十.百位数字 int nbai = newNumber / 100; int nshi

  • Android通过Path实现搜索按钮和时钟复杂效果

    在Android中复杂的图形的绘制绝大多数是通过path来实现,比如绘制一条曲线,然后让一个物体随着这个曲线运动,比如搜索按钮,比如一个简单时钟的实现: 那么什么是path呢! 定义:path  就是路径,就是图形的路径的集合,它里边包含了路径里边的坐标点,等等的属性.我们可以获取到任意点的坐标,正切值. 那么要获取Path上边所有点的坐标还需要用到一个类,PathMeasure; PathMesure: PathMeasure是一个用来测量Path的类,主要有以下方法: 构造方法 公共方法 可

  • android高仿小米时钟(使用Camera和Matrix实现3D效果)

    继续练习自定义View..毕竟熟才能生巧.一直觉得小米的时钟很精美,那这次就搞它~这次除了练习自定义View,还涉及到使用Camera和Matrix实现3D效果. 一个这样的效果,在绘制的时候最好选择一个方向一步一步的绘制,这里我选择由外到内.由深到浅的方向来绘制,代码步骤如下: 1.首先老一套~新建attrs.xml文件,编写自定义属性如时钟背景色.亮色(用于分针.秒针.渐变终止色).暗色(圆弧.刻度线.时针.渐变起始色),新建MiClockView继承View,重写构造方法,获取自定义属性值

  • Android多功能时钟开发案例(基础篇)

    本文我们进入Android多功能时钟开发实战学习,具体的效果可以参考手机上的时钟,内容如下 首先我们来看一看布局文件layout_main.xml 整个布局: <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="match_parent" androi

  • Android获取设备CPU核数、时钟频率以及内存大小的方法

    本文实例讲述了Android获取设备CPU核数.时钟频率以及内存大小的方法.分享给大家供大家参考,具体如下: 因项目需要,分析了一下 Facebook 的开源项目 - Device Year Class. Device Year Class 的主要功能是根据 CPU核数.时钟频率 以及 内存大小 对设备进行分级.代码很简单,只包含两个类: DeviceInfo -> 获取设备参数, YearClass -> 根据参数进行分级. 下表是 Facebook 公司提供的分级标准,其中 Year 栏表

  • Android画个时钟玩玩

    先看下最终的效果 开始实现 新建一个ClockView集成View public class ClockView extends View { } 先重写onMeasure方法,这里要先说一下View的测量模式,一共有三种: 1.EXACTLY 即精确值模式,当我们将控件的layout_width属性或layout_height属性指定为具体数值时,比如android:layout_width="100dp",或者指定为math_parent属性时(占据父View的大小),系统使用的是

  • Android实现简单时钟View的方法

    通过Canvas的平移与旋转简化绘图逻辑是一个非常有用的技巧,下面的时钟view就是利用这个方法完成的,省去了使用三角函数计算坐标的麻烦. package com.example.swt369.simpleclock; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.Nullable; i

  • Android ActionBar制作时钟实例解析

    本文实例为大家分享了Android ActionBar制作时钟的具体代码,供大家参考,具体内容如下 1. MainActivity.java   package com.example.days19actionbar07custom; import com.example.days19actionbar07custom.R; import android.app.Activity; import android.os.Bundle; import android.view.Menu; impor

  • android实现widget时钟示例分享

    一.在 AndroidManifest.xml文件中配置Widgets: 复制代码 代码如下: <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.widget"    android:versionCode="1"    android:versionName="1.0" >   

随机推荐