当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) // 设置下划线

Demo

一个自定义时钟视图的写法:

<code        class        =        "language-java"        hljs=        ""        >        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();       


                 


                 }       


         }</code>


需要在布局中加载自定义View,名字必须是全名(包括包名):
activity_timer


<code        class        =        "language-xml"        hljs=        ""        ><!--?xml version=        1.0        encoding=utf-        8        ?-->       


         <linearlayout android:layout_height=        "match_parent"        android:layout_width=        "match_parent"        android:orientation=        "vertical"        xmlns:android=        "http://schemas.android.com/apk/res/android"        >       


                 <com.example.administrator.selfdefinedview.widget.myview android:layout_height=        "match_parent/"        android:layout_width=        "match_parent"        >       


         </com.example.administrator.selfdefinedview.widget.myview></linearlayout></code>


主活动setContentView就行了

<code        class        =        "language-java"        hljs=        ""        >        public        class          TimerActivity         extends        Activity {       


                 


                 @Override       


                 protected        void          onCreate(Bundle savedInstanceState) {       


                 super        .onCreate(savedInstanceState);       


                 setContentView(R.layout.activity_timer);       


                 }       


         }</code>