一、自定义组件造成其他组件的隐藏

我们在开发过程中往往现有的组件无法满足我们的需求,所有我们需要去自定义组件来实现我们的需求,在实现的过程中总会有各种问题,这里我们讨论一下onMeasure的使用,首先我们看一下下面的一个例子

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

android:id="@+id/test1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

/>

android:id="@+id/test2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="测试是否显示"

/>

如果我们这样设置一个布局的话,没有运行的效果就是一片空白,如果我们调整一下位置如下:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

android:id="@+id/test2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="测试是否显示"

/>

android:id="@+id/test1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

/>

就会显示出我的TextView内容,主要原因就是我们在自定义组件的时候,没有重写重写onMeasure这个方法,我们在自定义组件的时候,大多数都是重写OnDraw方法,而忽略OnMeasure,onMeasure比OnDraw先执行,主要是测量组件的高度和宽度,然后OnDraw使用OnMeasure里面的width和height来绘制组件,有人会说我怎么没有遇到这种情况呢,要注意的是我上面设置的宽度和高度都是用在wrap_content,如果你设置了精确的值就不会出现这种情况,这个主要是涉及specMode模式,接下来我们看一下onMeasure的实现过程。

二、onMeasure的实现过程

我们在继承View后,然后覆写OnMeasure方法会显示

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

} 会调用父类的onMeasure,内容如下:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),

getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));

}

onMeasure会调用两次,我们肢解一下,首先会调用

public static int getDefaultSize(int size, int measureSpec) {

int result = size;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

switch (specMode) {

case MeasureSpec.UNSPECIFIED:

result = size;

break;

case MeasureSpec.AT_MOST:

case MeasureSpec.EXACTLY:

result = specSize;

break;

}

return result;

}

这里面涉及specMode,它分为三种情况:

MeasureSpec.UNSPECIFIED:(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;

MeasureSpec.AT_MOST:(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;

MeasureSpec.EXACTLY:(至多),子元素至多达到指定大小的值。

getDefaultSize计算View组件的大小,然后使用setMeasuredDimension来设置组件的宽度和高度,我们覆写的时候,就是重写getDefaultSize这个函数的功能。

widthMeasureSpec和heightMeasureSpec这两个值是android:layout_width="200dp" android:layout_height="80dp"来定义的,它由两部分构成,可通过int specModeHeight = MeasureSpec.getMode(heightMeasureSpec); int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec)来得到各自的值。

如果android:layout_width="wrap_content"或android:layout_width="fill_parent",哪么得到的specMode为MeasureSpec.AT_MOST,如果为精确的值则为MeasureSpec.EXACTLY。另外,specSize要想得到合适的值需要在Androidmanifest.xml中添加

三、实例演示

自定义组件TestMeasure.java

package com.example.test;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Paint.Style;

import android.util.AttributeSet;

import android.view.View;

public class TestMeasure extends View {

private String text = "自定义组件";

private Paint mPaint;

private int mAscent;

public TestMeasure(Context context, AttributeSet attrs) {

super(context, attrs);

mPaint = new Paint();

mPaint.setStyle(Style.FILL);

mPaint.setTextSize(45.0f);

mPaint.setColor(Color.RED);

setPadding(20, 60, 0, 0);

}

@Override

protected void onLayout(boolean changed, int left, int top, int right,

int bottom) {

super.onLayout(changed, left, top, right, bottom);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));

}

private int measureWidth(int measureSpec){

int result = 0;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

switch (specMode) {

case MeasureSpec.EXACTLY:

result = specSize;

break;

case MeasureSpec.UNSPECIFIED:

result = (int) mPaint.measureText(text) + getPaddingLeft() + getPaddingRight();

break;

case MeasureSpec.AT_MOST:

result = (int) mPaint.measureText(text) + getPaddingLeft() + getPaddingRight();

result = Math.min(result, specSize);

break;

}

return result;

}

private int measureHeight(int measureSpec){

int result = 0;

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

mAscent = (int) mPaint.ascent();

switch (specMode) {

case MeasureSpec.EXACTLY:

result = specSize;

break;

case MeasureSpec.UNSPECIFIED:

result = (int) (-mAscent + mPaint.descent()) + getPaddingTop() + getPaddingBottom();

break;

case MeasureSpec.AT_MOST:

result = (int) (-mAscent + mPaint.descent()) + getPaddingTop() + getPaddingBottom();

result = Math.min(result, specSize);

break;

}

return result;

}

@Override

protected void onDraw(Canvas canvas) {

canvas.drawText(text, getPaddingLeft(), getPaddingTop(), mPaint);

super.onDraw(canvas);

}

}

主函数

package com.example.test;

import android.app.Activity;

import android.os.Bundle;

public class Main12 extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main14);

}

} 实现效果如下:

如果我们不覆写onMeasure则不会显示自定义组件下面的TextVeiw了,显示效果如下:

android 使用自定义组件,Android自定义组件开发之onMeasure使用相关推荐

  1. android 监听安装来源_Flutter插件开发之APK自动安装

    点击上方的终端研发部,右上角选择"设为星标" 每日早9点半,技术文章准时送上 公众号后台回复"学习",获取作者独家秘制精品资料 往期文章 记五月的一个Andro ...

  2. android qt 串口通信,Qt串口通信开发之QSerialPort模块详细使用方法与实例

    Qt串口通信开发之QSerialPort模块详细使用方法与实例 发布时间:2020-10-23 12:19:05 来源:脚本之家 阅读:111 作者:沧海一笑-dj Qt串口通信基础及名词说明 串口通 ...

  3. android jni 调用java对象_Android NDK开发之Jni调用Java对象

    本地代码中使用Java对象 通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函 ...

  4. 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件

    博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...

  5. Android自定义导览地图组件(一)

    丨版权说明 : <Android自定义导览地图组件(一)>于当前CSDN博客和乘月网属同一原创,转载请说明出处,谢谢.          鉴于Android关于自定义导览地图的相关资料以及 ...

  6. 【Android 内存优化】自定义组件长图组件 ( 长图滚动区域解码 | 手势识别 GestureDetector | 滑动计算类 Scroller | 代码示例 )

    文章目录 一.GestureDetector 创建与设置 二.GestureDetector 触摸事件传递 三.触摸滑动操作 四.惯性滑动操作 五.长图滑动组件代码示例 六.运行效果 七.源码及资源下 ...

  7. 【Android 内存优化】自定义组件长图组件 ( 获取图像宽高 | 计算解码区域 | 设置图像解码属性 复用 像素格式 | 图像绘制 )

    文章目录 一.获取图像真实宽高 二.计算解码区域 三.设置解码参数 内存复用 像素格式 四.图像绘制 五.执行效果 六.源码及资源下载 官方文档 API : BitmapRegionDecoder 在 ...

  8. 【Android 内存优化】自定义组件长图组件 ( 自定义组件构造方法 )

    文章目录 一.自定义组件构造方法简介 1.View(Context context) 构造函数 2.View(Context context, @Nullable AttributeSet attrs ...

  9. 【Android 应用开发】 自定义 圆形进度条 组件

    转载著名出处 : http://blog.csdn.net/shulianghan/article/details/40351487 代码下载 : -- CSDN 下载地址 : http://down ...

最新文章

  1. 【NLP】情感分析:BERT vs Catboost
  2. 安装的python没有菜单栏_由非root用户安装python包/工具
  3. mybatis中获取当前时间_Mybatis获取当前数据库时间
  4. 计算机网络|传输控制协议TCP概述
  5. AI队列长度检测:使用YOLO进行图像中的对象检测
  6. Oracle Net Services 配置:Xlib: connection to :0.0 refused by server
  7. 采访《以魂为中心的领导力》作者之问答
  8. python连接池框架_python3.0 django mysql连接池说明
  9. [2017.01.04] 经典排序算法思想及其实现
  10. kettle使用数据库来生成序列_kettle 生成 ktr
  11. 一个素数,如果将其反转后仍然是一个素数,我们称这样的素数为反转素数。 例如13是一个素数,反转之后得到的31也是一个素数,那么13和31都是反转素数。
  12. 【敏捷2.2】极限编程XP
  13. NRF52840 BLE OTA
  14. Maven之(七)pom.xml配置文件详解
  15. 施耐德驱动器维修ELAU控制器维修C400C600
  16. linux脚本回车键是什么,回车是什么意思 回车键功能介绍
  17. Win10上轻松安装docker,更改镜像安装目录
  18. ElasticSearch知识概括
  19. 学习笔记 | 二八定律、ABC分析法
  20. 906.nethogs安装使用

热门文章

  1. 7 种提升 SpringBoot 吞吐量神技!
  2. Vue-cli+Element(table多级表头及遍历表头)
  3. 【云图】如何设置微信里的全国实体店地图?
  4. DA FMC子卡学习资料:基于JESD204B的4路1Gsps AD 4路1.25Gsps DA FMC子卡
  5. mysql 复合索引_mysql联合索引(复合索引)详解
  6. 解决pyinstaller打包文件过大的问题(Anaconda)
  7. linux内核解析,8分钟掌握Linux内核分析的核心科技
  8. 【Qt6网络抓包工具项目实战】导航目录
  9. 数据湖 与 Lambda 架构
  10. RedisTemplate与zset redis