https://www.2cto.com/kf/201509/443112.html

概述:

Android自带的View满足不了开发者时,自定义View就发挥了很好的作用。
建立一个自定义View,需要继承于View类,并且实现其中的至少一个构造函数和两个方法:onMeasure()和onDraw();
onMeasure()用于设置自定义View的尺寸,onDraw()用于绘制View中的内容。

在onDraw()方法中,需要调用画笔绘制图形或文本,绘制的模板时Canvas对象, Canvas类中用来绘制图形文本的方法有:

drawRect(RectF rect, Paint paint) //绘制区域,参数一为RectF一个区域

drawPath(Path path, Paint paint) //绘制一个路径,参数一为Path路径对象

drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) //贴图,参数一就是我们常规的Bitmap对象,参数二是源区域(这里是bitmap),参数三是目标区域(应该在canvas的位置和大小),参数四是Paint画刷对象,因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失。

drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) //画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint 画刷对象。

drawPoint(float x, float y, Paint paint) //画点,参数一水平x轴,参数二垂直y轴,第三个参数为Paint对象。

drawText(String text, float x, floaty, Paint paint) //渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。

drawOval(RectF oval, Paint paint)//画椭圆,参数一是扫描区域,参数二为paint对象;

drawCircle(float cx, float cy, float radius,Paint paint)// 绘制圆,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象;

drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//画弧,参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象。

绘制图形需要画笔Paint对象,Paint类中的方法有:

setARGB(int a, int r, int g, int b) // 设置 Paint对象颜色,参数一为alpha透明值

setAlpha(int a) // 设置alpha不透明度,范围为0~255

setAntiAlias(boolean aa) // 是否抗锯齿

setColor(int color) // 设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义

setTextScaleX(float scaleX) // 设置文本缩放倍数,1.0f为原始

setTextSize(float textSize) // 设置字体大小

setUnderlineText(booleanunderlineText) // 设置下划线

public class MyView extends View {
 
    private int width;
    private int height;
    private Paint mPaintLine;
    private Paint mPaintCircle;
    private Paint mPaintHour;
    private Paint mPaintMinute;
    private Paint mPaintSec;
    private Paint mPaintText;
    private Calendar mCalendar;
    public static final int NEED_INVALIDATE = 0X23;
 
    //每隔一秒,在handler中调用一次重新绘制方法
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
 
            switch (msg.what){
                case NEED_INVALIDATE:
                    mCalendar = Calendar.getInstance();
                    invalidate();//告诉UI主线程重新绘制
                    handler.sendEmptyMessageDelayed(NEED_INVALIDATE,1000);
                    break;
                default:
                    break;
            }
        }
    };
 
    public MyView(Context context) {
        super(context);
    }
 
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
 
        mCalendar = Calendar.getInstance();
 
        mPaintLine = new Paint();
        mPaintLine.setColor(Color.BLUE);
        mPaintLine.setStrokeWidth(10);
 
        mPaintCircle = new Paint();
        mPaintCircle.setColor(Color.GREEN);//设置颜色
        mPaintCircle.setStrokeWidth(10);//设置线宽
        mPaintCircle.setAntiAlias(true);//设置是否抗锯齿
        mPaintCircle.setStyle(Paint.Style.STROKE);//设置绘制风格
 
        mPaintText = new Paint();
        mPaintText.setColor(Color.BLUE);
        mPaintText.setStrokeWidth(10);
        mPaintText.setTextAlign(Paint.Align.CENTER);
        mPaintText.setTextSize(40);
 
        mPaintHour = new Paint();
        mPaintHour.setStrokeWidth(20);
        mPaintHour.setColor(Color.BLUE);
 
        mPaintMinute = new Paint();
        mPaintMinute.setStrokeWidth(15);
        mPaintMinute.setColor(Color.BLUE);
 
        mPaintSec = new Paint();
        mPaintSec.setStrokeWidth(10);
        mPaintSec.setColor(Color.BLUE);
 
        handler.sendEmptyMessage(NEED_INVALIDATE);//向handler发送一个消息,让它开启重绘
    }
 
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
 
        int circleRadius = 400;
        //画出大圆
        canvas.drawCircle(width / 2, height / 2, circleRadius, mPaintCircle);
        //画出圆中心
        canvas.drawCircle(width / 2, height / 2, 20, mPaintCircle);
        //依次旋转画布,画出每个刻度和对应数字
        for (int i = 1; i <= 12; i++) {
            canvas.save();//保存当前画布
            canvas.rotate(360/12*i,width/2,height/2);
            //左起:起始位置x坐标,起始位置y坐标,终止位置x坐标,终止位置y坐标,画笔(一个Paint对象)
            canvas.drawLine(width / 2, height / 2 - circleRadius, width / 2, height / 2 - circleRadius + 30, mPaintCircle);
            //左起:文本内容,起始位置x坐标,起始位置y坐标,画笔
            canvas.drawText(+i, width / 2, height / 2 - circleRadius + 70, mPaintText);
            canvas.restore();//
        }
 
        int minute = mCalendar.get(Calendar.MINUTE);//得到当前分钟数
        int hour = mCalendar.get(Calendar.HOUR);//得到当前小时数
        int sec = mCalendar.get(Calendar.SECOND);//得到当前秒数
 
        float minuteDegree = minute/60f*360;//得到分针旋转的角度
        canvas.save();
        canvas.rotate(minuteDegree, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 - 250, width / 2, height / 2 + 40, mPaintMinute);
        canvas.restore();
 
        float hourDegree = (hour*60+minute)/12f/60*360;//得到时钟旋转的角度
        canvas.save();
        canvas.rotate(hourDegree, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 - 200, width / 2, height / 2 + 30, mPaintHour);
        canvas.restore();
 
        float secDegree = sec/60f*360;//得到秒针旋转的角度
        canvas.save();
        canvas.rotate(secDegree,width/2,height/2);
        canvas.drawLine(width/2,height/2-300,width/2,height/2+40,mPaintSec);
        canvas.restore();
 
    }

Android之自定义View以及画一个时钟的更多相关文章

  1. Android之自定义View学习(一)

    Android之自定义View学习(一) Canvas常用方法: 图片来源 /** * Created by SiberiaDante on 2017/6/3. */ public class Bas ...

  2. Android读取自定义View属性

    Android读取自定义View属性 attrs.xml : <?xml version="1.0" encoding="utf-8"?> < ...

  3. 深夜,用canvas画一个时钟

    深夜,用canvas画一个时钟 查看demo 这几天准备阿里巴巴的笔试,可以说已经是心力交瘁,自从阿里和蘑菇街的内推被刷掉之后,开始越来越怀疑起自己的能力来,虽然这点打击应该是微不足道的.毕竟校招在刚 ...

  4. Android的自定义View及View的绘制流程

    目标:实现Android中的自定义View,为理清楚Android中的View绘制流程“铺路”. 想法很简单:从一个简单例子着手开始编写自定义View,对ViewGroup.View类中与绘制View ...

  5. android开发:Android 中自定义View的应用

    大家好我们今天的教程是在Android 教程中自定义View 的学习,对于初学着来说,他们习惯了Android 传统的页面布局方式,如下代码: <?xml version="1.0&q ...

  6. 自定义View实战--实现一个清新美观的加载按钮

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在 Dribble 上偶然看到了一组交互如下: 当时在心里问自己能不能做,答案肯定是能做的,不过我比较懒,觉得中间那个伸缩变化要编写 ...

  7. Android之自定义View的实现

    对于学习Android开发的小童鞋对于自定义View一定不会陌生,相信大家对它是又爱又恨,爱它可以跟随我们的心意设计出漂亮的效果:恨它想要完全流畅掌握,需要一定的功夫.对于初学者来说确实很不容易,网上 ...

  8. 自定义View(三)--实现一个简单地流式布局

    Android中的流式布局也就是常说的瀑布流很是常见,不仅在很多项目中都能见到,而且面试中也有很多面试官问道,那么什么是流式布局呢?简单来说就是如果当前行的剩余宽度不足以摆放下一个控件的时候,则自动将 ...

  9. Android解决自定义View获取不到焦点的情况

    引言: 我们在使用Android View或者SurfaceView进行图形绘制,可以绘制各种各样我们喜欢的图形,然后满怀信心的给我们的View加上onTouchEvent.onKeyDown.onK ...

随机推荐

  1. 送给张思漫,李志媛和王颖的C语言经典例题

    1.打印乘法口诀表 #include<stdio.h> int main() { int i, j; ; i <= ; i++){ ; j <= i; j++) { print ...

  2. iOS开发ApplePay的介绍与实现

    1.Apple Pay的介绍 Apple Pay官方 1.1 Apple Pay概念 Apple Pay,简单来说, 就是一种移动支付方式.通过Touch ID/ Passcode,用户可使用存储在i ...

  3. 3-----Docker实例-安装MySQL

    Docker 安装 MySQL 方法一.docker pull mysql 查找Docker Hub上的mysql镜像 runoob@runoob:/mysql$ docker search mysq ...

  4. linux的yum报错

    yum makecache Loaded plugins: fastestmirror Could not retrieve mirrorlist http://mirrorlist.centos.o ...

  5. fastjson反序列化多层嵌套泛型类与java中的Type类型

    在使用springmvc时,我们通常会定义类似这样的通用类与前端进行交互,以便于前端可以做一些统一的处理: public class Result<T> { private int ret ...

  6. WPF的RadioButton--单选框

    1. 使用, 显示的内容改为Content属性 <RadioButton Content="boy"/> 2. 要使用分组,就是用 GroupName属性 <Ra ...

  7. hdu 3794 Magic Coupon

    浙大计算机研究生保研复试上机考试-2011年  贪心: 注意:输入输出用scanf  printf 可以加快速度,用cin WA #include<iostream> #include&l ...

  8. 【c++】iostreeam中的类为何不可以直接定义一个无参对象呢

    缘起 #include <iostream> #include <fstream> #include <sstream> using namespace std; ...

  9. 【转】WCF 服务第一次调用慢的问题

    写了一个WCF Serivces供外部程序通过.NET Businesss Connector调用AX的代码,第一次调用的时候总是很慢,有时候甚至超过1分钟,访问地址改成http://localhos ...

  10. 一个Java小菜鸟的实习之路

    博主今年大四,六月份毕业,之前一直对编程感兴趣,于是在大学里自学了Java,(本专业是通信工程).在今年过年的时候,父母让来南方过年,于是博主自己也想着能不能在南方找份java的实习先干着,了解一下行 ...