Android 布局笔记

安卓笔记11.常用布局—网格布局 GridLayout布局使用虚细线将布局划分为行、列和单元格,也支持一个控件在行、列上都有交错排列。 阅读详情

说实在我个人觉得 Android 搞这套玩意比 MiniGUI 麻烦多了。以前没怎么系统的研究、学习,遇到了不少问题。现在记一下。

onMeasure

实现 onMeasure 方法基本需要完成下面三个方面的事情(最终结果是你自己写相应代码得出测量值并调用view的一个方法进行设置,告诉给你的view安排位置大小的父容器你要多大的空间)。

  • 1. 传递进来的参数:widthMeasureSpec 和 heightMeasureSpec 是你对你应该得出来的测量值的限制。

The overidden onMeasure() method is called with width and height measure specifications(widthMeasureSpec and heightMeasureSpec parameters,both are integer codes representing dimensions) which should be treated as requirements for the restrictions on the width and height measurements you should produce.

  • 2. 你在 onMeasure 计算出来设置的 width 和 height 将被用来渲染组件。应当尽量在传递进来的 width 和 height 声明之间。虽然你也可以选择你设置的尺寸超过传递进来的声明。但是这样的话,父容器可以选择,如 clipping, scrolling, 或者抛出异常,或者(也许是用新的声明参数)再次调用 onMeasure 。

Your component's onMeasure() method should calculate a measurement width and height which will be required to render the component.it should try to stay within the specified passed in.although it can choose to exceed them(in this case,the parent can choose what to do,including clipping,scrolling,throwing an excption,or asking the onMeasure to try again,perhaps with different measurement specifications).

  • 3. 一但 width 和 height 计算好了,就应该调用 View.setMeasuredDimension(int width,int height) 方法,否则将导致抛出异常。

Once the width and height are calculated,the setMeasureDimension(int width,int height) method must be called with the calculated measurements.Failure to do this will result in an exceptiion being thrown.

例子分析

在 Android 提提供的一个自定义 View 示例中(在 API Demos 中的 view/LabelView)可以看到一个重写 onMeasure 方法的实例,也比较好理解:
/**
* @see android.view.View#measure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec),
        measureHeight(heightMeasureSpec));
}

/**
* Determines the width of this view
* @param measureSpec A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        
        if (specMode == MeasureSpec.EXACTLY) {
                // We were told how big to be
                result = specSize;
        } else {
                // Measure the text
                result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
                + getPaddingRight();
                if (specMode == MeasureSpec.AT_MOST) {
                        // Respect AT_MOST value if that was what is called for by measureSpec
                        result = Math.min(result, specSize);
                }
        }
        
        return result;
}

/**
* Determines the height of this view
* @param measureSpec A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        
        mAscent = (int) mTextPaint.ascent();
        if (specMode == MeasureSpec.EXACTLY) {
                // We were told how big to be
                result = specSize;
        } else {
                // Measure the text (beware: ascent is a negative number)
                result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
                + getPaddingBottom();
                if (specMode == MeasureSpec.AT_MOST) {
                        // Respect AT_MOST value if that was what is called for by measureSpec
                        result = Math.min(result, specSize);
                }
        }
        return result;
}

直接看 measureWidth 首先看到的是参数,分别代表宽度和高度的 MeasureSpec? 。 Android2.2 文档中对于 MeasureSpec? 中的说明是:

  1. 一个 MeasureSpec? 封装了从父容器传递给子容器的布局需求。
  2. 每一个MeasureSpec代表了一个宽度,或者高度的说明。
  3. 一个MeasureSpec是一个大小跟模式的组合值。一共有三种模式:

A MeasureSpec? encapsulates the layout requirements passed from parent to child Each MeasureSpec? represents a requirement for either the width or the height.A MeasureSpec? is compsized of a size and a mode.There are three possible modes:

  • 1. UPSPECIFIED:
父容器对于子容器没有任何限制,子容器想要多大就多大。

UNSPECIFIED The parent has not imposed any constraint on the child.It can be whatever size it wants.

  • 2.EXACTLY:
父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间。

EXACTLY The parent has determined and exact size for the child.The child is going to be given those bounds regardless of how big it wants to be.

  • 3.AT_MOST:
子容器可以是声明大小内的任意大小。

AT_MOST The child can be as large as it wants up to the specified size.

MeasureSpec?

MeasureSpec?  是 View 类下的静态公开类。MeasureSpec 中的值作为一个整型是为了减少对象的分配开支。此类用于将 size 和 mode 打包或者解包为一个整型。

MeasureSpecs? are implemented as ints to reduce object allocation.This class is provided to pack and unpack the size,mode tuple into the int.

我比较好奇的是怎么样将两个值打包到一个int中,又如何解包。MeasureSpec 类代码如下(注释已经被我删除了,因为在上面说明了):

public static class MeasureSpec {
        private static final int MODE_SHIFT = 30;
        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
        
        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
        public static final int EXACTLY     = 1 << MODE_SHIFT;
        public static final int AT_MOST     = 2 << MODE_SHIFT;
        
        public static int makeMeasureSpec(int size, int mode) {
                return size + mode;
        }
        
        public static int getMode(int measureSpec) {
                return (measureSpec & MODE_MASK);
        }
        
        public static int getSize(int measureSpec) {
                return (measureSpec & ~MODE_MASK);
        }
}

我无聊的将他们的十进制值打印出来了:

mode_shift=30, 
mode_mask=-1073741824, 
UNSPECIFIED=0, 
EXACTLY=1073741824, 
AT_MOST=-2147483648

然后觉得也应该将他们的二进制值打印出来,如下:

mode_shift=11110, // 30
mode_mask=11000000000000000000000000000000,
UNSPECIFIED=0, 
EXACTLY=1000000000000000000000000000000, 
AT_MOST=10000000000000000000000000000000

MODE_MASK = 0x3 << MODE_SHIFT :也就是说 MODE_MASK 是由11左移30位得到的。因为 Java 用补码表示数值.最后得到的值最高位是1所以就是负数了。对于上面的数值我们应该这样想,不要把0x3看成3而要看成二进制的11,而把 MODE_SHIFF 就看成30。那为什么是二进制的11呢?因为只有三各模式,如果有四种模式就是111了因为111三个位才可以有四种组合对吧。我们这样来看:

UNSPECIFIED=00000000000000000000000000000000, 
EXACTLY=01000000000000000000000000000000, 
AT_MOST=10000000000000000000000000000000

也就是说 0, 1, 2 对应 00, 01, 10。当跟11相与时 00 &11 还是得到 00, 11&01 -> 01, 10&11 -> 10。

onLayout

onLayout 的调用在 onMeasure 之后,主要是决定子 View 如何摆放的。 需要注意的是,如果自定义的 View 只重载了 onLayout 而没重载 onMeasure 的话,就会导致子 View 布局不正确(如果 View 自己都没有在 onMeasure 里设置自己的话,自己的布局都会不对,例如 View 不是继承现有的 View)。要想子 View 布局正确,需要在 onMeasuer 里调用子 View 的 measure 方法设置子 View 的大小,然后在 onLayout 里对子 View 进行布局,才会正确显示。 ... ...

一些系统属性分析

padding 和 margin 的区别

在 android 默认 view 中 padding (android:paddingTop) 是用于 view 外部的边界距离(例如说 layout 中子 view 之间的)。而 margin (android:layout_marginLeft) 是 view 内部的边界距离(例如说 Button 中字体的距边界的距离)。
安卓学习笔记10:常用布局 - 相对布局 安卓学习笔记10:常用布局 - 相对布局 在这里插入图片描述 (二)实现步骤 1、创建安卓应用【RelativeLayoutDemo】 在这里插入图片描述 在这里插入图片描述 2、主布局资源文件activity_main.xml 在这里插入图片描述 分析界面:首先确定【中央】按钮,然后其它按钮可以根据与它的相对位置关系来定位。【左上角】按钮、【右上角】按钮、【左下角】按钮与【右下角】按钮可以根据它与父容器的对齐方式来确定。 <?xml version="1.0" encoding="utf-8"?&g 阅读详情

相关推荐

Android Studio安卓学习笔记(三)Android用户界面的设计布局与组件(一)用户界面布局设计(1)...

当我们创建了一个安卓项目后,我们会发现真正建立一个完善的安卓项目并不是想象的那么容易。其实和设计GUI可视化界面一样,开发安卓也需要考虑很多方面,主要考虑的还是界面布局和需要的组件。 一:Android用户界面布局管理 Android系统按照MVC(模型(model)-视图(view)-控制器(controller))设计模式将应用程序的界面设计与功能控制设计分离,类似于...

weixin_30886233的博客 5970

android-自定义控件

我们所用的所有控件都是直接或间接继承自View,View是android最基本的一种UI组件,它可以在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件。 自定义控件两种方式 1、继承ViewGroup 例如:ViewGroup , LinearLayout, FrameLayout, RelativeLayout等。 2、继承View 例如:View, TextView, ImageV...

金溪的博客 340

安卓课后笔记 线性布局嵌套

线性布局的嵌套

weixin_64711832的博客 214

初识android 自定义控件

为什么要自定义控件呢?Android提供了一套复杂而强大的组件模板,让开发者基于基本的布局类View类和ViewGroup类来创建自定义控件。Android框架已经包含了各种各样的预设的View和VIewGroup子类,既基本控件和布局,开发者可以根据这些控件和布局开发独立的UI控件。部分基本控件包括Button,TextView,EditText, ListVIew, CheckBox,Ra

不积跬步,无以至千里;不积小流,无以成江海。 908

安卓开发Android studio学习笔记06:常用布局 - 相对布局

【代码】安卓开发Android studio学习笔记06:常用布局 - 相对布局。

那人独钓寒江雪 426

5.2 自抗扰控制 (ADRC)

自抗扰控制(Active Disturbance Rejection Control, ADRC)是由韩京清研究员于1998年提出的一种不依赖被控对象精确数学模型的新型控制技术[reference:0]。其核心思想是将系统的模型不确定性、内部参数摄动以及外部负载变化等所有影响统一定义为“总扰动”,通过一个名为扩张状态观测器(ESO)的环节对其进行实时估计并主动补偿,从而实现动态解耦和强鲁棒性。

技术工作者 1175

Android MeasureSpec介绍及使用

MeasureSpc类说明MeasureSpc类封装了父View传递给子View的布局(layout)要求。每个MeasureSpc实例代表宽度或者高度。它有三种模式: UNSPECIFIED(未指定):父元素不对子元素施加任何束缚,子元素可以得到任意想要的大小; EXACTLY(完全):父元素决定子元素的确切大小,子元素将被限定在给定的边界里而忽略它本身的大小; AT_MOST(最多):子元素至最

Dream It Possible 4162

保姆级教程:用+86手机号成功注册Discord的三种亲测方法(附节点选择技巧)

本文提供了三种经过验证的方法,帮助用户使用+86手机号成功注册Discord,包括号码格式调整、网络环境优化和设备组合方案。同时详细解析了'手机号无效'报错的深层原因,并附上节点选择技巧,确保注册流程顺利。

weixin_42683394的博客 1890

自定义View之 onMeasure() view的高度自适应wrap_content view的测量

在很多自定义view之后,控件的高度需要自适应,即使使用wrap_content没有作用还是match_parent的效果,这时就需要重写onMeasure()方法来实现,view类的onMeasure()方法默认是只支持.EXACTLY模式,所以在自定义view先支持wrap_content就得重写onMeasure(),在这里就需要说一下测量的三种模式了: 第一种: EXACTCLY 大

mxiaoyem的博客 1万+

手把手教你用STM32CubeMX配置Bootloader:从分区设置到跳转逻辑详解(含完整代码示例)

本文详细介绍了如何使用STM32CubeMX配置STM32 Bootloader,从基础概念到完整实现。涵盖Flash分区设置、跳转逻辑、固件升级协议设计等关键步骤,并提供完整代码示例。适合嵌入式开发者快速掌握Bootloader开发技巧,提升STM32固件升级能力。

weixin_29169505的博客 283

SAP ABAP实战:如何用CVI_EI_INBOUND_MAIN批量更新BP邮箱(附完整代码)

本文深入解析了SAP ABAP中CVI_EI_INBOUND_MAIN函数在业务伙伴(BP)邮箱地址批量维护场景下的应用。通过详细讲解数据结构构建、关键参数(如任务参数'5')配置及完整代码示例,为开发者提供了一套高效、稳定的批量更新解决方案,并分享了性能优化与错误处理的最佳实践。

weixin_29228781的博客 77

Android ViewGroup测量child过程

ViewGroup测量child的过程 1.UNSPECIFIED 2.EXACTLY 3.AT_MOST

csm_qz的专栏 1547

用人话讲明白线性回归LinearRegression

目录 什么是回归 一元线性回归 损失函数 最小二乘估计 小结 1. 什么是回归 当我们学习一门新课程、接触一个新专业时,总会对该领域的专有名词感到困惑,甚至看完解释仍难以理解其含义。在我们一起学习machine learning的过程中,我会尽量对相关名词用“人话”做一遍解释,以减少学习的“痛苦感”。 譬如今天要学的线性“回归”,这个回归(regression)和我们平时说的“回归祖国”的回...

化简可得 1万+

【安卓小笔记】android的页面布局

一共有五种页面布局: 1.LinearLayout  线性布局 2.RelativeLayout 相对布局 3.FreameLayout 帧布局(框架布局) 4.AbsoluteLayout  绝对布局 5.TableLayout 表格布局 --------LinearLayout线性布局 LinearLayout是线性布局控件,它包含的子控件将以横向或纵向的

Paul的博客 831

OpenMM | PDBFixer 用于蛋白质预处理

PDBFixer 用于蛋白质预处理

DrugOne 3005

PCL点云DBSCAN聚类算法:基于密度的点云聚类

核心点是在给定半径内拥有足够多邻居点的点,边界点是在给定半径内没有足够多邻居点但是位于核心点的邻域内的点,噪声点是既不是核心点也不是边界点的点。本文将介绍PCL中的DBSCAN(基于密度的空间聚类应用噪声)算法,用于点云数据的聚类。上述示例代码首先从PCD文件中读取点云数据,并设置了DBSCAN聚类的参数,包括邻域搜索半径(epsilon)和邻域内最小点数(min_points)。需要注意的是,示例代码中的点云数据格式为pcl::PointXYZ,如果使用其他类型的点云数据,需要相应地修改代码。

LpmShell的博客 1237

Android开发学习笔记之详解五大布局,2024年最新安卓开发自学技巧

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。还有。

2301_79098886的博客 1224

dji psdk开发 关于SDK认证芯片的使用

Payload SDK V3.10.0 于 2025-1-8 发布,增加了 Matrice 4T/4E 机型支持,同时也增加了 DJI SDK 认证芯片(DJI SDK CC)功能支持。关于认证芯片的介绍大疆 SDK 认证芯片(DJI SDK Certified Chip),简称 DJI SDK CC,用于认证基于 DJI Eport/Eport-Lite 接口开发的第三方负载设备,确保设备能够正常工作并与无人机可以进行有效通信,起到负载安全认证和功能授权的作用。

热爱生活,忠于自己 2142

Android开发学习笔记之详解五大布局,2024年最新安卓移动开发实验报告

题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多程序员朋友无法获得正确的资料得到学习提升,故此将并将重要的Android进阶资料包括自定义view、性能优化、MVC与MVP与MVVM三大框架的区别、NDK技术、阿里面试题精编汇总、常见源码分析等学习资料。【Android思维脑图(技能树)】

m0_60707660的博客 673

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

安卓学习笔记---Android布局总结

其实不管是什么布局,要想学好它,必须要知道它里面包含的方法,如果连里面的方法都不知道,不会用,怎么能够写出好的代码来呢? 布局的方法很简单,下面我主要写一下布局的属性方法和实例。 1.线性布局 线性布局由LinearLayout类来代表,它可以将容器里的组件一个一个的排列起来,但需要注意的是,当一行或一列排满后,线性布局不会自动换行,后面的东西将不会显示出来。 xml属性:

人生e旅途 498

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Android studio笔记:安卓基本开发布局(TableLayout)

android:stretchColumns="1"这个拉伸是需要空余空间进行拉伸的,如果没有它是没有效果的。如果我们设置的标签超过了设置行的长度,它不会自动换行,而是将超过的部分不显示出来。android:collapseColumns="0,2"//隐藏。android:layout_column="1"这是第1列显示。而我们想要它占同一行,我们就需要设置(行)android:layout_span="2" 这是跨2列。正常情况下按钮应该是部分,但是在表格布局下,它会占一行。

薛定谔的猫 1354

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

android移动布局,Android笔记:代码编写布局

Android笔记:代码编写布局发布时间:2020-07-15 05:07:48来源:51CTO阅读:1028作者:glblong自己在shareSdk原有布局中添加一个加载过程的布局:/** 新增:分享发送进度 **/private void setLoadingUI(){// 页面父布局pageLayout = new RelativeLayout(getContext());pageLayo...

weixin_42261100的博客 180

Android安卓学习笔记: 2.LinearLayout(线性布局)

2.LinearLayout(线性布局) Android中有六大布局,分别是: LinearLayout(线性布局), RelativeLayout(相对布局), TableLayout(表格布局) FrameLayout(帧布局), AbsoluteLayout(绝对布局), GridLayout(网格布局) weight(权重)属性详解: ①最简单用法: 如图: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/and

暴走的山交君的博客 1174

Android studio笔记:安卓基本开发布局(ConstraintLayout)

设置约束条件,就旁边四个小圆圈。其实除了在这里可以设置,在代码中也可以实现。约束布局,字面意思就是可以在Design中自行设置。就是跟VB一样拖拽拉组件就可以了。第二个是推导约束(你放在哪个位置,它就推测你在哪个位置。约束布局的特点:如果我们不给button设置约束条件,它就默认放在左上角。

薛定谔的猫 1016

Android studio笔记:安卓基本开发布局(RelativeLayout)

RelativeLayout相对布局,这个子容器是相对父容器,默认在左上;因为我们没有设置定位,因此第二个将第一个覆盖了。android:layout_marginLeft="100dp"是绿色容器跟父容器(黄色的)距离。android:layout_alignParentRight="true"相对父容器右对齐。android:layout_toRightOf="@+id/rl1"相对兄弟元素的右边。

薛定谔的猫 547

安卓开发——安卓界面布局笔记

在这个布局中,整个界面被当成一块空白备用区域,所有的子元素都不能被指定放置的位置,它们统统放于这块区域的左上角,并且后面的子元素直接覆盖在前面的子元素之上,将前面的子元素部分和全部遮挡。如果是垂直排列,那么将是一个N行单列的结构,每一行只会有一个元素,而不论这个元素的宽度为多少;4.FrameLayout,单帧布局,所有控件都放置在屏幕左上角(0,0),可以放多个控件,但是会按控件定义的先后顺序依次覆盖,后一个会直接覆盖在前一个之上显示,如果后放的比之前的大,会把之前的全部盖住(类似于一层层的纸张)。

m0_72345017的博客 2478
上一篇: Android View 系统的一些理解
下一篇: Android Create Bitmap Out Of Memory
mingming_killer
博客等级 码龄19年 18粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值