(面试)获取View宽高的几种方式

Android 中获取 View 宽高的几种方式,以及它们的适用场景和注意事项:

1. View.getWidth()View.getHeight()

  • 原理: 直接从 View 对象中获取已经计算好的宽度和高度。

  • 优点: 简单直接。

  • 缺点: onCreate()onStart() 等生命周期方法中,View 可能还没有完成测量,此时获取到的值可能是 0。 通常在 onResume() 之后才能保证获取到正确的值。
    问题本质:

  1. onCreate()setContentView() 仅加载布局,未开始测量。
  2. onStart()/onResume():界面可见,但测量可能仍未完成(尤其是复杂布局或异步数据加载时)。
  • 适用场景: 在 View 已经完成布局之后,需要获取其宽高时使用。例如,在用户交互事件(如点击事件)中,或者在 onWindowFocusChanged(boolean hasFocus) 方法中。

  • 代码示例:

    @Override
    protected void onResume() {super.onResume();int width = myView.getWidth();int height = myView.getHeight();Log.d("ViewSize", "Width: " + width + ", Height: " + height);
    }
    

    2. View.getMeasuredWidth()View.getMeasuredHeight()

  • 原理: 获取 View 的测量宽度和测量高度。 View 在布局过程中会经过测量阶段,getMeasuredWidth()getMeasuredHeight() 返回的就是测量阶段计算出的宽高

  • 优点:getWidth()getHeight() 更早获取到 View 的宽高信息。

  • 缺点: 测量宽高可能与最终显示的宽高不同 例如,如果 View 的 layout_widthlayout_height 设置为 wrap_content,并且父容器对其进行了限制,那么测量宽高可能只是一个预估值。 此外,如果 View 进行了重新测量,getMeasuredWidth()getMeasuredHeight() 的值也会发生变化。

  • 适用场景: 在 View 还没有完全布局完成,但需要提前知道其大致宽高信息时使用。例如,在自定义 View 的 onMeasure() 方法中。

  • 代码示例:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int measuredWidth = getMeasuredWidth();int measuredHeight = getMeasuredHeight();Log.d("ViewSize", "Measured Width: " + measuredWidth + ", Measured Height: " + measuredHeight);
    }
    

    3. ViewTreeObserver.OnGlobalLayoutListener

  • ViewTreeObserver.OnGlobalLayoutListener 是 Android 中用于监听 视图树(ViewTree)全局布局变化 的接口,常用于在 View 完成测量和布局后 获取其宽高、位置等属性。

  • 优点: 可以保证在 View 已经完成布局之后获取到正确的宽高值 即使 View 的宽高在布局过程中发生了变化,也能及时获取到最新的值。

  • 缺点: 需要注册监听器,并且在获取到宽高后需要移除监听器,否则会造成性能问题。

  • 适用场景: 需要在 View 布局完成后立即获取其宽高,并且需要保证获取到的值是准确的。

  • 代码示例:

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myView = findViewById(R.id.my_view);ViewTreeObserver vto = myView.getViewTreeObserver();vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {myView.getViewTreeObserver().removeOnGlobalLayoutListener(this);int width = myView.getWidth();int height = myView.getHeight();Log.d("ViewSize", "Width: " + width + ", Height: " + height);}});
    }
    

    4. View.post(Runnable)

  • 原理: 将一个 Runnable 对象添加到 View 的消息队列中,该 Runnable 对象会在 View 布局完成后执行。

  • 优点: 可以保证在 View 已经完成布局之后获取到正确的宽高值,并且代码简洁。

  • 缺点: 相对于 OnGlobalLayoutListener,可能稍微延迟一点执行

  • 适用场景: 需要在 View 布局完成后立即获取其宽高,并且对执行时间要求不高。

  • 代码示例:

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myView = findViewById(R.id.my_view);myView.post(new Runnable() {@Overridepublic void run() {int width = myView.getWidth();int height = myView.getHeight();Log.d("ViewSize", "Width: " + width + ", Height: " + height);}});
    }
    

    5. View.addOnLayoutChangeListener(OnLayoutChangeListener) (API Level 11+)

  • 原理: 监听 View 的布局变化。 当 View 的布局发生改变时,onLayoutChange() 方法会被调用。

  • 优点: 可以监听 View 的布局变化,并在布局变化后获取最新的宽高值。

  • 缺点: 只在 API Level 11 及以上可用。

  • 适用场景: 需要在 View 布局变化后立即获取其宽高,并且需要监听 View 的布局变化。

  • 代码示例:

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myView = findViewById(R.id.my_view);myView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {@Overridepublic void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {int width = myView.getWidth();int height = myView.getHeight();Log.d("ViewSize", "Width: " + width + ", Height: " + height);}});
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82231.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL pgrowlocks 扩展

PostgreSQL pgrowlocks 扩展 pgrowlocks 是 PostgreSQL 的一个系统扩展,用于显示表中行级锁定信息。这个扩展特别适合诊断锁争用问题和性能调优。 一、扩展安装与启用 1. 安装扩展 -- 使用超级用户安装 CREATE EXTENSION pgrowlocks;2. 验证安装 -- 查看扩展是…

JavaSE知识总结 ~个人笔记以及不断思考~持续更新

目录 字符串常量池 如果是创建对象还会吗? Integer也是在字串常量池中复用? 字符串拼接 为什么String是不可变的? String的不可变性是怎么做的? 外部代码不能创建对象? 构造方法不是私有的吗? 怎么…

使用HTTPS进行传输加密

文章目录 说明示例(公网上的公开web)安装SSL证书Certbot 的 Webroot 模式 和 Standalone 模式的区别**Webroot 模式****Standalone 模式** 技术对比表Node.js 场景下的最佳实践推荐方案:**Webroot 模式**Standalone 模式应急使用:…

驱动开发(2)|鲁班猫rk3568简单GPIO波形操控

上篇文章写了如何下载内核源码、编译源码的详细步骤,以及一个简单的官方demo编译,今天分享一下如何根据板子的引脚写自己控制GPIO进行高低电平反转。 想要控制GPIO之前要学会看自己的引脚分布图,我用的是鲁班猫RK3568,引脚分布图如…

ArcGIS Pro 3.4 二次开发 - 布局

环境:ArcGIS Pro SDK 3.4 + .NET 8 文章目录 布局1 布局工程项1.1 引用布局工程项及其关联的布局1.2 在新视图中打开布局工程项1.3 激活已打开的布局视图1.4 引用活动布局视图1.5 将 pagx 导入工程1.6 移除布局工程项1.7 创建并打开一个新的基本布局1.8 使用修改后的CIM创建新…

OpenCV 图像像素的算术操作

一、知识点 1、operator (1)、MatExpr operator (const Mat & a, const Mat & b); a、a和b的行数、列数、通道数得相同。 b、a和b的每个像素的每个通道值分别相加。 (2)、MatExpr operator (const Mat & a, const Scalar & s); a、若a…

音视频中的复用器

🎬 什么是复用器(Muxer)? 复用器(muxer)是负责把音频、视频、字幕等多个媒体流打包(封装)成一个单一的文件格式的组件。 💡 举个形象的例子: 假设你有两样东…

数据库安全性

一、计算机安全性概论 (一)核心概念 数据库安全性:保护数据库免受非法使用导致的数据泄露、更改或破坏,是衡量数据库系统的关键指标之一,与计算机系统安全性相互关联。计算机系统安全性:通过各类安全保护…

【Linux网络编程】网络层IP协议

目录 IP协议的协议头格式 网段划分 特殊的IP地址 IP地址的数量限制 私有IP地址和公网IP地址 路由 IP协议的协议头格式 4位版本号 :指定IP协议的版本,对于IPv4,版本号就是4。 4位首部长度:表名IP协议报头的长度,单…

“候选对话链”(Candidate Dialogue Chain)概念

目录 一、定义与形式 二、生成过程详解 1. 语言模型生成(LLM-Based Generation) 2. 知识图谱支持(KG-Augmented Generation) 3. 策略调控(Policy-Driven Planning) 三、候选对话链的属性 四、候选对…

Unity中的JsonManager

1.具体代码 先贴代码 using LitJson; using System.IO; using UnityEngine;/// <summary> /// 序列化和反序列化Json时 使用的是哪种方案 有两种 JsonUtility 不能直接序列化字典 ligJson可以序列化字典 /// </summary> public enum JsonType {JsonUtilit…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Split Landing Page(拆分展示页)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— SplitLandingPage 组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ 在这篇文章中&#xff0c;我们将实现一个交互式的左右面板…

机器学习-ROC曲线​​ 和 ​​AUC指标

1. 什么是ROC曲线&#xff1f;​​ ROC&#xff08;Receiver Operating Characteristic&#xff0c;受试者工作特征曲线&#xff09;是用来评估​​分类模型性能​​的一种方法&#xff0c;特别是针对​​二分类问题​​&#xff08;比如“患病”或“健康”&#xff09;。 ​…

Docker容器创建Redis主从集群

利用虚拟机中的三个Docker容器创建主从集群&#xff0c;容器信息&#xff1a; 容器名角色IP映射端口r1master192.168.150.1017001r2slave192.168.150.1017002r3slave192.168.150.1017003 启动多个redis实例 新建一个docker-compose文件来构建主从集群&#xff1a; 文件内容&…

手写ArrayList和LinkedList

项目仓库&#xff1a;https://gitee.com/bossDuy/hand-tear-collection-series 基于b站up生生大佬&#xff1a;https://www.bilibili.com/video/BV1Kp5tzGEc5/?spm_id_from333.788.videopod.sections&vd_source4cda4baec795c32b16ddd661bb9ce865 LinkedList package com…

每日c/c++题 备战蓝桥杯(Cantor 表)

Cantor 表的探究与实现 在数学中&#xff0c;有理数的可枚举性是一个令人惊叹的结论。今天&#xff0c;就让我们一起深入探讨这个经典问题&#xff0c;并分享一段精心编写的代码&#xff0c;揭开这一数学奥秘的神秘面纱。 问题背景 在 19 世纪末&#xff0c;伟大的数学家康托…

解决idea与springboot版本问题

遇到以下问题&#xff1a; 1、springboot3.2.0与jdk1.8 提示这个包org.springframework.web.bind.annotation不存在&#xff0c;但是pom已经引入了spring-boot-starter-web 2、Error:Cannot determine path to tools.jar library for 17 (D:/jdk17) 3、Error:(3, 28) java: …

Notepad++找回自动暂存的文件

场景&#xff1a; 当你没有保存就退出Notepad&#xff0c;下次进来Notepad会自动把你上次编辑的内容显示出来&#xff0c;以便你继续编辑。除非你手动关掉当前页面&#xff0c;这样Notepad就会删除掉自动保存的内容。 问题&#xff1a; Notepad会将自动保存的文件地址,打开Note…

yolov12毕设前置知识准备 1

1 什么是目标检测呢&#xff1f; 目标检测&#xff08;Object Detection&#xff09;主要用于识别图像或视频中特定类型物体的位置&#xff0c;并标注其类别。 简单来说&#xff0c;就是让计算机像人类一样 “看懂” 图像内容&#xff0c;不仅能识别出物体&#xff08;如人、…

unix/linux source 命令,其内部结构机制

要理解 source (或 .) 命令的内部结构机制,我们需要戴上“操作系统”和“解释器设计”的眼镜,深入到 Shell 如何管理其状态以及如何执行命令的层面。 虽然我们无法直接看到 Shell 内部的 C 代码(除非我们去阅读 Bash 或 Zsh 的源码),但我们可以基于其行为和操作系统的原理…