zoukankan      html  css  js  c++  java
  • Android之自定义View以及画一个时钟

    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();
     
        }
  • 相关阅读:
    100行代码实现了多线程,批量写入,文件分块的日志方法
    阿里云客户端开发技巧
    阿里云客户端的实现(支持文件分块,断点续传,进度,速度,倒计时显示)
    类库间无项目引用时,在编译时拷贝DLL
    数据库-锁的实践
    Node.js学习资料
    文档流转,文档操作,文档归档(一)
    滑动验证码研究-后续
    iTextSharp 116秒处理6G的文件
    在职场中混,"讲演稿"的重要性
  • 原文地址:https://www.cnblogs.com/wcLT/p/7943905.html
Copyright © 2011-2022 走看看