专栏首页码客Android 自定义View中的onMeasure onLayout onDraw

Android 自定义View中的onMeasure onLayout onDraw

正文

Android自定义View时常重写三个方法onMeasureonLayout以及onDraw

他们的作用

  • onMeasure 计算当前View的宽高
  • onLayout 处理子View的布局
  • onDraw 绘制当前View 调用的顺序为onMeasure–>onLayout–>onDraw

View中还有三个比较重要的方法

  • requestLayout View重新调用一次layout过程。
  • invalidate View重新调用一次draw过程
  • forceLayout 标识View在下一次重绘,需要重新调用layout过程。

如果我们的自定义View内容变了 但大小位置不变的话。只需要调用invalidate. 如果我们的自定义View内容变了 大小位置也变的话。就需要先调用requestLayout 再调用invalidate

onMeasure细要

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    // 获取宽-测量规则的模式和大小
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);

    // 获取高-测量规则的模式和大小
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int sigleHeight = 50;
    int mWidth = sigleHeight;
    int mHeight = sigleHeight * letters.length;

    if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
        setMeasuredDimension(mWidth, mHeight);
    } else if (widthMode == MeasureSpec.AT_MOST) {
        setMeasuredDimension(mWidth, heightSize);
    } else if (heightMode == MeasureSpec.AT_MOST) {
        setMeasuredDimension(widthSize, mHeight);
    } else {
        setMeasuredDimension(widthSize, heightSize);
    }

}

我们可以重写onMeasure来重新定义View的宽高。 其中setMeasuredDimension()方法,设置了measure过程中View的宽高 getSuggestedMinimumWidth()返回View的最小Width,Height也有对应的方法。

插几句,MeasureSpec类是View类的一个内部静态类,它定义了三个常量UNSPECIFIEDAT_MOSTEXACTLY, 其实我们可以这样理解它,它们分别对应LayoutParamsmatch_parentwrap_contentxxxdp

这里对比两个方法

  • getMeasuredHeight() 获取测量的高度 可能和View真实的高度不一样 如果我们不调用requestLayout重新layout的话 getHeight()获取的一直会是之前的高度
  • getHeight() 获取真实的高度

自定义属性

  1. values文件夹下,打开attrs.xml,其实这个文件名称可以是任意的,写在这里更规范一点
  2. 假设我们用到了两个属性一个宽度,一个颜色值的属性
<declare-styleable name="zjslide">
  <attr name="slide_border_width" format="dimension"></attr>
  <attr name="slide_border_color" format="color"></attr>
</declare-styleable>

使用方式

int slideBorderWidth = Utils.dpToPx(1, getResources());
int slideBorderColor = Color.parseColor("#1E88E5");

public ZJSlideBar(Context context) {
    super(context);
}

public ZJSlideBar(Context context, AttributeSet attrs) {
    super(context, attrs,0);
}

public ZJSlideBar(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    TypedArray t = context.obtainStyledAttributes(attrs,R.styleable.zjslide, 0, 0);
    slideBorderWidth = t.getDimensionPixelSize(R.styleable.slide_border_width, slideBorderWidth);
    slideBorderColor = t.getColor(R.styleable.slide_border_color, slideBorderColor);
    t.recycle();// we should always recycle after used
}

View有了三个构造方法需要我们重写,这里介绍下三个方法会被调用的场景:

  • 第一个方法,一般我们这样使用时会被调用:View view = new View(context)
  • 第二个方法,当我们在xml布局文件中使用View时,会在inflate布局时被调用
<View
layout_width="match_parent"
layout_height="match_parent"/>
  • 第三个方法,跟第二种类似,但是增加style属性设置,这时inflater布局时会调用第三个构造方法。
<View
style="@styles/MyCustomStyle"
layout_width="match_parent"
layout_height="match_parent"/>

像上边的例子一样 为了避免代码冗余 我们把获取属性的代码都写在了第三个方法中了

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android页面的跳转及传值

    使用Bundle传递参数,第一个Activity点击一个按钮,跳转到第二个页面。第二个页面输入一个内容,点击按钮,返回第一个Activity,并将第二个Acti...

    剑行者
  • Android RecycleView高度自适应

    当RecycleView的高度为wrap_content 并且item的高度也是wrap_content时 RecycleView的高度就不会根据内容自动设置

    剑行者
  • js扩展

    剑行者
  • Android-LinearLayout中getChildMeasureSpec解析

    该函数的注释是:执行最难的一步:测量子View大小,测量出指定的MeasureSpec 给一个单独的子View,这个方法要计算出子View正确的HeightMe...

    None_Ling
  • 1225 八数码难题

    1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果 题目描述 Descri...

    attack
  • CEO说其实福特造的是“计算机”,流水线工人靠外骨骼变身钢铁侠

    安妮 编译整理 量子位 出品 | 公众号 QbitAI 还是没有阻止股价下跌。 自五月上任以来,福特CEO Hackett就着手推动汽车制造商加速全球范围内的连...

    量子位
  • Codeforces Round #487 (Div. 2)

    给定一段序列,由$“1”,“0”,“.”$组成,其中$.$代表不确定是$“1”$还是$“0”$,

    attack
  • 1225 八数码难题

    题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们. 问题描述 在3×3的棋盘上,...

    attack
  • BZOJ2337: [HNOI2011]XOR和路径(期望 高斯消元)

    设\(f[i]\)表示从\(i\)到\(n\)边权为1的概率,统计答案的时候乘一下权值

    attack
  • BZOJ2707: [SDOI2012]走迷宫(期望 tarjan 高斯消元)

    显然有\(f[x] = \sum_{y} \frac{f[y]}{deg[x]} + 1\)

    attack

扫码关注云+社区

领取腾讯云代金券