android 使用自定义组件,Android自定义组件开发之onMeasure使用
一、自定义组件造成其他组件的隐藏
我们在开发过程中往往现有的组件无法满足我们的需求,所有我们需要去自定义组件来实现我们的需求,在实现的过程中总会有各种问题,这里我们讨论一下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使用相关推荐
- android 监听安装来源_Flutter插件开发之APK自动安装
点击上方的终端研发部,右上角选择"设为星标" 每日早9点半,技术文章准时送上 公众号后台回复"学习",获取作者独家秘制精品资料 往期文章 记五月的一个Andro ...
- android qt 串口通信,Qt串口通信开发之QSerialPort模块详细使用方法与实例
Qt串口通信开发之QSerialPort模块详细使用方法与实例 发布时间:2020-10-23 12:19:05 来源:脚本之家 阅读:111 作者:沧海一笑-dj Qt串口通信基础及名词说明 串口通 ...
- android jni 调用java对象_Android NDK开发之Jni调用Java对象
本地代码中使用Java对象 通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函 ...
- 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件
博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...
- Android自定义导览地图组件(一)
丨版权说明 : <Android自定义导览地图组件(一)>于当前CSDN博客和乘月网属同一原创,转载请说明出处,谢谢. 鉴于Android关于自定义导览地图的相关资料以及 ...
- 【Android 内存优化】自定义组件长图组件 ( 长图滚动区域解码 | 手势识别 GestureDetector | 滑动计算类 Scroller | 代码示例 )
文章目录 一.GestureDetector 创建与设置 二.GestureDetector 触摸事件传递 三.触摸滑动操作 四.惯性滑动操作 五.长图滑动组件代码示例 六.运行效果 七.源码及资源下 ...
- 【Android 内存优化】自定义组件长图组件 ( 获取图像宽高 | 计算解码区域 | 设置图像解码属性 复用 像素格式 | 图像绘制 )
文章目录 一.获取图像真实宽高 二.计算解码区域 三.设置解码参数 内存复用 像素格式 四.图像绘制 五.执行效果 六.源码及资源下载 官方文档 API : BitmapRegionDecoder 在 ...
- 【Android 内存优化】自定义组件长图组件 ( 自定义组件构造方法 )
文章目录 一.自定义组件构造方法简介 1.View(Context context) 构造函数 2.View(Context context, @Nullable AttributeSet attrs ...
- 【Android 应用开发】 自定义 圆形进度条 组件
转载著名出处 : http://blog.csdn.net/shulianghan/article/details/40351487 代码下载 : -- CSDN 下载地址 : http://down ...
最新文章
- 【NLP】情感分析:BERT vs Catboost
- 安装的python没有菜单栏_由非root用户安装python包/工具
- mybatis中获取当前时间_Mybatis获取当前数据库时间
- 计算机网络|传输控制协议TCP概述
- AI队列长度检测:使用YOLO进行图像中的对象检测
- Oracle Net Services 配置:Xlib: connection to :0.0 refused by server
- 采访《以魂为中心的领导力》作者之问答
- python连接池框架_python3.0 django mysql连接池说明
- [2017.01.04] 经典排序算法思想及其实现
- kettle使用数据库来生成序列_kettle 生成 ktr
- 一个素数,如果将其反转后仍然是一个素数,我们称这样的素数为反转素数。 例如13是一个素数,反转之后得到的31也是一个素数,那么13和31都是反转素数。
- 【敏捷2.2】极限编程XP
- NRF52840 BLE OTA
- Maven之(七)pom.xml配置文件详解
- 施耐德驱动器维修ELAU控制器维修C400C600
- linux脚本回车键是什么,回车是什么意思 回车键功能介绍
- Win10上轻松安装docker,更改镜像安装目录
- ElasticSearch知识概括
- 学习笔记 | 二八定律、ABC分析法
- 906.nethogs安装使用
热门文章
- 7 种提升 SpringBoot 吞吐量神技!
- Vue-cli+Element(table多级表头及遍历表头)
- 【云图】如何设置微信里的全国实体店地图?
- DA FMC子卡学习资料:基于JESD204B的4路1Gsps AD 4路1.25Gsps DA FMC子卡
- mysql 复合索引_mysql联合索引(复合索引)详解
- 解决pyinstaller打包文件过大的问题(Anaconda)
- linux内核解析,8分钟掌握Linux内核分析的核心科技
- 【Qt6网络抓包工具项目实战】导航目录
- 数据湖 与 Lambda 架构
- RedisTemplate与zset redis