前言
Android提供了丰富的控件,但是有时候还是不能满足自己的需求,这时候就需要自定义视图了,自定义视图分为几种,一种为继承为View的,一种为继承于ViewGroup的。继承于View的需要我们自己去绘制控件,继承于ViewGroup的可以组织已有的控件,下面就先介绍下继承于View的情况。
效果图
下面就是自定义了一个简单的圆形图来介绍整个的绘制过程,如下所示
概述
绘制一个控件需要绘制两部分内容,一是尺寸,二是内容,这通过两个方法来进行绘制,一个是onMeasure、一个是onDraw,整体结构如下所示
1 public class CustomView extends View { 2 3 public CustomView(Context context, AttributeSet attrs) { 4 super(context, attrs); 5 } 6 //绘制内容 7 @Override 8 protected void onDraw(Canvas canvas) { 9 super.onDraw(canvas); 10 } 11 //计算尺寸大小 12 @Override 13 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 14 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 15 } 16 17 }
onMeasure
这个函数用来计算控件的大小尺寸,尺寸这个地方有一个概念为绘制模式
MeasureSpec.AT_MOST:父元素指定控件最大达到的尺寸,通过设定为wrap_content为此模式
MeasureSpec.EXACTLY:父元素指定控件精确的大小,比如设置为100dip,或者match_parent为此模式
MeasureSpec.UNSPECIFIED:父元素不控制控件的大小,其大小完全由内部控制
这个模式,可以通过int mode = MeasureSpec.getMode(widthMeasureSpec);方法来获取模式。
等计算好大小后,通过setMeasuredDimension(width, height);方法来设置宽高
onDraw
这个函数用来绘制控件的内容,这个函数传入了一个Canvas对象,这个是当前的Canvas对象,把需要绘制的内容绘制到这个Canvas上即可,可以通过Canvas中的drawCircle、drawLine、drawText等方法来绘制内容,如果需要设定笔线内容,通过paint对象来设定
源码
Java
1 public class CustomView extends View { 2 3 int height=0,width=0; 4 private int cx; //圆心x 5 private int cy; //圆心y 6 private int padding=5; //控件边距 7 8 public CustomView(Context context, AttributeSet attrs) { 9 super(context, attrs); 10 } 11 @Override 12 protected void onDraw(Canvas canvas) { 13 super.onDraw(canvas); 14 //计算圆心位置、半径 15 cx = width/2; 16 cy = height/2; 17 int radius = cx>cy?cy:cx; 18 19 Paint paint = new Paint(); 20 paint.setColor(Color.RED); 21 canvas.drawCircle(cx, cy, radius, paint); 22 canvas.drawColor(Color.GRAY); 23 } 24 //计算尺寸大小 25 @Override 26 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 27 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 28 29 widthMeasureSpec = MeasureSpec.getSize(widthMeasureSpec); 30 heightMeasureSpec = MeasureSpec.getSize(heightMeasureSpec); 31 //计算宽度 32 int mode = MeasureSpec.getMode(widthMeasureSpec); 33 if(mode==MeasureSpec.EXACTLY){ 34 width = widthMeasureSpec + padding; 35 }else{ 36 width = widthMeasureSpec; 37 } 38 39 //计算高度 40 mode = MeasureSpec.getMode(heightMeasureSpec); 41 if(mode==MeasureSpec.EXACTLY){ 42 height = heightMeasureSpec + padding; 43 }else{ 44 height = heightMeasureSpec; 45 } 46 setMeasuredDimension(width, height); 47 } 48 49 }
布局文件
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" 10 11 > 12 13 <com.example.customview.CustomView 14 android:id="@+id/customView1" 15 android:layout_width="50dip" 16 android:layout_height="50dip" 17 android:layout_alignParentLeft="true" 18 android:layout_alignParentTop="true" 19 /> 20 21 </RelativeLayout>
后记
这篇文章主要是说了下绘制的一个整体过程,实现的功能比较简单,但是再复杂的内容其原理是相同的,通过这个过程可以发挥想象力来绘制控件,关于通过组合控件来进行绘制的情况再下篇文章中进行叙述。
原文地址:http://www.cnblogs.com/luoaz/p/3980651.html