当前位置: 首页 > news >正文

自定义ViewGroup实现要点

更多面试题请看这里:https://interview.raoyunsoft.com/
面试题专栏会持续更新欢迎关注订阅

1. 核心方法重写

必须重写以下方法

@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {return new MarginLayoutParams(p);
}@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {return new MarginLayoutParams(getContext(), attrs);
}
2. onMeasure测量流程

关键操作

  1. 解析父容器测量规格
  2. 测量所有子View
  3. 计算自身最终尺寸
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 获取测量模式和尺寸int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);// 测量所有子ViewmeasureChildren(widthMeasureSpec, heightMeasureSpec);// 遍历子View计算尺寸int tWidth = 0, bWidth = 0;for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);int cWidth = child.getMeasuredWidth();MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();// 根据子View位置分组计算if (i == 0 || i == 1) {tWidth += cWidth + params.leftMargin + params.rightMargin;} else if (i == 2 || i == 3) {bWidth += cWidth + params.leftMargin + params.rightMargin;}}// 确定最终宽度int width = Math.max(tWidth, bWidth);setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth : width,(heightMode == MeasureSpec.EXACTLY) ? sizeHeight : ...);
}
3. onLayout布局流程

关键步骤

  1. 获取子View尺寸
  2. 计算每个子View坐标
  3. 调用子View的layout()
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);int cWidth = child.getMeasuredWidth();int cHeight = child.getMeasuredHeight();MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();// 计算子View的四个边界坐标(示例)int cl = ... // 根据布局逻辑计算leftint ct = ... // 根据布局逻辑计算topint cr = cl + cWidth;int cb = ct + cHeight;child.layout(cl, ct, cr, cb);}
}
4. 实战技巧
  • 测量模式处理
    switch(widthMode) {case MeasureSpec.EXACTLY: // 精确值模式case MeasureSpec.AT_MOST: // 最大值模式case MeasureSpec.UNSPECIFIED: // 未指定模式
    }
    
  • 边距处理
    使用MarginLayoutParams获取子View的leftMargin/topMargin等值
  • 性能优化
    避免在onMeasure/onLayout中创建新对象,复用已有变量
5. 常见问题解决方案

子View重叠问题

  • 检查坐标计算逻辑是否考虑其他子View的位置
  • 确保每次布局时重置定位坐标

测量不准确

  • 检查是否处理了wrap_content模式
  • 验证子View测量是否调用measureChild()measureChildren()

布局效率优化

// 使用预计算减少循环内计算量
int currentX = 0, currentY = 0;
for (View child : children) {child.layout(currentX, currentY, currentX + childWidth, currentY + childHeight);currentX += childWidth + margin;
}
http://www.dtcms.com/a/544930.html

相关文章:

  • docker学习笔记,从入门开始!
  • 从 MVC 5 到 Core MVC:ASP.NET MVC 框架的 “进化之路“
  • 认识人工智能与大模型应用开发
  • 电子学会青少年机器人技术(一级)等级考试试卷-实操题(2025年9月)
  • 亲 怎么给一个网站做备份哪些专业能建网站
  • JWT 全面解析与 Spring Boot 实战教程
  • 【预览PDF】前端预览pdf
  • 【PrintPDF】PrintPDF Cargo.toml 分析
  • R/3 销售与分销
  • 唐山微网站建设价格网站建设信息发布
  • 做的最好的理财网站国内无版权图片网站
  • GXDE OS 支持在 WSL 上使用了(带桌面环境)
  • 【Linux】基础指令(2):理解Linux的指令和核心概念
  • Rust 借用分割技巧:安全解构复杂数据结构
  • 在Vue项目中平滑地引入HTML文件
  • 1688网站特点石家庄模板网站建设
  • 不练不熟,不写就忘 之 compose 之 动画之 animateDpAsState动画练习
  • HTML的布局—— DIV 与 SPAN
  • php网站搬家软件潍坊网络营销公司有哪些
  • Langchain中的消息
  • SQL是怎样执行的
  • 合肥网站建设卫来科技郑州高端建站
  • 景区网站建设策划书wordpress去掉rss订阅
  • HTTP中get请求和post请求的区别和联系
  • Rust 开发环境配置:IDE 选择与深度优化实践
  • PyTorch与TensorFlow GPU分布式训练策略详解
  • IDE热键冲突的解决
  • Docker篇1:docker-compose和docker.io区别
  • 如何将 TRAE IDE 的插件市场源切换至 VS Code 官方市场
  • 公司网站建设的请示有网站怎么做下载直链