一个模仿小米手机秒表样式的安卓小应用程序,利用自定义控件实现。

超详细的代码注释

开发工具为:Android Studio

看图

代码:

大表盘自定义控件:【xiaomiClock 】

public class xiaomiClock extends View {    private Paint textPaint,paint;    private Path mTriangle;    private Timer mTimer;    private float agree = 1;    private Shader mshader;    private PathEffect mEffect;    public xiaomiClock(Context context) {        super(context);    }    public xiaomiClock(Context context, AttributeSet attrs) {        super(context, attrs);        //mEffect = new DashPathEffect(new float[]{1,2,5,10,50,20}, 0);    // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}        mEffect = new DashPathEffect(new float[]{5,0}, 0);    // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}        mshader = new SweepGradient(500, 500, Color.parseColor("#3b3b3b"), Color.parseColor("#ffffff"));    //渐变遮罩样式        textPaint = new Paint();        textPaint.setStrokeWidth(16);        textPaint.setColor(Color.WHITE);        textPaint.setStrokeCap(Paint.Cap.ROUND);        textPaint.setAntiAlias(true);        paint = new Paint();        paint.setAntiAlias(true);        mTriangle = new Path();        mTriangle.moveTo(960, 500);// 此点为多边形的顶点【三角形(指针)】        //下面两个x 相等,表示底边的位置        mTriangle.lineTo(1000, 525);  // y:底边宽的其中一个顶点        mTriangle.lineTo(1000, 475);  //y:底边宽的其中一个顶点        mTriangle.close();        setmTimer();        System.out.println("度数" + ((float) 6.0 / 10));    }    @Override    protected void onDraw(Canvas canvas) {        //绘画手表盘        drawbeauty(canvas);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        //设置宽高        setMeasuredDimension(1000,1000);  //画布大小    }    public void drawbeauty(Canvas canvas) {        int canvasWidth = canvas.getWidth();        int canvasHeight = canvas.getHeight();        //设置缓存层,因为下面要实用xfermode,使用xfemode必须使用缓存层,否则会出现黑色背景        int layerId = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);        //初始化画笔,因为上下两层做画需要的画笔属性不一样,所以只能每次重新设置一次        paint.setStyle(Paint.Style.STROKE);     //设置画笔为不填充模式        paint.setPathEffect(mEffect);           //设置笔画样式,这里设置的是虚线样式        paint.setStrokeWidth(50);               //设置笔画宽度        canvas.drawCircle(500, 500, 420, paint);    //画一个纯色表盘,虚线,空心圆形 【表盘位置和大小】        //设置画笔属性,SRC_IN属性,让第二个图案只能花在第一个图案上面,也就是只能画在上面所说那个纯色表盘里面        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));        //把画笔虚线属性去掉,因为我要的是一个实心圆形,然后让这个实心但是颜色不一样圆形画在上面所说表盘上面,因为设置了xfermode,所以显示的一样会是虚线圆形表盘,但是颜色会变成你现在的颜色        paint.setPathEffect(null);        //设置画笔shader属性,这里设置的是SweepGradient模式,可以让颜色过渡泾渭分明,以圆形为中心开始变化        paint.setShader(mshader);        paint.setStyle(Paint.Style.FILL);        canvas.save();      //保存画布        //旋转画布,然后你就会发现时钟表盘开始动了        canvas.rotate(agree, 500, 500);    //画布旋转的中心点        canvas.drawRect(10, 10, 1000, 1100, paint);   //渐变矩形绘制        canvas.drawPath(mTriangle, textPaint);    //绘制小三角形        canvas.restore();        //最后将画笔去除Xfermode        paint.setXfermode(null);        canvas.restoreToCount(layerId);    }    private void setmTimer() {        mTimer = new Timer();        mTimer.schedule(new TimerTask() {            @Override            public void run() {                agree = agree + 0.022f;//数值越大,旋转速度越快                if (agree > 360)                    agree = 1;                postInvalidate();            }        }, 1000, 3);  //延时/周期    }}

小码表表盘自定义控件:【xiaomiClock 02】

public class xiaomiClock02 extends View {    private Paint textPaint,paint;    private Path mTriangle;    private Timer mTimer;    private float agree = 1;    private Shader  mshader;    private PathEffect mEffect;    public xiaomiClock02(Context context) {        super(context);    }    public xiaomiClock02(Context context, AttributeSet attrs) {        super(context, attrs);        //mEffect = new DashPathEffect(new float[]{1,2,5,10,50,20}, 0);    // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}        mEffect = new DashPathEffect(new float[]{5,0}, 0);    // float[]{ 虚线的厚度, 虚线的间距,虚线的厚度, 虚线的间距 ......}        mshader = new SweepGradient(110, 110, Color.parseColor("#3b3b3b"), Color.parseColor("#ffffff"));    //渐变遮罩样式【渐变色的渐变中心点以及颜色】        textPaint = new Paint();        textPaint.setStrokeWidth(16);        textPaint.setColor(Color.WHITE);        textPaint.setStrokeCap(Paint.Cap.ROUND);        textPaint.setAntiAlias(true);        paint = new Paint();        paint.setAntiAlias(true);        mTriangle = new Path();        mTriangle.moveTo(190, 110);// 此点为多边形的顶点【三角形(指针)】        //下面两个x 相等,表示底边的位置        mTriangle.lineTo(110, 112);  // y:底边宽的其中一个顶点        mTriangle.lineTo(110, 108);  //y:底边宽的其中一个顶点        mTriangle.close();        setmTimer();        System.out.println("度数" + ((float) 6.0 / 10));    }    @Override    protected void onDraw(Canvas canvas) {        //绘画手表盘        drawbeauty(canvas);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        //设置宽高        setMeasuredDimension(220,220);  //画布大小    }    public void drawbeauty(Canvas canvas) {        int canvasWidth = canvas.getWidth();        int canvasHeight = canvas.getHeight();        //设置缓存层,因为下面要实用xfermode,使用xfemode必须使用缓存层,否则会出现黑色背景        int layerId = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);        //初始化画笔,因为上下两层做画需要的画笔属性不一样,所以只能每次重新设置一次        paint.setStyle(Paint.Style.STROKE);     //设置画笔为不填充模式        paint.setPathEffect(mEffect);           //设置笔画样式,这里设置的是虚线样式        paint.setStrokeWidth(2);               //设置笔画宽度        canvas.drawCircle(110, 110, 100, paint);    //画一个纯色表盘,虚线,空心圆形 【表盘位置和大小】        //设置画笔属性,SRC_IN属性,让第二个图案只能花在第一个图案上面,也就是只能画在上面所说那个纯色表盘里面        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));        //把画笔虚线属性去掉,因为我要的是一个实心圆形,然后让这个实心但是颜色不一样圆形画在上面所说表盘上面,因为设置了xfermode,所以显示的一样会是虚线圆形表盘,但是颜色会变成你现在的颜色        paint.setPathEffect(null);        //设置画笔shader属性,这里设置的是SweepGradient模式,可以让颜色过渡泾渭分明,以圆形为中心开始变化        paint.setShader(mshader);        paint.setStyle(Paint.Style.FILL);        canvas.save();      //保存画布        //旋转画布,然后你就会发现时钟表盘开始动了        canvas.rotate(agree, 110, 110);    //画布旋转的中心点        canvas.drawRect(1, 1, 220, 220, paint);   //渐变矩形绘制        canvas.drawPath(mTriangle, textPaint);    //绘制小三角形        canvas.restore();        //最后将画笔去除Xfermode        paint.setXfermode(null);        canvas.restoreToCount(layerId);    }    private void setmTimer() {        mTimer = new Timer();        mTimer.schedule(new TimerTask() {            @Override            public void run() {                agree = agree + 0.2f + 1f;//数值越大,旋转速度越快                if (agree > 360)                    agree = 1;                postInvalidate();            }        }, 1000, 3);  //延时/周期    }}

BaseActivity设置主题为黑色

public class BaseActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //主题设置        setTheme(R.style.AppTheme01);    }}

主题Styles样式

    

MainActivity 设置时间代码

public class MainActivity extends BaseActivity{    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        new DataThread().start();  //时间控制线程    }    //设定显示系统时间    private String getData() {        long sysTime = System.currentTimeMillis();        CharSequence sysTimeStr = DateFormat.format("" + "yyyy/MM/dd", sysTime);        return (String) sysTimeStr;    }    @SuppressLint("HandlerLeak")    private Handler mHandlerData = new Handler() {        public void handleMessage(android.os.Message msg) {            TextView textView = findViewById(R.id.Time_TextView01);  //确定系统时间变化的控件            textView.setText((String) msg.obj);        }    };    //设定显示系统时间    private String getTime() {        long sysTime = System.currentTimeMillis();        CharSequence sysTimeStr = DateFormat.format("" + "HH:mm:ss", sysTime);        return (String) sysTimeStr;    }    @SuppressLint("HandlerLeak")    private Handler mHandlerTime = new Handler() {        public void handleMessage(android.os.Message msg) {            TextView textView = findViewById(R.id.Time_TextView02);  //确定系统时间变化的控件            textView.setText((String) msg.obj);        }    };    private class DataThread extends Thread {        @Override        public void run() {            for (int i = 0; i < 999999999; i++) {    //一共变化多少次次                try {                    Thread.sleep(10);   //每一毫秒变化一次                } catch (InterruptedException e) {                    e.printStackTrace();                }                final String sysTime = getTime();                final String sysData = getData();                // 只能在主线程中修改ui控件                mHandlerData.sendMessage(mHandlerData.obtainMessage(0, sysData));  //系统日期                mHandlerTime.sendMessage(mHandlerTime.obtainMessage(0, sysTime));  //系统时间            }        }    }}

.
App下载:https://aifabu.com/iUfi

源码下载:https://download.csdn.net/download/erp_lxkun_jak/11240191
【注意:使用开发工具是 Android Studio 哦!】
.
.
感谢你的查阅,希望可以帮到你,祝你学习愉快!

我是和你一起学习的 易君

更多相关文章

  1. Android画图demo
  2. android 简单的画图操作
  3. android 圆形进度条的简单实现
  4. android 绘图--简单手写绘图后保存为图片(demo)
  5. Android(安卓)自己画View设置画笔的颜色
  6. Android绘图篇(一)——Canvans基本操作
  7. 【Android应用实例之二】跟随手指的小球——自定义View应用
  8. Android本地验证码的生成
  9. Android(安卓)Canvas绘制直方图

随机推荐

  1. SQl Function 创建函数实例介绍
  2. Sqlserver 自定义函数 Function使用介绍
  3. SQL Function 自定义函数详解
  4. 数据库 关键字一览表
  5. sql server 自定义分割月功能详解及实现
  6. SQL Server 实现数字辅助表实例代码
  7. Python版Mssql爆破小脚本
  8. SQL分页查询方式汇总
  9. SqlServer中如何解决session阻塞问题
  10. MySQL 5.7 create VIEW or FUNCTION or P