安卓自定义View(二)---如何自定义View

吐槽

回学校啦啦啦啦,把当时没写完的博客今天写完下尴尬唉
好好学习天天向上

什么是View和ViewGroup

View是安卓里面的所有控件的基类
所以说,view是界面层的控件的一种抽象,代表一个控件
ViewGroup,表示控件组
eg一个Button是个View,一个LinearLayout不但是个View还是个ViewGroup
//ViewGroup内部可以是子View,同时这个子View也可以是ViewGroup
这里写图片描述
view和viewGroup的关系我觉得应该是个体和集合的关系
总结:
- 所有的控件什么的都是继承于View这个类的
- ViewGroup也是继承于View
- View不包含子View
- ViewGroup包含子View
- Android里面所有的UI组件都是由View,viewGroup组成的
- View表现为屏幕的显示的各种视图

如何自定义View呢

觉得从上面可以看出来,view就是和View和ViewGroup两者有关系,所以有两种方法
从操作的逻辑上来讲的话,有以下的步骤:
1View初始化
2测量View的大小
3确定View的大小
4确定View的布局//包含子View的时候用
5绘制内容
6根据用户操作或者自身的操作改变视图
7提供接口
这里写图片描述

自定义View

在没有现成的View,需要自己实现的时候,就使用自定义View,一般继承自View,SurfaceView或其他的View,不包含子View。

自定义ViewGroup

自定义ViewGroup一般是利用现有的组件根据特定的布局方式来组成新的组件,大多继承自ViewGroup或各种Layout,包含有子View。

view的构造函数

构造函数是View的入口,可以用于初始化一些的内容,和获取自定义属性。
如果我们要自定义的话,肯定要从这里入手
先看下View的构造函数四种的重载方法构造函数的大佬博客链接
自定义View必须重写至少一个构造函数
第一种:Context - View中随处都会用到。

// 如果View是在Java代码里面new的,则调用第一个构造函数
 public CarsonView(Context context) {
        super(context);
    }

第二种:AttributeSet - XML属性(当从XML inflate的时候)

// 如果View是在.xml里声明的,则调用第二个构造函数 
// 自定义属性是从AttributeSet参数传进来的 
public CarsonView(Context context, AttributeSet attrs) {
 super(context, attrs);
  } 

第三种:int defStyleAttr - 应用到View的默认风格(定义在主题中)。

// 不会自动调用 
// 一般是在第二个构造函数里主动调用 
// 如View有style属性时 
public CarsonView(Context context, AttributeSet attrs, int defStyleAttr) { 
super(context, attrs, defStyleAttr); } 

第四种:int defStyleResource - 如果没有使用defStyleAttr,应用到View的默认风格

//API21之后才使用 
// 不会自动调用 
// 一般是在第二个构造函数里主动调用 
// 如View有style属性时 
public CarsonView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
super(context, attrs, defStyleAttr, defStyleRes);
 } 

测量view的大小

原因:View的大小不仅由自身所决定,同时也会受到父控件的影响,为了我们的控件能更好的适应各种情况,一般会自己进行测量。
用的类是MeasureSpec
测量View大小使用的是onMeasure函数,我们可以从onMeasure的两个参数中取出宽高的相关数据:
这里写图片描述

测量规格(MeasureSpec) = 测量模式(mode) + 测量大小(size)

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthsize  MeasureSpec.getSize(widthMeasureSpec);      //取出宽度的确切数值
    int widthmode  MeasureSpec.getMode(widthMeasureSpec);      //取出宽度的测量模式

    int heightsize  MeasureSpec.getSize(heightMeasureSpec);    //取出高度的确切数值
    int heightmode  MeasureSpec.getMode(heightMeasureSpec);    //取出高度的测量模式
}

从上面可以看出 onMeasure 函数中有 widthMeasureSpec 和 heightMeasureSpec 这两个 int 类型的参数, 毫无疑问他们是和宽高相关的, 但它们其实不是宽和高, 而是由宽、高和各自方向上对应的测量模式来合成的一个值

测量规格(MeasureSpec) = 测量模式(mode) + 测量大小(size)
在int类型的32位二进制位中,31-30这两位表示测量模式,29~0这三十位表示宽和高的实际值,实际上如下:
这里写图片描述

测量模式一共有三种, 被定义在 Android 中的 View 类的一个内部类View.MeasureSpec中
这里写图片描述

看这个一脸懵逼,就知道下MeasureSpec 的 getSize是获取数值, getMode是获取模式即可
这里写图片描述

确定View大小(onSizeChanged)

时间:这个函数在视图大小发生改变时调用
原因:这是因为View的大小不仅由View本身控制,而且受父控件的影响,所以我们在确定View大小的时候最好使用系统提供的onSizeChanged回调函数

onSizeChanged如下

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
}

它又四个参数,分别为 宽度,高度,上一次宽度,上一次高度。
这个函数比较简单,我们只需关注 宽度(w), 高度(h) 即可,这两个参数就是View最终的大小

确定子View布局位置(onLayout)

确定布局的函数是onLayout,它用于确定子View的位置,在自定义ViewGroup中会用到,他调用的是子View的layout函数。
在自定义ViewGroup中,onLayout一般是循环取出子View,然后经过计算得出各个子View位置的坐标值,然后用以下函数设置子View位置:

child.layout(l, t, r, b);

四个参数的具体意思
View左侧距父View左侧的距离 getLeft();
View顶部距父View顶部的距离 getTop();
View右侧距父View左侧的距离 getRight();
View底部距父View顶部的距离 getBottom();

绘制内容(onDraw)

onDraw是实际绘制的部分,也就是我们真正关心的部分,使用的是Canvas绘图

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
}

对外提供操作方法和监听回调

自定义完View之后,一般会对外暴露一些接口,用于控制View的状态等,或者监听View的变化.

总结

这个就是自定义view的流程,简单知道一点要干什么,用那些函数,顺序是什么就好了,其余的再接着学习。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值