概述
一、 为什么要学习自定义View
主要是Android系统内置的View无法实现我们的需求,我们需要针对我们的业务需求定制我们想要的View
自定义View的方式:
自定义View我们大部分时候只需重写两个函数:onMeasure()、onDraw()。onMeasure负责对当前View的尺寸进行测量,onDraw负责把当前这个View绘制出来。
自定义View的绘制流程
集成View:View流程
onMeasure() (在这个方法里指定自己的宽高) -> onDraw() (绘制自己的内容)
集成ViewGroup:ViewGroup流程
onMeasure() (指定自己的宽高, 所有子View的宽高)-> onLayout() (摆放所有子View) -> onDraw() (绘制内容)
二、 常用的方法:
获取父View提供的参考大小
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
设置自定义View的尺寸大小(在OnMeasure的最后调用)
刷新View(invalidate() postInvalidate())
invalidate()与postInvalidate()这两个都是刷新View的API,它们主要的区别是invalidate()可以在主线程(UI线程)中调用,而不能在子线程中调用,若在子线程中进行刷新view的操作需要配合handler来使用。而postInvalidate()可以在子线程中直接调用。
三、自定义布局属性(通我们自定属性,让用户用我们定义的属性)
res/values/styles.xml
文件(如果没有请自己新建)里面声明一个我们自定义的属性:
<!--name为声明的"属性集合"名,可以随便取,但是最好是设置为跟我们的View一样的名称-->
<declare-styleable name="MyView">
<!--声明我们的属性,名称为default_size,取值类型为尺寸类型(dp,px等)-->
<attr name="default_size" format="dimension" />
</declare-styleable>
</resources>
②第二步:在布局文件用上我们的自定义的属性啦
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:hc="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="100dp"
hc:default_size="100dp" />
</LinearLayout>
注意:需要在根标签(LinearLayout)里面设定命名空间,命名空间名称可以随便取,比如hc
,命名空间后面取得值是固定的:"http://schemas.android.com/apk/res-auto"。
③第三步:我们的自定义的View里面把我们自定义的属性的值取出来,在构造函数中,还记得有个AttributeSet属性吗?就是靠它帮我们把布局里面的属性取出来。
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
//第二个参数就是我们在styles.xml文件中的<declare-styleable>标签
//即属性集合的标签,在R文件中名称为R.styleable+name
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
//第一个参数为属性集合里面的属性,R文件名称:R.styleable+属性集合名称+下划线+属性名称
//第二个参数为,如果没有设置这个属性,则设置的默认的值
defalutSize = a.getDimensionPixelSize(R.styleable.MyView_default_size, 100);
//最后记得将TypedArray对象回收
a.recycle();
}
四、注意的问题
1. 支持wrap_content
如果不在onMeasure()
中对wrap_content
作特殊处理,那么wrap_content
属性将失效
2. 支持padding & margin
如果不支持,那么padding
和margin
(ViewGroup情况)的属性将失效
对于继承View的控件,padding是在draw()中处理
对于继承ViewGroup的控件,padding和margin会直接影响measure和layout过程
3. 启动或停止线程/ 动画的方式:
1. 启动线程/ 动画:使用view.onAttachedToWindow()
,因为该方法调用的时机是当包含View的Activity启动的时刻
2. 停止线程/ 动画:使用view.onDetachedFromWindow()
,因为该方法调用的时机是当包含View的Activity退出或当前View被remove的时刻
最后
以上就是沉默招牌为你收集整理的自定义View理解的全部内容,希望文章能够帮你解决自定义View理解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复