android 自定义 View(1)

参考:

android 自定义 View - 参考


自定义视图(View)是 Android 开发的一个进阶内容。随着开发的深入,肯定会出现系统提供的基础控件不符合需求的情况。一方面通过组合基础控件以形成新的布局,另一方面可以通过自定义控件的方式来更加灵活的实现需求

自定义视图涉及到 Android 系统许多方面的内容,下面根据自己的理解顺序来讲一讲如何自定义视图


主要内容

  1. 视图层次结构浅析
  2. 视图基本方法
  3. 绘图(drawing)浅析
  4. 事件处理(event handling)浅析
  5. 位置和大小

视图层次结构浅析

ViewViewGroup 是所有组件的基类

View 的作用是在屏幕上绘制可供用户交互的内容

ViewGroup 的作用是储存其它 View 或者 ViewGroup,作为定义界面的布局。

通俗的说,View 是所有组件的基类,ViewGroup 是布局组件(LinearLayout / RelativeLayout 等)的基类

视图层次结构图如下:

Note:自定义视图,必须继承 View 或者 View 的子类;如果想要自定义布局,必须继承 ViewGroup 或者其子类

下面先叙述如何继承 View 实现功能,再实现继承 View 子类(比如 TextView / Button 等)实现功能,最后是如果实现自定义布局


视图基本方法

自定义视图主要分两个部分,绘图(Drawing) 和 事件处理(event handling

Android 通过一套流程来绘制视图,View 类也提供了标准方法(standard methods

这里写图片描述

Note:以上为最常用的标准方法,实际开发过程中不需要重载全部方法,仅需根据自身需求选择合适的方法即可


绘图(drawing)浅析

针对绘图部分,基本的实现流程如下:

构造函数 -> 自定义属性 -> 尺寸测量 -> 绘图

其中还会遇到属性改变和尺寸改变的情况


事件处理(event handling)浅析

未完待续…


位置和大小

视图在屏幕上占据一块矩形(rectangle)区域(对于那些屏幕上的圆型图案,只是将四周透明化了),为了描述视图在屏幕上的位置(position)和大小(dimension),系统提供了一些函数方便计算

Note:屏幕坐标系和数学坐标系不一样,它的 X 轴正方向为水平向左,Y 轴正方向为垂直向下。参考:安卓自定义View基础-坐标系

位置

定位一个视图在屏幕坐标系上的位置,最重要的是左侧坐标(left coordinate,即 Y 轴坐标)和顶部坐标(top coordinate,即 X 轴坐标),通过方法 getLeft()getTop() 获得

/**
 * Left position of this view relative to its parent.
 *
 * @return The left edge of this view, in pixels.
 */
@ViewDebug.CapturedViewProperty
public final int getLeft() {
    return mLeft;
}

/**
 * Top position of this view relative to its parent.
 *
 * @return The top of this view, in pixels.
 */
@ViewDebug.CapturedViewProperty
public final int getTop() {
    return mTop;
}

Note:以上两个方法得到是视图相对于父视图的位置。视图层次结构是一个树状图,每一层视图得到自身大小后,再赋予下一层子视图位置

同样的,还可以得到视图右侧的坐标(getRight())和底部的坐标(getBottom()),它们之间的关系如下:

getRight() = getLeft() + getWidth()
getBottom() = getTop() + getHeight()

方法 getWidthgetHeight 需要在绘制阶段调用;同理,getRightgetBottom 在绘制阶段调用

大小

视图提供了两组方法来获取宽和高:

  • getMeasuredWidth()getMeasuredHeight()
  • getWidth()getHeight()

第一组方法能得到 测量宽度(Measured Width测量高度(Measured Height,其值表示子视图想要在父视图中占据多大的尺寸(define how big a view wants to be within its parent):

/**
 * Like {@link #getMeasuredWidthAndState()}, but only returns the
 * raw width component (that is the result is masked by
 * {@link #MEASURED_SIZE_MASK}).
 *
 * @return The raw measured width of this view.
 */
public final int getMeasuredWidth() {
    return mMeasuredWidth & MEASURED_SIZE_MASK;
}

/**
 * Like {@link #getMeasuredHeightAndState()}, but only returns the
 * raw width component (that is the result is masked by
 * {@link #MEASURED_SIZE_MASK}).
 *
 * @return The raw measured height of this view.
 */
public final int getMeasuredHeight() {
    return mMeasuredHeight & MEASURED_SIZE_MASK;
}

第二组方法得到的就是实际的宽度(width,也称为 drawing width)和实际的高度(height,也称为 drawing height),其值表示的是视图在屏幕上的实际大小:

/**
 * Return the width of the your view.
 *
 * @return The width of your view, in pixels.
 */
@ViewDebug.ExportedProperty(category = "layout")
public final int getWidth() {
    return mRight - mLeft;
}

/**
 * Return the height of your view.
 *
 * @return The height of your view, in pixels.
 */
@ViewDebug.ExportedProperty(category = "layout")
public final int getHeight() {
    return mBottom - mTop;
}

Note 1:二组方法得到的宽和高并不一定不一致

Note 2:位置和尺寸方法得到的值以 像素 为单位(The unit for location and dimensions is the pixel

Note 3:在 onMeasure 方法后调用测量宽度(measured width)和测量高度(measured height

Note 4:在布局完成后,绘制过程中调用实际宽度和实际高度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值