多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

B06_XML控件布局与ViewBinding

B06_XML控件布局与ViewBinding Android 基础补强 B06读懂 XML 布局控件尺寸、父容器与 ViewBinding摘要从一张传统文章卡片出发理解尺寸与布局参数、控件更新、资源复用和 ViewBinding学会定位长标题及横屏布局问题。标签Android、XML、ViewBinding、布局、第一行代码这一篇对应《第一行代码》第 3 版第 4 章也是 28 天课程 D17 的基础补强。主项目使用 Compose并不意味着存量 View 代码可以跳过。维护传统页面时首先要看懂 XML 如何生成对象、父容器如何安排子控件以及数据变化后谁来更新显示。文中布局与 Kotlin 片段未在现有工程编译需放入独立练习页面验证。1. 子控件的尺寸是交给父布局解释的layout_width和layout_height描述子控件向父容器提出的尺寸要求match_parent与wrap_content也要结合父容器约束理解。布局参数并不是每种容器都通用LinearLayout 的权重、ConstraintLayout 的约束规则属于不同的父布局协议不能看到0dp就一律理解为“不显示”。例如水平 LinearLayout 中标题宽度设为零并给权重可以让它使用分配的剩余空间若在没有相应规则的容器中机械复制标题可能真的没有可用宽度。定位时先看父布局类型再看尺寸、间距和约束最后看文本自身的行数与截断设置。Android 布局指南padding位于控件内部影响内容与控件边界layout_margin位于控件外部由父布局布局时考虑。gravity常控制容器内部内容对齐layout_gravity则要看父容器如何解释子控件位置。这些属性名字相似但调整错误的一项会出现“怎么改都没反应”。2. 用最小卡片观察布局变化下面保存为res/layout/activity_article_practice.xml。字符串资源需在strings.xml定义bookmark_action可为“收藏”sample_article_title为示例标题。它只是练习布局不包含项目主题、窗口边距等完整配置。LinearLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:orientationhorizontalandroid:gravitycenter_verticalandroid:padding16dpTextViewandroid:idid/article_titleandroid:layout_width0dpandroid:layout_heightwrap_contentandroid:layout_weight1android:layout_marginEnd12dpandroid:maxLines2android:ellipsizeendandroid:textstring/sample_article_titleandroid:textSize18sp/Buttonandroid:idid/bookmark_buttonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:textstring/bookmark_action//LinearLayout标题使用剩余宽度按钮按自身需要占位。文字单位使用sp布局尺寸使用dp用户放大字体后可用行数和高度需求会改变不能只在默认字体下看截图。长标题超过两行时截断属于当前练习的产品选择完整内容可以放在详情页不应假装所有文章天然都很短。资源也是结构的一部分。把文案放进字符串资源才能集中管理翻译与格式颜色、尺寸和样式需要复用时也应抽取。不要把“减少 XML 行数”当作唯一目标过早嵌套很多通用布局同样可能增加理解成本。3. ViewBinding 负责引用不负责业务状态模块启用buildFeatures { viewBinding true }后布局会生成相应 Binding 类。对于上面的文件类名为ActivityArticlePracticeBinding控件 ID 对应可访问字段。Activity 中先 inflate再把同一个 root 交给setContentView之后更新它的字段即可。ViewBinding 官方说明下面放在练习 Activity 的onCreate中需补齐 AppCompat 或 ComponentActivity 基类和布局资源。onBookmarkClicked代表事件入口应该交给状态持有者而不是在此永久维护业务数据。valbindingActivityArticlePracticeBinding.inflate(layoutInflater)setContentView(binding.root)binding.articleTitle.textarticle.title binding.bookmarkButton.isSelectedarticle.isBookmarked binding.bookmarkButton.setOnClickListener{onBookmarkClicked(article.id)}ViewBinding 使控件访问具有生成的类型信息但不会把普通变量变成可观察状态也不会自动保存旋转后的收藏。状态仍要从 ViewModel 或 Repository 读取再由渲染函数同步到控件。若把新布局 inflate 后只更新新 Binding却仍然显示旧 root就会出现“赋值执行了屏幕没变”的对象错位。Activity 与 Fragment 也不能完全复制同一套成员管理方式。Fragment 的 View 可先于 Fragment 销毁需要在onDestroyView清理 BindingB08 将详细解释。不能因为引用有类型就认为它在任何生命周期时刻都有效。4. 三个能定位问题的布局实验第一组把短标题换成六十个字并开启较大系统字体。预期按钮仍能操作标题最多两行如果按钮被挤出应检查标题是否错误地使用全宽。记录横竖屏分别的现象不只截最漂亮的一种尺寸。第二组暂时去掉标题权重但保留零宽度。预期标题区域不能再获得原来的剩余空间从而直观理解零宽度必须配合父容器规则。恢复后把外边距改为内边距观察两控件之间的距离与文字位置是否按预期变化。第三组故意 inflate 两份布局一份显示、一份赋值。预期第二份的内容变化不会出现在第一份屏幕上。用对象标识或调试器确认当前 root随后恢复只持有显示树的实现。这些实验用于理解对象关系不应作为保留在正式页面的代码。5. 原创面试问答与追问问一为什么同样是 0dp在不同布局里效果不同尺寸由父容器规则解释权重或约束可能会再分配空间。追问排错先看什么先看父布局与对应 LayoutParams而非只改数字。问二ViewBinding 能替代状态管理吗不能它提供布局控件引用业务状态与生命周期仍要设计。追问按钮变色会自动持久化吗不会需要把事件写入相应数据来源。问三代码更新文字但页面没变化有哪些可能更新了未显示的 View、后续渲染覆盖、状态未被观察等。追问怎样缩小范围确认当前 root、赋值时机与模型来源再检查渲染顺序。以上为围绕书本知识原创的自测不是面试鸭原题摘录。6. 本专题验收不看答案重建标题与按钮布局说明每一个尺寸属性由谁解释在长标题、大字体与横屏下检查行为能把 ViewBinding 的引用便利和 ViewModel 的状态职责分开说明。完成这些基础后再进入 D17 的传统列表与 Compose 互操作就不会把所有问题都归因于框架不同。
返回列表