自定义View总结(一)

来源:互联网 发布:腾讯红包大数据,归属地 编辑:程序博客网 时间:2024/06/06 20:28

参考资料

  • Android之View的诞生之谜
  • Android自定义View的实现方法,带你一步步深入了解View(四)
  • 安卓自定义View教程目录
  • Android自定义控件三部曲文章索引

简介

网上的自定义的控件的博客超多,根据我上面我收集的一些参考资料,相信总有你需要的。这边博客只会简单介绍一下自定义相关知识,更多的是个人在自定义View时的一些总结。

自定义View在android 中是重难点,需要你重点关注,别以为只是学会了一些简单的,就以为你会了自定义控件。基础知识知识很快就学会,重写一个onDraw就是一个自定义控件,哈哈,是不是很简单。有卵用?自定义View涉及的知识点繁多,冰冻三尺非一日之寒。我们要做的就是Step By Step。

android 视图层

参考资料一中,就是一个activity加载视图源码分析,点进去看看吧,写的真的很好。如果你使用Android Studio,建议你将AppCompatActivity换成Activity,AppCompatActivity中有太多兼容代码,无法直接看到根本的源码,你要绕老远的路,况且博主也是根据Activity的源码分析。

Start!

PhoneWindow是所有顶层窗口,下一级就是DecorView,DecorView包括两个容器:ActionBar、mContentParent,mcontentParent就是在setContentView加载布局时需要的父容器。看图:

android视图层

ActivityTHread管理Activity,调用oncreate,onResume等方法,调用onResume时,才开始measure、layout、draw。详细点还是看参考一吧,我只是总结而已。

自定义View

四种方式

  • 继承View
  • 继承ViewGroup
  • 继承现有的View
  • 组合控件

自定义View就是四种方式,你想自绘一个View,就是继承自View重写onDraw()方法。你想做个布局容器所有情况就是上面下三个了。

步骤

关于步骤,我想你看过的每一篇博客都是这样的:

onMeasure -> onLayout -> onDraw

对吧。

整个流程应该是这样的:

onCreate(加载布局,实例化View)->View的构造函数->onFinishInflate->onMeasure->onSizeChanged->onLayout->onDraw

View构造函数中,主要是做一些初始化、获取自定义属性的值(也可以通过generateLayoutParams获取,布局容器每次加载View时都会调用generateLayoutParams)的过程,onFinishInflate加载完xml文件时调用,onSizeChanged屏幕宽高发生变化时调用(可用于获取容器宽高,不过一般在onMeasure就可以获取到,看需求吧),剩下的就是自定义控件三部曲,onDraw一般是自绘View时使用,onMeasure、onLayout是自定义布局容器时调用。

下面自定义流程图:

自定义View

从上图就可以看出:
- 自定义View需要走onMeasure和onDraw两个方法,onMeasure看情况而定。
- 自定义布局容器就需要measure、layout,draw看情况,但是会调用dispatchDraw,然后调用drawChild()方法后,最后调用子View的onDraw。其中测量的过程就是父容器调用孩子的measure方法给孩子测量大小,measure调用onMeasure,onMeasure最后调用setMeasuredDimension,测量结束。layout、draw同理。

测量中MeasureSpec,这个类就是测量用,就是30位二进制数表示成类形式,有宽高两个成员变量,30位前两位表示宽高的模式,后28位就是具体的宽高的值,30位是从左向右的。

三种模式:

MeasureSpec.AT_MOST  : 代表是wrap_contentMeasureSpec.EXACTLY  :代表是match_parentMeasureSpec.UNSPECIFIED  : 你想多大就多大MeasureSpec.getMode()获取模式

自定义属性,创建xml文件attrs.xml,名字随意:

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="PercenteLinearLayout">        <attr name="layout_width_percent" format="float"/>        <attr name="layout_height_percent" format="float"/>    </declare-styleable></resources>

使用时,需要命名空间:

    xmlns:app = "http://schemas.android.com/apk/res-auto" 

自动跟踪自定义类。

获取自定属性值:

@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {    return new LayoutParams(getContext(),attrs);}public static class LayoutParams extends LinearLayout.LayoutParams{    private float widthPercent;    private float heightPercent;    public LayoutParams(Context c, AttributeSet attrs) {        super(c, attrs);        //获取自定义属性的值        TypedArray array = c.obtainStyledAttributes(attrs, R.styleable.PercenteLinearLayout);        widthPercent = array.getFloat(R.styleable.PercenteLinearLayout_layout_width_percent,widthPercent);        heightPercent = array.getFloat(R.styleable.PercenteLinearLayout_layout_height_percent,heightPercent);        array.recycle();//释放资源,以免造成内存泄漏    }    public float getWidthPercent() {        return widthPercent;    }    public float getHeightPercent() {        return heightPercent;    }}

这里是通过generateLayoutParams获取到自定义属性,获取时,自定义属性的name前面都要declare-styleable的name作为前缀。值获取到后要释放资源。

自定义View总结一就到这里,找你做过的自定义View的源码,温习下,温故而知新。如果没有的话,从网上找一篇练练吧,不要太多啊,也可以从我的参考资料中找,向那些前辈好好学习吧。

原创粉丝点击