Android提供了丰富的控件,但是有时候还是不能满足自己的需求,这时候就需要自定义视图了,自定义视图分为几种,一种为继承为View的,一种为继承于ViewGroup的。继承于View的需要我们自己去绘制控件,继承于ViewGroup的可以组织已有的控件,下面就先介绍下继承于View的情况。
下面就是自定义了一个简单的圆形图来介绍整个的绘制过程,如下所示
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ljXl2EOqWcN9qfc5zX/DI6xsY1/hUyxqSOehmTOuplTOqolzGpo17GpI56GZM66mVM6qiXMambeAJAJuoFpJpofm0yxiRuIgEg00Sapulpev6/jLGHtqttXjQ7YX8fGmNM3Cbyszw/yzMAEvRrzc/y83oZY+I2kZ8N/KOdg/8N4KE5G/jfPJ+4vxsC4E6oF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpblZv+Uv5AW5Mdw3wwFEvINXfrjefmBga9QK3M/Z6r+Z6/agX+ENjrPem3d664THdNcADN5Z679LtLQIe010DPHCjr3ck6d6o4THdNcADN+J6R5vuHwY8prsGeOBGVu84uv3Dhsd01wAP3GjqHXe61wc8prsGeOCoF5BqBPX+nXSvCXhMdw3wwN213r+Z7q8CHtNdAzxwd6r376dLvUCfvHqvBjymuwZ44G5f732lezXgMd01wANHvYBUt6z3ftMdCnhMdw3wwFEvIBX1AlJRLyAV9QJS3abee+92KOAx3TXAA0e9gFTUC0hFvYBU1AtIRb2AVHzHCJCKegGpqBeQinoBqagXkIqfzgekol5AKn4rHSCVvHqHbgP14tHit7EDUvEvoQBS8a+QAVJRLyAV//o2INXI6h1fw7+/UuBRGnG9Iw/4j64ReJRGX++oAv7D66JePFpjqffuDd/sioBHaYz13q7h21wF8CiNvd7fxjyCywQepb9d7zg2prsGeOCoF5DqZvUCeDioF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6AamoF5CKegGpqBeQinoBqagXkIp6Aan+A3BrsqnlXz9RAAAAAElFTkSuQmCC" alt="" />
绘制一个控件需要绘制两部分内容,一是尺寸,二是内容,这通过两个方法来进行绘制,一个是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 }
这个函数用来计算控件的大小尺寸,尺寸这个地方有一个概念为绘制模式
MeasureSpec.AT_MOST:父元素指定控件最大达到的尺寸,通过设定为wrap_content为此模式
MeasureSpec.EXACTLY:父元素指定控件精确的大小,比如设置为100dip,或者match_parent为此模式
MeasureSpec.UNSPECIFIED:父元素不控制控件的大小,其大小完全由内部控制
这个模式,可以通过int mode = MeasureSpec.getMode(widthMeasureSpec);方法来获取模式。
等计算好大小后,通过setMeasuredDimension(width, height);方法来设置宽高
这个函数用来绘制控件的内容,这个函数传入了一个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