安卓基础布局核心知识点整理

一、基础布局类型

  1. LinearLayout

    • 线性排列子 View,支持垂直 / 水平方向

    • 关键属性:android:orientationlayout_weight

      <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">

      复制代码
        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="按钮1"/>
            
        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:text="按钮2"/>
      </LinearLayout>
  2. RelativeLayout

    • 通过相对位置规则放置子 View

    • 关键属性:layout_abovelayout_toRightOflayout_centerInParent

      <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent">

      复制代码
        <TextView
            android:id="@+id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="顶部文本"/>
            
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/text1"
            android:layout_alignParentRight="true"
            android:text="右侧按钮"/>
      </RelativeLayout>
  3. FrameLayout

    • 所有子 View 堆叠在左上角

    • 适合实现图层效果或单元素展示

      <FrameLayout android:layout_width="match_parent" android:layout_height="200dp">

      复制代码
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/image_bg"
            android:scaleType="centerCrop"/>
            
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="图片标题"
            android:textColor="#FFFFFF"/>
      </FrameLayout>
  4. ConstraintLayout

    • 基于约束关系定位子 View,性能优化

    • 关键特性:链 (Chains)、屏障 (Barrier)、引导线 (GuideLine)

      <androidx.constraintlayout.widget.ConstraintLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent">

      复制代码
        <EditText
            android:id="@+id/input"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@id/button"
            app:layout_constraintTop_toTopOf="parent"/>
            
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="@id/input"/>

      </androidx.constraintlayout.widget.ConstraintLayout>

二、布局性能优化

  1. 减少布局层级

    • 使用 ConstraintLayout 替代嵌套 LinearLayout
    • 避免超过 3 层布局嵌套
  2. 布局复用技术

    • <include>标签:复用布局文件

      <include layout="@layout/common_toolbar"/>
    • <merge>标签:减少布局层级

      <merge xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:layout_width="match_parent" .../> <Button android:layout_width="wrap_content" .../> </merge>
  3. 延迟加载

    • ViewStub:需要时再加载布

      <ViewStub android:id="@+id/stub" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout="@layout/progress_view"/>

    java

    复制代码
    ViewStub stub = findViewById(R.id.stub);
    View inflated = stub.inflate(); // 延迟加载

三、尺寸单位

单位 说明 适用场景
px 像素 不推荐使用
dp/dip 密度无关像素 大多数场景
sp 缩放像素 文本大小
pt 点 (1/72 英寸) 很少使用
% 百分比 ConstraintLayout 中使用

四、常见面试问题

  1. LinearLayout 中 layout_weight 的工作原理

    • 剩余空间按权重比例分配
    • 建议将 width/height 设为 0dp 优化性能
  2. RelativeLayout 与 LinearLayout 性能对比

    • RelativeLayout:单次测量,但布局算法复杂
    • LinearLayout:可能需要多次测量 (有 weight 时)
    • ConstraintLayout 性能最优
  3. 如何实现流式布局 (FlowLayout)

    • 自定义 View 继承 ViewGroup
    • 重写 onMeasure 和 onLayout 方法
    • 或使用第三方库:HFlowLayout
  4. 谈谈 ConstraintLayout 的优势

    • 扁平化布局减少层级
    • 支持复杂约束关系
    • 性能优于 RelativeLayout
    • 可视化编辑器友好

五、自定义布局

  1. 继承 ViewGroup 并重写:

    • onMeasure ():测量子 View 尺寸
    • onLayout ():放置子 View 位置

    java

    复制代码
    public class CustomLayout extends ViewGroup {
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // 测量所有子View
            measureChildren(widthMeasureSpec, heightMeasureSpec);
            // 计算自身尺寸
            setMeasuredDimension(width, height);
        }
        
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            // 放置每个子View的位置
            child.layout(left, top, right, bottom);
        }
    }
  2. 自定义属性:

    xml

    复制代码
    <declare-styleable name="CustomLayout">
        <attr name="item_space" format="dimension"/>
    </declare-styleable>

    java

    复制代码
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomLayout);
    int itemSpace = a.getDimensionPixelSize(R.styleable.CustomLayout_item_space, 0);
    a.recycle();

六、最佳实践

  1. 使用 ConstraintLayout 作为主要布局

  2. 使用 VectorDrawable 替代多分辨率图片

  3. 为不同屏幕尺寸创建布局别名

    xml

    复制代码
    <!-- values-sw600dp/dimens.xml -->
    <dimen name="card_padding">24dp</dimen>
    
    <!-- values/dimens.xml -->
    <dimen name="card_padding">16dp</dimen>
  4. 使用 Data Binding 减少 findViewById

    xml

    复制代码
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable name="user" type="com.example.User"/>
        </data>
        <TextView
            android:text="@{user.name}"
            .../>
    </layout>

七、补充面试问题

1. View 的绘制流程是怎样的?
  • 核心流程measure()layout()draw()
    • measure:确定 View 的测量宽高(通过父容器传递的 MeasureSpec 和自身需求计算)
    • layout:确定 View 在父容器中的位置(left/top/right/bottom)
    • draw:绘制 View 的内容(背景、文本、图形等)
2. MeasureSpec 的作用是什么?
  • 定义:32 位 int 值,高 2 位表示模式,低 30 位表示尺寸
  • 三种模式
    • EXACTLY :父容器已确定精确尺寸(如match_parent或固定值)
    • AT_MOST :父容器指定最大尺寸(如wrap_content
    • UNSPECIFIED:父容器不对 View 尺寸做限制(如 ScrollView)
3. 如何优化自定义 View 的性能?
  • 关键优化点
    • 避免在onDraw()中创建对象(如 Paint 应在初始化时创建)
    • 使用setWillNotDraw(false)明确需要绘制
    • 实现onSaveInstanceState()保存状态
    • 使用Canvas.clipRect()减少重绘区域
    • 考虑硬件加速兼容性
4. FrameLayout、LinearLayout、RelativeLayout 的使用场景?
  • FrameLayout:简单堆叠场景(如加载框、图片叠加)
  • LinearLayout:单行 / 单列排列(避免过多 weight 嵌套)
  • RelativeLayout:复杂相对位置关系(已逐渐被 ConstraintLayout 替代)
5. 谈谈 ConstraintLayout 的链 (Chain) 机制
  • 作用:水平 / 垂直方向上的权重分配
  • 类型
    • Spread(默认):均匀分布元素
    • Spread Inside:两端元素贴近边界,中间均分
    • Packed :元素紧凑排列,可通过chainStyle设置权重
6. 什么情况下会导致 View 的过度绘制?如何检测和修复?
  • 过度绘制:同一像素被多次绘制(如多层重叠背景)
  • 检测工具:开发者选项 → 显示过度绘制区域
  • 修复方法
    • 移除不必要的背景
    • 使用<merge>标签减少层级
    • 按需显示隐藏视图(如使用 ViewStub)
    • 优化 Drawable 资源(避免多层 Alpha 叠加)
7. 如何实现一个自适应屏幕方向的布局?
  • 方案
    • 创建layout-landlayout-port目录存放不同方向布局

    • 使用ConstraintLayoutBarrierGuideline动态调整

    • 代码中监听屏幕旋转事件: java

      复制代码
      @Override
      public void onConfigurationChanged(Configuration newConfig) {
          super.onConfigurationChanged(newConfig);
          // 重新布局或加载对应资源
      }
8. 对比match_parentwrap_content在 MeasureSpec 中的区别
属性 父容器为 EXACTLY 父容器为 AT_MOST
match_parent EXACTLY (父尺寸) EXACTLY (父尺寸)
wrap_content AT_MOST (父尺寸) AT_MOST (父尺寸)
9. 自定义 View 如何支持 padding 和 margin?
  • Padding :在onDraw()中处理(如canvas.translate(paddingLeft, paddingTop)
  • Margin:需在父容器(自定义 ViewGroup)中解析 LayoutParams 并应用
10. 如何实现布局的懒加载?
  • 方案
    • 使用ViewStub(仅加载一次)
    • 动态 addView(如 Fragment 的setUserVisibleHint()
    • 配合 Jetpack 的LazyColumn/LazyRow(Compose)

八、代码实战问题

1. 手写一个正方形 ImageView

java

复制代码
public class SquareImageView extends ImageView {
    public SquareImageView(Context context) {
        super(context);
    }
    
    public SquareImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int size = Math.min(width, height);
        setMeasuredDimension(size, size);
    }
}
2. 优化以下布局(减少层级)

xml

复制代码
<!-- 原始布局 -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
        
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

<!-- 优化后(ConstraintLayout) -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"/>
        
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/image"/>
</androidx.constraintlayout.widget.ConstraintLayout>
相关推荐
এ旧栎2 小时前
Gitee
笔记·gitee·学习方法
我是好小孩2 小时前
Android-侧边导航栏的使用
android·gitee
安卓开发者2 小时前
Android Material Components 全面解析:打造现代化 Material Design 应用
android
教程分享大师3 小时前
带root权限_中国移动创维DT541_S905L3融合机器改机顶盒刷机教程 当贝纯净版安卓9.0系统线刷包 刷机包
android
wuk9983 小时前
Android:UI:Drawable:View/ImageView与Drawable
android·ui
whysqwhw4 小时前
Kotlin 中作用域函数 let、with、run、also、apply 的核心使用指南
android
旋风菠萝4 小时前
设计模式---单例
android·java·开发语言
whysqwhw6 小时前
Android Jetpack 中 ViewModel 的全面解析
android
2501_916007479 小时前
iPhone查看App日志和系统崩溃日志的完整实用指南
android·ios·小程序·https·uni-app·iphone·webview