android-自定义View初步探索
2015-10-14 15:32
585 查看
最近开始学习自定义View,之前搞过,但是没有系统搞,从这篇博文开始系统学习自定义View。做出一些效果图展示给大家,同时写一写学些心得分享给大家。
这篇文章就是简单的一个View视图,如果你是大牛,请直接绕走,本篇对你来说太简单了。如果你自认为还不行,水平还不够,接来下请看!
首先展示效果图:
![](https://img-blog.csdn.net/20151014143756363)
效果图非常简单,就是一个view!上面就是一个自定义view的展示!
那么实现的思路是什么呢?
将上面的图分解,中间一个圆形、一个字符串、外面有个弧形。首先分成这样的三种形状。
这么一分解就简单不少了。
首先圆形图形代码如下:
绘制圆形图案的代码片段如上所示。首先定义一个画笔,然后对画笔进行一些设置,最后使用画笔在canvas画布进行绘制。简单吧!!
下面对上面的代码一步步说明:
setStyle(Paint.Style.FILL) 这个是设置画笔是否填充绘制区域,Fill的意思就是填充,所以绘制的圆形是实心圆。那么空心圆如何设置呢?简单setStyle(Paint.Style.STROKE)就是。
setAntiAlias(true);//抗锯齿 一般绘制图形都会设置这个抗锯齿的效果。
setAlpha(200);//设置透明度 这个要根据实际需求进行设置。要说活命的是,这个值是从0-255之间。但是我在测试的时候,感觉没变化。设置0和设置255一样。不知道什么原因。
drawCircle(0, 0, rr / 2, paintCir)这个方法第一个和第二个参数是设置圆心x、y的坐标,第三个参数是设置圆形的半径,第四个参数就是画笔。
说明完成之后呢,就要科普一下手机屏幕的坐标系和角度坐标系是怎么回事儿了?
手机屏幕坐标系
![](https://img-blog.csdn.net/20151014145049584)
矩形区域就是手机屏幕,x、y分别代表了横轴、数轴的正方向。这是在默认情况下,不改变坐标原点的情况下的坐标系。为什么说不改变坐标原点的情况呢?因为坐标原点可以更改。怎么改呢?
canvas.translate(width/2,height/2);
这句代码就实现坐标原点的平移,也就是更改。参数分别是在x、y轴上平移的距离。
角度坐标系
![](https://img-blog.csdn.net/20151014145429314)
这幅图就是手机屏幕的角度坐标系,屏幕的中心不是原点,而是相对位置的原点。这么说吧,我们绘制一个view的时候,这个view有大小,有中心,这个中心可以当做角度坐标的中心原点。
明白这一点之后,对着图,0度方向水平向右,顺时针方向为正方向。逆时针方向为负方向。
这一点需要特别注意。不然后面的绘制弧形图案的时候容易脑袋混乱和抽筋!哈哈。。。
好了基础知识说明完成,下面就说一说如何实现博文开始展示的效果图,首先给出自定义view的代码:
自定义view的代码,其中有三个构造器,一个都不能少,少了会报错!!切记!
然后init()是一个初始化的方法,分别 在三个构造器中调用进行初始化。初始化的过程中,创建了三个画笔,分别对应文章开头分析的三个图案。代码中也写了一些注释,不再说明方法的意思。
然后重写了父类的onMeasure方法,对自定义view的宽高进行了设置。在这里需要说明view的宽高。
在ViewGroup中,给View分配的空间大小并不是确定的,有可能随着具体的变化而变化,而这个变化的条件就是传到specMode中决定的,specMode一共有三种可能:
MeasureSpec.EXACTLY:父视图希望子视图的大小应该是specSize中指定的。例如设置layout_width=match_parent ,100dp,100dip 或者layout_height=match_parent ,100dp,100dip等等这些值的情况下,specMode的值就是MeasureSpec.EXACTLY
MeasureSpec.AT_MOST:子视图的大小最多是specSize中指定的值,也就是说不建议子视图的大小超过specSize中给定的值。例如,设置view的属性layout_width=wrap_content,layout_height=wrap_content 的时候,specMode的值就是MeasureSpec.AT_MOST
MeasureSpec.UNSPECIFIED:我们可以随意指定视图的大小。这种情况下view的大小不定,想多大就多大。自定义view的时候很实用。
有了上面的说明,我们就很容易理解代码中onMeasure方法的设置了。代码的意思是如果在没有指定view的大小的情况下,view大小默认宽高就是250
接下来,最后就是核心onDraw方法的重写,在onDraw方法中在画布canvas上进行绘制图案,并进行保存。
由于最终的效果中有圆形、弧形,为了绘制方便,我把原点平移到了view的中心。
canvas.translate(width/2,height/2);
这句代码就实现了这种效果。
需要说明的是,绘制圆弧的时候需要制定一个矩形区域!指定了矩形区域以后,弧形会贴着矩形区域进行绘制。请看下面的效果图:
![](https://img-blog.csdn.net/20151014151703660)
这个效果图就把矩形区域也绘制了出来,大家可以看到弧形区域贴着矩形区域进行绘制。
同时要问问大家,能不能说出弧形区域的绘制角度???
猜到了吗?
canvas.drawArc(rectF, -90, 240, false, paintArc);
这句代码就对应上面图形的绘制角度,意思是从-90度开始,正方向绘制240度。大家好好想一想刚开始我说明的角度坐标系的问题!!!
有了自定义view之后,就可以使用了,下面给出activity的代码;
是不是超级简单!没错,就是这么简单粗暴!!!!哈哈。。。
布局文件:
引用自定义view的全类名引用到xml布局文件中就可以了。不得不提的是,android sutdio确实不错。自定义view可以在视图中进行观察,比eclipse要强!
最终的效果图,就是上面的那幅图。
下面把布局文件中改一下,如下:
别的地方都不变,最终的效果图如下:
![](https://img-blog.csdn.net/20151014152418762)
是不是还可以!!哈哈。。。
好了,这个文章算是自定义view的初步实现吧,后期会加紧这方面的学习,绘制一个酷炫的效果展示出来。
代码我已经通过android studio提交到github中了,地址如下:
https://github.com/longyinzaitian/MyCustomView
大家可以通过fork或者star进自己的账号下面,通过android studio下载工程到本地,然后观看代码进行学习交流。
如果不想到github,我这里也给出下载地址,请猛戳这里!!
这篇文章就是简单的一个View视图,如果你是大牛,请直接绕走,本篇对你来说太简单了。如果你自认为还不行,水平还不够,接来下请看!
首先展示效果图:
效果图非常简单,就是一个view!上面就是一个自定义view的展示!
那么实现的思路是什么呢?
将上面的图分解,中间一个圆形、一个字符串、外面有个弧形。首先分成这样的三种形状。
这么一分解就简单不少了。
首先圆形图形代码如下:
paintCir = new Paint(); paintCir.setStyle(Paint.Style.FILL);//画笔填充绘制区域 paintCir.setAntiAlias(true);//抗锯齿 paintCir.setAlpha(200);//设置透明度 paintCir.setColor(getResources().getColor(android.R.color.holo_blue_light)); //绘制圆形 canvas.drawCircle(0, 0, rr / 2, paintCir);
绘制圆形图案的代码片段如上所示。首先定义一个画笔,然后对画笔进行一些设置,最后使用画笔在canvas画布进行绘制。简单吧!!
下面对上面的代码一步步说明:
setStyle(Paint.Style.FILL) 这个是设置画笔是否填充绘制区域,Fill的意思就是填充,所以绘制的圆形是实心圆。那么空心圆如何设置呢?简单setStyle(Paint.Style.STROKE)就是。
setAntiAlias(true);//抗锯齿 一般绘制图形都会设置这个抗锯齿的效果。
setAlpha(200);//设置透明度 这个要根据实际需求进行设置。要说活命的是,这个值是从0-255之间。但是我在测试的时候,感觉没变化。设置0和设置255一样。不知道什么原因。
drawCircle(0, 0, rr / 2, paintCir)这个方法第一个和第二个参数是设置圆心x、y的坐标,第三个参数是设置圆形的半径,第四个参数就是画笔。
说明完成之后呢,就要科普一下手机屏幕的坐标系和角度坐标系是怎么回事儿了?
手机屏幕坐标系
矩形区域就是手机屏幕,x、y分别代表了横轴、数轴的正方向。这是在默认情况下,不改变坐标原点的情况下的坐标系。为什么说不改变坐标原点的情况呢?因为坐标原点可以更改。怎么改呢?
canvas.translate(width/2,height/2);
这句代码就实现坐标原点的平移,也就是更改。参数分别是在x、y轴上平移的距离。
角度坐标系
这幅图就是手机屏幕的角度坐标系,屏幕的中心不是原点,而是相对位置的原点。这么说吧,我们绘制一个view的时候,这个view有大小,有中心,这个中心可以当做角度坐标的中心原点。
明白这一点之后,对着图,0度方向水平向右,顺时针方向为正方向。逆时针方向为负方向。
这一点需要特别注意。不然后面的绘制弧形图案的时候容易脑袋混乱和抽筋!哈哈。。。
好了基础知识说明完成,下面就说一说如何实现博文开始展示的效果图,首先给出自定义view的代码:
package com.husy.mycustomview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.text.AndroidCharacter; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.Display; import android.view.View; import android.view.WindowManager; /** * Created by husy on 2015/10/13. * * @link http://blog.csdn.net/u010156024 * @description: */ public class MyCustomView extends View{ private Paint paintTx; private Paint paintCir; private Paint paintArc; public MyCustomView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public MyCustomView(Context context) { super(context); init(); } private void init(){ paintTx = new Paint(); paintTx.setStyle(Paint.Style.STROKE);//设置画笔划线不填充 paintTx.setAntiAlias(true);//抗锯齿 paintTx.setTextSize(32);//这是字体大小 paintTx.setStrokeWidth(3);//设置画笔宽度 paintTx.setTextAlign(Paint.Align.CENTER);//设置字体对齐方式 paintTx.setColor(getResources().getColor(android.R.color.black));//设置画笔颜色 paintCir = new Paint(); paintCir.setStyle(Paint.Style.FILL);//画笔填充绘制区域 paintCir.setAntiAlias(true);//抗锯齿 paintCir.setAlpha(255);//设置透明度 paintCir.setColor(getResources().getColor(android.R.color.holo_blue_light)); paintArc = new Paint(); paintArc.setStyle(Paint.Style.STROKE); paintArc.setAntiAlias(true);//抗锯齿 paintArc.setAlpha(127); paintArc.setStrokeWidth(10);//设置画笔宽度 paintArc.setColor(getResources().getColor(android.R.color.holo_green_light)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int wmode = MeasureSpec.getMode(widthMeasureSpec); int wid = MeasureSpec.getSize(widthMeasureSpec); int hmode = MeasureSpec.getMode(heightMeasureSpec); int hei = MeasureSpec.getSize(heightMeasureSpec); /* * 此处的处理是为了当设置组件为wrap_content的时候,使用默认值大小。 * 防止出现图形混乱。 */ if (wmode==MeasureSpec.UNSPECIFIED){ wid = 250; } if (hmode==MeasureSpec.UNSPECIFIED){ hei = 250; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); canvas.translate(width/2,height/2); if (width==height){ }else{ height =width; } //将坐标系原点移到组件中心 int rr = width/2; String tx = "自定义View"; int len = tx.length(); //绘制圆形 canvas.drawCircle(0, 0, rr / 2, paintCir); //绘制圆弧 float rcwidth = width*0.4f; RectF rectF = new RectF(-rcwidth, //left -(height*0.4f), //top rcwidth, //right height*0.4f); //bottom canvas.drawRect(rectF,paintTx); canvas.drawArc(rectF, -90, 240, false, paintArc); //绘制文本 canvas.drawText(tx, 0, len, - len, len/4, paintTx); canvas.save(); } }
自定义view的代码,其中有三个构造器,一个都不能少,少了会报错!!切记!
然后init()是一个初始化的方法,分别 在三个构造器中调用进行初始化。初始化的过程中,创建了三个画笔,分别对应文章开头分析的三个图案。代码中也写了一些注释,不再说明方法的意思。
然后重写了父类的onMeasure方法,对自定义view的宽高进行了设置。在这里需要说明view的宽高。
在ViewGroup中,给View分配的空间大小并不是确定的,有可能随着具体的变化而变化,而这个变化的条件就是传到specMode中决定的,specMode一共有三种可能:
MeasureSpec.EXACTLY:父视图希望子视图的大小应该是specSize中指定的。例如设置layout_width=match_parent ,100dp,100dip 或者layout_height=match_parent ,100dp,100dip等等这些值的情况下,specMode的值就是MeasureSpec.EXACTLY
MeasureSpec.AT_MOST:子视图的大小最多是specSize中指定的值,也就是说不建议子视图的大小超过specSize中给定的值。例如,设置view的属性layout_width=wrap_content,layout_height=wrap_content 的时候,specMode的值就是MeasureSpec.AT_MOST
MeasureSpec.UNSPECIFIED:我们可以随意指定视图的大小。这种情况下view的大小不定,想多大就多大。自定义view的时候很实用。
有了上面的说明,我们就很容易理解代码中onMeasure方法的设置了。代码的意思是如果在没有指定view的大小的情况下,view大小默认宽高就是250
接下来,最后就是核心onDraw方法的重写,在onDraw方法中在画布canvas上进行绘制图案,并进行保存。
由于最终的效果中有圆形、弧形,为了绘制方便,我把原点平移到了view的中心。
canvas.translate(width/2,height/2);
这句代码就实现了这种效果。
需要说明的是,绘制圆弧的时候需要制定一个矩形区域!指定了矩形区域以后,弧形会贴着矩形区域进行绘制。请看下面的效果图:
这个效果图就把矩形区域也绘制了出来,大家可以看到弧形区域贴着矩形区域进行绘制。
同时要问问大家,能不能说出弧形区域的绘制角度???
猜到了吗?
canvas.drawArc(rectF, -90, 240, false, paintArc);
这句代码就对应上面图形的绘制角度,意思是从-90度开始,正方向绘制240度。大家好好想一想刚开始我说明的角度坐标系的问题!!!
有了自定义view之后,就可以使用了,下面给出activity的代码;
package com.husy.mycustomview; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
是不是超级简单!没错,就是这么简单粗暴!!!!哈哈。。。
布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.husy.mycustomview.MyCustomView android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
引用自定义view的全类名引用到xml布局文件中就可以了。不得不提的是,android sutdio确实不错。自定义view可以在视图中进行观察,比eclipse要强!
最终的效果图,就是上面的那幅图。
下面把布局文件中改一下,如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.husy.mycustomview.MyCustomView android:layout_width="200dp" android:layout_height="200dp" /> </RelativeLayout>
别的地方都不变,最终的效果图如下:
是不是还可以!!哈哈。。。
好了,这个文章算是自定义view的初步实现吧,后期会加紧这方面的学习,绘制一个酷炫的效果展示出来。
代码我已经通过android studio提交到github中了,地址如下:
https://github.com/longyinzaitian/MyCustomView
大家可以通过fork或者star进自己的账号下面,通过android studio下载工程到本地,然后观看代码进行学习交流。
如果不想到github,我这里也给出下载地址,请猛戳这里!!
相关文章推荐
- Android长按事件和点击事件问题处理,OnItemLongClickListener和OnItemClickListener冲突问题
- Android游戏开发学习①弹跳小球实现方法
- Android初学习 - onActivityResult和setResult方法的使用
- Android四大组件之Service解析
- 一个Android开发妹子的找工作心酸史
- android横竖屏切换总结
- android videoview 播放前黑屏的解决方法之一
- 日报2015/10/14(极客学院安卓视频学习)
- Android Service 全面总结
- Android程序完全退出的三种方法
- Android四大组件应用系列——Activity与Service交互实现APK下载
- 《转载》android 属性动画Property Animation学习
- android color.xml --各种颜色的值
- android shape的使用
- 开发中Android的一些总结,帮助自己记忆
- Android 精华笔记
- Android TouchEvent事件传递机制
- Android中Parcelable接口的使用
- Android中Parcelable接口的使用
- android去广告