在很多时候,原生控件不能满足我们的需求,就需要我们自定义View,下面以ImageView圆角为例讲一下个人自定义View经验。我们在自定义View的过程中,需要搞清楚下面几点:
- 首先想想生活中画圆的过程:
我们需要工具:圆规,一张纸,圆规里面还必须要有笔,工具有了就可以画圆了。
代码开发出来的功能肯定是为了服务生活,那就必须来源于生活。对应起来,就不那么麻烦了。
-
然后就是将图片圆角的思路:
(1)我们要画出一个圆
(2)我们用一张图片去填充这个圆就行了
(3)细节,我们需要控制圆心坐标,计算圆的半径等等问题
-
再然后接下来就是该清楚系统绘制过程,和系统绘制的机制
(1)用什么去画?
(2)怎么画?
(3)我们怎么控制,让他画出我们想要的东西?
(4)在每个生命周期方法中都做了些什么?
带着思路上面的上面的四个问题,我们往下面看,先看完理论的讲解,再去看源代码,分析源代码,分析源代码的log,去慢慢搞懂这些问题就差不多了。
1.自定义View的过程或者说系统绘制的机制一般如下:
(1)有一支画笔(Paint),对这个对象决定最终的效果,比如颜色(颜色就是用于填充我们画出来的形状,也可以用图片去填充),风格等等渲染问题。
(2)有一张画布(Canvas),在画布上按照我们想要的效果绘制视图,就是用canvas这个对象去画画,canvas对象决定了画出来的图形的形状,坐标等等,这些都需要我们调用API去进行
2.系统将视图绘制到屏幕的整个过程中,ImageView的几个关键生命周期方法调用过程:
(1)调用setImageDrawable:setImageResource.....这几个设置图片的方法,在这几个方法中就能拿到ImageView中的bitmap或者resourceId,或者地址反正在这儿能得到你设置的图片
(2)调用构造方法:我们需要自定义属性,都需要在这儿先关联attr.xml文件,并且拿到布局文件中我们设置的属性值,在后面绘制的时候用。需要注意的是在这儿系统还拿不到view的宽高,所以初始化画笔等等的事儿,别在这儿做,有坑
(3)onSizeChanged方法:在这儿,我们就能拿到view的宽高了,所以在这儿初始化画笔等等,时机正好
(4)onDraw方法:这个方法才是真的让视图绘制出来,显示在我们的眼前。但是这儿要注意需不需要调用父类的onDraw方法,有可能你不想有的视图出现,完全是希望自己绘制,那就不要调用了,不然会出现双层视图
3.上源代码,来点实际的
在values目录下创建,自定义属性,attr.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- 如果是用Android studio开发,注意styleable中的name需要跟自定义的View类名相同,否则,在布局文件中无法引用下面的属性 --> <declare-styleable name="CircleImage"> <!-- 是否有外边框 --> <attr name="hasBorder" format="boolean" /> <!-- 有外边框的情况下,外边框的颜色 --> <attr name="borderColor" format="color" /> <!-- 有外边框的情况下,外边框的厚度 --> <attr name="borderWidth" format="dimension" /> </declare-styleable> </resources>
编写xml布局文件文件引用
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:dragon="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0000FF"> <!-- xmlns:dragon="http://schemas.android.com/apk/res-auto" 注意看上面的这句话,是用于引用自定义的属性,不可丢 --> <com.picovr.animatordemo.CircleImage android:id="@+id/iv_animator" android:layout_width="200dp" android:layout_height="200dp" android:layout_centerInParent="true" android:src="@mipmap/timgs" dragon:borderColor="#000000" dragon:borderWidth="3dp" dragon:hasBorder="true" /> </RelativeLayout>
创建类,继承ImageView编写代码