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

一、基础布局类型

  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>
相关推荐
maki0778 小时前
虚幻版Pico大空间VR入门教程 05 —— 原点坐标和项目优化技巧整理
android·游戏引擎·vr·虚幻·pico·htc vive·大空间
千里马学框架8 小时前
音频焦点学习之AudioFocusRequest.Builder类剖析
android·面试·智能手机·车载系统·音视频·安卓framework开发·audio
fundroid12 小时前
掌握 Compose 性能优化三步法
android·android jetpack
TeleostNaCl12 小时前
如何在 IDEA 中使用 Proguard 自动混淆 Gradle 编译的Java 项目
android·java·经验分享·kotlin·gradle·intellij-idea
旷野说14 小时前
Android Studio Narwhal 3 特性
android·ide·android studio
maki07720 小时前
VR大空间资料 01 —— 常用VR框架对比
android·ue5·游戏引擎·vr·虚幻·pico
xhBruce1 天前
InputReader与InputDispatcher关系 - android-15.0.0_r23
android·ims
领创工作室1 天前
安卓设备分区作用详解-测试机红米K40
android·java·linux
hello_ludy1 天前
Android 中的 mk 和 bp 文件编译说明
android·编译
maki0771 天前
VR大空间资料 03 —— VRGK使用体验和源码分析
android·vr·虚幻·源码分析·oculus·htc vive·vrgk