Android入门教程 - 第三章:Android布局全攻略

🎨 Android入门教程 - 第三章:Android布局全攻略

💡 前言:学习Android开发,布局是绕不开的第一关。本章将带你系统掌握Android六大布局,从最简单的线性排列到复杂的网格设计,让你的App界面专业又美观!


📚 本章学习路线图

布局基础概念 LinearLayout 线性布局 RelativeLayout 相对布局 FrameLayout 帧布局 TableLayout 表格布局 GridLayout 网格布局 综合实战

学完本章你将掌握

  • ✅ 6种Android基本布局的使用方法
  • ✅ 每种布局的特点和最佳应用场景
  • ✅ 布局嵌套技巧实现复杂界面
  • ✅ 界面适配不同屏幕的方法

🎯 一、布局是什么?为什么要学布局?

1.1 布局的本质

布局(Layout) 是Android中的容器控件,就像是一个"组织者",负责管理和安排其他控件(按钮、文本框等)在屏幕上的位置和大小。

1.2 生动的类比

想象你在装修房子:

概念 类比 说明
布局 房间的格局设计 决定家具放在哪里
控件 各种家具 沙发、桌子、椅子等
屏幕 整个房子 所有内容的承载空间

再比如

  • 📚 布局像书架的隔板:决定书籍如何摆放
  • 🎯 布局像停车场的车位:规划每辆车的位置
  • 🎨 布局像画布的构图:安排画面元素的位置

1.3 Android六大布局家族

序号 布局名称 核心特点 典型应用
1️⃣ LinearLayout 线性排列(横向/纵向) 按钮组、列表项
2️⃣ RelativeLayout 相对定位 复杂界面、表单
3️⃣ FrameLayout 层叠显示 轮播图、遮罩层
4️⃣ TableLayout 表格结构 数据表格、日历
5️⃣ GridLayout 网格布局 计算器、相册
6️⃣ AbsoluteLayout 绝对定位(已废弃) ⚠️ 不推荐使用

📐 二、LinearLayout - 最常用的线性布局

2.1 LinearLayout是什么?

LinearLayout(线性布局) 将子控件按照垂直水平方向依次排列,就像排队一样简单明了。

2.2 生活中的LinearLayout

复制代码
垂直排列 (vertical)          水平排列 (horizontal)
    
    📱                      📱 📱 📱 📱
    📱                      ← 水平排列 →
    📱                   
    📱                   
    ↓                    
  垂直排列                
  • 排队买票:人们一个接一个排成一列 → 垂直LinearLayout
  • 并排停车:车辆横向依次排列 → 水平LinearLayout

2.3 核心属性速查表

属性名 作用 可选值 示例代码
orientation 排列方向 vertical(垂直) horizontal(水平) android:orientation="vertical"
layout_weight 权重分配 数字(如1, 2, 3) android:layout_weight="1"
gravity 子控件对齐方式 center, left, right, top, bottom android:gravity="center"
layout_gravity 自身在父容器中的对齐 同上 android:layout_gravity="center"

2.4 实战案例:垂直排列的登录界面

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="24dp"
    android:background="#F5F5F5">

    <!-- 标题 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="欢迎登录"
        android:textSize="28sp"
        android:textColor="#333333"
        android:textStyle="bold"
        android:layout_gravity="center"
        android:layout_marginBottom="32dp"/>

    <!-- 用户名输入框 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入用户名"
        android:padding="12dp"
        android:background="@android:color/white"
        android:layout_marginBottom="16dp"/>

    <!-- 密码输入框 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入密码"
        android:inputType="textPassword"
        android:padding="12dp"
        android:background="@android:color/white"
        android:layout_marginBottom="24dp"/>

    <!-- 登录按钮 -->
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录"
        android:textSize="18sp"
        android:padding="12dp"
        android:background="#4CAF50"
        android:textColor="@android:color/white"/>

</LinearLayout>

效果预览

复制代码
┌─────────────────────────┐
│                         │
│       欢迎登录          │
│                         │
│  ┌──────────────────┐  │
│  │ 请输入用户名      │  │
│  └──────────────────┘  │
│                         │
│  ┌──────────────────┐  │
│  │ 请输入密码 ••••   │  │
│  └──────────────────┘  │
│                         │
│  ┌──────────────────┐  │
│  │      登录         │  │
│  └──────────────────┘  │
│                         │
└─────────────────────────┘

2.5 权重(Weight)详解:最重要的属性!

权重是LinearLayout的灵魂,它决定了控件如何分配剩余空间。

权重计算公式
java 复制代码
实际大小 = 原始大小 + (剩余空间 × 权重比例)
实战案例:三个按钮平分空间
xml 复制代码
<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="1"
        android:text="按钮2"/>

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="按钮3"/>

</LinearLayout>

关键点

  1. layout_width="0dp":让权重生效
  2. layout_weight="1":三个按钮权重相同,平分空间
不同权重的效果对比
xml 复制代码
<!-- 权重比例 1:2:1 -->
<Button android:layout_weight="1" android:text="小"/>
<Button android:layout_weight="2" android:text="大"/>
<Button android:layout_weight="1" android:text="小"/>

视觉效果

复制代码
┌────┬──────────┬────┐
│ 小 │    大    │ 小 │
└────┴──────────┴────┘
 25%      50%     25%

2.6 Java代码动态创建LinearLayout

java 复制代码
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 创建垂直LinearLayout
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.setPadding(20, 20, 20, 20);
        
        // 创建TextView
        TextView textView = new TextView(this);
        textView.setText("动态创建的文本");
        textView.setTextSize(18);
        
        // 创建Button
        Button button = new Button(this);
        button.setText("动态按钮");
        
        // 添加到布局
        layout.addView(textView);
        layout.addView(button);
        
        // 设置为Activity的内容视图
        setContentView(layout);
    }
}

2.7 LinearLayout常见问题

问题 原因 解决方案
控件显示不全 宽高设置不当 使用wrap_contentmatch_parent
权重不生效 宽度不是0dp 设置layout_width="0dp"
控件重叠 方向设置错误 检查orientation属性

🔗 三、RelativeLayout - 灵活的相对布局

3.1 RelativeLayout是什么?

RelativeLayout(相对布局) 通过相对位置关系 来排列控件。每个控件可以相对于父容器其他控件定位。

3.2 生活中的RelativeLayout

像玩拼图

  • "把沙发放在电视对面" → 相对于电视定位
  • "把茶几放在沙发前面" → 相对于沙发定位
  • "把台灯放在房间中央" → 相对于父容器定位

3.3 RelativeLayout核心属性分类

📍 相对于父容器的定位
属性 作用 视觉效果
layout_alignParentTop 顶部对齐 控件贴着屏幕上边缘
layout_alignParentBottom 底部对齐 控件贴着屏幕下边缘
layout_alignParentLeft 左对齐 控件贴着屏幕左边缘
layout_alignParentRight 右对齐 控件贴着屏幕右边缘
layout_centerInParent 居中 控件在屏幕正中央
layout_centerHorizontal 水平居中 控件水平方向居中
layout_centerVertical 垂直居中 控件垂直方向居中
📍 相对于其他控件的定位
属性 作用 使用示例
layout_above 在指定控件上方 android:layout_above="@id/centerView"
layout_below 在指定控件下方 android:layout_below="@id/centerView"
layout_toLeftOf 在指定控件左边 android:layout_toLeftOf="@id/centerView"
layout_toRightOf 在指定控件右边 android:layout_toRightOf="@id/centerView"
📍 对齐其他控件的边缘
属性 作用
layout_alignTop 顶部与指定控件对齐
layout_alignBottom 底部与指定控件对齐
layout_alignLeft 左边与指定控件对齐
layout_alignRight 右边与指定控件对齐

3.4 实战案例:十字星布局

xml 复制代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <!-- 中心控件 -->
    <TextView
        android:id="@+id/centerView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="中心"
        android:gravity="center"
        android:background="#2196F3"
        android:textColor="@android:color/white"
        android:layout_centerInParent="true"/>

    <!-- 上方控件 -->
    <TextView
        android:id="@+id/topView"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:text="上"
        android:gravity="center"
        android:background="#4CAF50"
        android:textColor="@android:color/white"
        android:layout_above="@id/centerView"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"/>

    <!-- 下方控件 -->
    <TextView
        android:id="@+id/bottomView"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:text="下"
        android:gravity="center"
        android:background="#FF5722"
        android:textColor="@android:color/white"
        android:layout_below="@id/centerView"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"/>

    <!-- 左边控件 -->
    <TextView
        android:id="@+id/leftView"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:text="左"
        android:gravity="center"
        android:background="#FFC107"
        android:textColor="@android:color/white"
        android:layout_toLeftOf="@id/centerView"
        android:layout_centerVertical="true"
        android:layout_marginEnd="20dp"/>

    <!-- 右边控件 -->
    <TextView
        android:id="@+id/rightView"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:text="右"
        android:gravity="center"
        android:background="#9C27B0"
        android:textColor="@android:color/white"
        android:layout_toRightOf="@id/centerView"
        android:layout_centerVertical="true"
        android:layout_marginStart="20dp"/>

</RelativeLayout>

效果预览

复制代码
        ┌────┐
        │ 上 │
        └────┘
          ↑
   ┌────┐ ┌────────┐ ┌────┐
   │ 左 │←│  中心  │→│ 右 │
   └────┘ └────────┘ └────┘
          ↓
        ┌────┐
        │ 下 │
        └────┘

3.5 实战案例:微信聊天界面布局

xml 复制代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 顶部标题栏 -->
    <LinearLayout
        android:id="@+id/titleBar"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:background="#1AAD19"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="聊天"
            android:textSize="20sp"
            android:textColor="@android:color/white"/>

    </LinearLayout>

    <!-- 底部输入栏 -->
    <LinearLayout
        android:id="@+id/inputBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:padding="8dp"
        android:background="#F5F5F5">

        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="输入消息"
            android:padding="8dp"
            android:background="@android:color/white"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发送"
            android:layout_marginStart="8dp"/>

    </LinearLayout>

    <!-- 中间消息列表区域 -->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/titleBar"
        android:layout_above="@id/inputBar"
        android:background="@android:color/white">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="16dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="这里显示聊天消息"
                android:textSize="16sp"/>

        </LinearLayout>

    </ScrollView>

</RelativeLayout>

3.6 RelativeLayout vs LinearLayout 对比

对比项 LinearLayout RelativeLayout
布局方式 线性排列 相对定位
嵌套层数 可能需要多层嵌套 通常一层即可
性能 较好 略差(测量过程复杂)
灵活性 较低 非常高
适用场景 简单列表、按钮组 复杂界面、表单
学习难度 ⭐⭐ ⭐⭐⭐

3.7 RelativeLayout使用技巧

✅ 推荐做法

  1. 先定位关键的"锚点"控件(如中心控件)
  2. 其他控件相对于锚点定位
  3. 使用ID引用时确保ID已定义在前面

❌ 常见错误

xml 复制代码
<!-- 错误:centerView还未定义就被引用 -->
<TextView
    android:layout_below="@id/centerView"/>  <!-- centerView在下面才定义 -->

<TextView
    android:id="@+id/centerView"/>

✅ 正确做法

xml 复制代码
<!-- 正确:先定义centerView -->
<TextView
    android:id="@+id/centerView"/>

<TextView
    android:layout_below="@id/centerView"/>

🎬 四、FrameLayout - 堆叠式帧布局

4.1 FrameLayout是什么?

FrameLayout(帧布局) 将所有子控件叠加显示,就像一叠扑克牌,后添加的控件会覆盖在前面的控件上方。

4.2 生活中的FrameLayout

场景 说明
🃏 叠扑克牌 一张张叠在一起,最上面的牌可见
🖼️ 相框 可以在同一位置放多张照片
🎭 舞台布景 背景、中景、前景层层叠加

4.3 FrameLayout核心属性

属性 作用 可选值
layout_gravity 控件在帧布局中的位置 center, top, bottom, left, right
foreground 前景图片/颜色 资源ID或颜色值
foregroundGravity 前景对齐方式 layout_gravity

4.4 实战案例:图片加载遮罩层

xml 复制代码
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 第一层:背景图片 -->
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/background"
        android:scaleType="centerCrop"/>

    <!-- 第二层:半透明遮罩 -->
    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#80000000"/>  <!-- 50%透明的黑色 -->

    <!-- 第三层:加载动画(居中显示) -->
    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"/>

    <!-- 第四层:提示文字 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加载中..."
        android:textColor="@android:color/white"
        android:textSize="16sp"
        android:layout_gravity="center"
        android:layout_marginTop="80dp"/>

</FrameLayout>

分层示意图

复制代码
┌─────────────────────────┐
│                         │  ← 第4层:提示文字
│       加载中...         │
│          ⭕             │  ← 第3层:加载动画
│    (半透明黑色遮罩)      │  ← 第2层:遮罩
│    [背景图片]           │  ← 第1层:背景
└─────────────────────────┘

4.5 实战案例:轮播图指示器

xml 复制代码
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <!-- 轮播图ViewPager -->
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <!-- 底部指示器(在ViewPager上层) -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center_horizontal"
        android:layout_marginBottom="16dp"
        android:orientation="horizontal">

        <View
            android:layout_width="8dp"
            android:layout_height="8dp"
            android:background="@drawable/dot_selected"
            android:layout_margin="4dp"/>

        <View
            android:layout_width="8dp"
            android:layout_height="8dp"
            android:background="@drawable/dot_normal"
            android:layout_margin="4dp"/>

        <View
            android:layout_width="8dp"
            android:layout_height="8dp"
            android:background="@drawable/dot_normal"
            android:layout_margin="4dp"/>

    </LinearLayout>

</FrameLayout>

4.6 FrameLayout的layout_gravity组合用法

xml 复制代码
<!-- 九宫格位置演示 -->
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 左上角 -->
    <Button
        android:layout_gravity="top|left"
        android:text="左上"/>

    <!-- 正上方 -->
    <Button
        android:layout_gravity="top|center_horizontal"
        android:text="上"/>

    <!-- 右上角 -->
    <Button
        android:layout_gravity="top|right"
        android:text="右上"/>

    <!-- 正中间 -->
    <Button
        android:layout_gravity="center"
        android:text="中"/>

    <!-- 左下角 -->
    <Button
        android:layout_gravity="bottom|left"
        android:text="左下"/>

    <!-- 正下方 -->
    <Button
        android:layout_gravity="bottom|center_horizontal"
        android:text="下"/>

    <!-- 右下角 -->
    <Button
        android:layout_gravity="bottom|right"
        android:text="右下"/>

</FrameLayout>

效果示意

复制代码
┌─────────────────────────┐
│ 左上   上      右上      │
│                         │
│ 左     中       右       │
│                         │
│ 左下   下      右下      │
└─────────────────────────┘

4.7 FrameLayout典型应用场景

应用场景 说明 层级结构
🎠 轮播图 ViewPager + 指示器 图片层 → 指示器层
💬 对话框 内容 + 遮罩背景 遮罩层 → 内容层
🔄 加载动画 内容 + 加载提示 内容层 → 加载层
🎮 游戏界面 背景 + 角色 + UI 多层叠加
📹 视频播放 视频 + 控制条 视频层 → 控制层

4.8 Java代码动态添加层

java 复制代码
public class FrameLayoutDemo extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        FrameLayout frameLayout = new FrameLayout(this);
        
        // 添加背景层
        ImageView bgImage = new ImageView(this);
        bgImage.setImageResource(R.drawable.background);
        bgImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
        frameLayout.addView(bgImage);
        
        // 添加遮罩层
        View mask = new View(this);
        mask.setBackgroundColor(0x80000000);  // 半透明黑色
        frameLayout.addView(mask);
        
        // 添加前景内容
        TextView text = new TextView(this);
        text.setText("前景文字");
        text.setTextColor(Color.WHITE);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT,
            Gravity.CENTER
        );
        text.setLayoutParams(params);
        frameLayout.addView(text);
        
        setContentView(frameLayout);
    }
}

📊 五、TableLayout - 表格式布局

5.1 TableLayout是什么?

TableLayout(表格布局)行和列的形式组织控件,就像Excel表格一样规整。

5.2 生活中的TableLayout

场景 特点
📊 Excel表格 行列清晰,数据规整
📅 课程表 时间、科目按表格排列
🎯 成绩单 姓名、科目、分数列表

5.3 TableLayout核心概念

xml 复制代码
<TableLayout>              ← 表格容器
    <TableRow>             ← 一行
        <TextView/>        ← 第1列
        <TextView/>        ← 第2列
        <TextView/>        ← 第3列
    </TableRow>
    <TableRow>             ← 下一行
        <TextView/>
        <TextView/>
        <TextView/>
    </TableRow>
</TableLayout>

5.4 TableLayout核心属性

属性 作用 使用示例
stretchColumns 指定可拉伸的列 android:stretchColumns="*"(所有列) android:stretchColumns="0,2"(第0列和第2列)
shrinkColumns 指定可收缩的列 android:shrinkColumns="1"
collapseColumns 指定可隐藏的列 android:collapseColumns="2"
layout_span 跨列显示 android:layout_span="3"(跨3列)
layout_column 指定列位置 android:layout_column="1"(放在第1列)

5.5 实战案例:学生成绩表

xml 复制代码
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="*"
    android:padding="16dp"
    android:background="#F5F5F5">

    <!-- 标题行 -->
    <TableRow
        android:background="#2196F3"
        android:padding="12dp">

        <TextView
            android:text="姓名"
            android:textColor="@android:color/white"
            android:textSize="16sp"
            android:textStyle="bold"
            android:gravity="center"/>

        <TextView
            android:text="语文"
            android:textColor="@android:color/white"
            android:textSize="16sp"
            android:textStyle="bold"
            android:gravity="center"/>

        <TextView
            android:text="数学"
            android:textColor="@android:color/white"
            android:textSize="16sp"
            android:textStyle="bold"
            android:gravity="center"/>

        <TextView
            android:text="英语"
            android:textColor="@android:color/white"
            android:textSize="16sp"
            android:textStyle="bold"
            android:gravity="center"/>

    </TableRow>

    <!-- 分隔线 -->
    <View
        android:layout_height="1dp"
        android:background="#CCCCCC"/>

    <!-- 数据行1 -->
    <TableRow
        android:background="@android:color/white"
        android:padding="10dp">

        <TextView
            android:text="张三"
            android:textSize="14sp"
            android:gravity="center"/>

        <TextView
            android:text="95"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

        <TextView
            android:text="88"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

        <TextView
            android:text="92"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

    </TableRow>

    <!-- 分隔线 -->
    <View
        android:layout_height="1dp"
        android:background="#EEEEEE"/>

    <!-- 数据行2 -->
    <TableRow
        android:background="@android:color/white"
        android:padding="10dp">

        <TextView
            android:text="李四"
            android:textSize="14sp"
            android:gravity="center"/>

        <TextView
            android:text="78"
            android:textSize="14sp"
            android:textColor="#FF9800"
            android:gravity="center"/>

        <TextView
            android:text="85"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

        <TextView
            android:text="90"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

    </TableRow>

    <!-- 分隔线 -->
    <View
        android:layout_height="1dp"
        android:background="#EEEEEE"/>

    <!-- 数据行3 -->
    <TableRow
        android:background="@android:color/white"
        android:padding="10dp">

        <TextView
            android:text="王五"
            android:textSize="14sp"
            android:gravity="center"/>

        <TextView
            android:text="92"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

        <TextView
            android:text="96"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

        <TextView
            android:text="89"
            android:textSize="14sp"
            android:textColor="#4CAF50"
            android:gravity="center"/>

    </TableRow>

    <!-- 分隔线 -->
    <View
        android:layout_height="2dp"
        android:background="#CCCCCC"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"/>

    <!-- 统计行(跨列显示) -->
    <TableRow
        android:background="#E8F5E9"
        android:padding="12dp">

        <TextView
            android:text="平均分统计"
            android:textSize="16sp"
            android:textStyle="bold"
            android:textColor="#2E7D32"
            android:layout_span="4"
            android:gravity="center"/>

    </TableRow>

    <TableRow
        android:background="@android:color/white"
        android:padding="10dp">

        <TextView
            android:text="平均分"
            android:textSize="14sp"
            android:gravity="center"/>

        <TextView
            android:text="88.3"
            android:textSize="14sp"
            android:textColor="#2196F3"
            android:gravity="center"/>

        <TextView
            android:text="89.7"
            android:textSize="14sp"
            android:textColor="#2196F3"
            android:gravity="center"/>

        <TextView
            android:text="90.3"
            android:textSize="14sp"
            android:textColor="#2196F3"
            android:gravity="center"/>

    </TableRow>

</TableLayout>

效果预览

复制代码
┌──────────────────────────────────┐
│ 姓名 │ 语文 │ 数学 │ 英语 │ ← 标题行
├──────┼──────┼──────┼──────┤
│ 张三 │  95  │  88  │  92  │
├──────┼──────┼──────┼──────┤
│ 李四 │  78  │  85  │  90  │
├──────┼──────┼──────┼──────┤
│ 王五 │  92  │  96  │  89  │
├──────────────────────────────────┤
│        平均分统计                 │ ← 跨列
├──────┼──────┼──────┼──────┤
│ 平均 │ 88.3 │ 89.7 │ 90.3 │
└──────────────────────────────────┘

5.6 实战案例:计算器布局

xml 复制代码
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="*"
    android:padding="8dp"
    android:background="#263238">

    <!-- 显示屏 -->
    <TableRow
        android:layout_marginBottom="16dp">

        <TextView
            android:id="@+id/display"
            android:layout_span="4"
            android:text="0"
            android:textSize="48sp"
            android:textColor="@android:color/white"
            android:gravity="right|center_vertical"
            android:padding="24dp"
            android:background="#37474F"
            android:layout_height="120dp"/>

    </TableRow>

    <!-- 第一行按钮:C ÷ × ← -->
    <TableRow>
        <Button
            android:text="C"
            android:textSize="20sp"
            android:layout_margin="4dp"
            android:background="#EF5350"
            android:textColor="@android:color/white"/>

        <Button
            android:text="÷"
            android:textSize="20sp"
            android:layout_margin="4dp"
            android:background="#546E7A"
            android:textColor="@android:color/white"/>

        <Button
            android:text="×"
            android:textSize="20sp"
            android:layout_margin="4dp"
            android:background="#546E7A"
            android:textColor="@android:color/white"/>

        <Button
            android:text="←"
            android:textSize="20sp"
            android:layout_margin="4dp"
            android:background="#546E7A"
            android:textColor="@android:color/white"/>
    </TableRow>

    <!-- 第二行:7 8 9 - -->
    <TableRow>
        <Button
            android:text="7"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="8"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="9"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="-"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#546E7A"
            android:textColor="@android:color/white"/>
    </TableRow>

    <!-- 第三行:4 5 6 + -->
    <TableRow>
        <Button
            android:text="4"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="5"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="6"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="+"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#546E7A"
            android:textColor="@android:color/white"/>
    </TableRow>

    <!-- 第四行:1 2 3 = -->
    <TableRow>
        <Button
            android:text="1"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="2"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="3"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="="
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#4CAF50"
            android:textColor="@android:color/white"/>
    </TableRow>

    <!-- 第五行:0跨2列 . = -->
    <TableRow>
        <Button
            android:text="0"
            android:textSize="24sp"
            android:layout_span="2"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="."
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#455A64"
            android:textColor="@android:color/white"/>

        <Button
            android:text="%"
            android:textSize="24sp"
            android:layout_margin="4dp"
            android:background="#546E7A"
            android:textColor="@android:color/white"/>
    </TableRow>

</TableLayout>

5.7 TableLayout的列属性详解

🔧 stretchColumns 拉伸列
xml 复制代码
<!-- 所有列平均拉伸 -->
<TableLayout android:stretchColumns="*">

<!-- 只拉伸第0列和第2列 -->
<TableLayout android:stretchColumns="0,2">

<!-- 只拉伸第1列 -->
<TableLayout android:stretchColumns="1">
🔧 shrinkColumns 收缩列
xml 复制代码
<!-- 当内容过多时,第1列自动收缩 -->
<TableLayout android:shrinkColumns="1">
🔧 collapseColumns 隐藏列
xml 复制代码
<!-- 隐藏第2列 -->
<TableLayout android:collapseColumns="2">

5.8 跨列显示技巧

xml 复制代码
<TableRow>
    <!-- 跨3列显示 -->
    <TextView
        android:text="这是跨3列的标题"
        android:layout_span="3"
        android:gravity="center"
        android:textSize="18sp"
        android:background="#E3F2FD"
        android:padding="12dp"/>
</TableRow>

<TableRow>
    <!-- 正常的3列 -->
    <TextView android:text="第1列"/>
    <TextView android:text="第2列"/>
    <TextView android:text="第3列"/>
</TableRow>

5.9 Java代码动态创建表格

java 复制代码
public class TableLayoutDemo extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        TableLayout tableLayout = new TableLayout(this);
        tableLayout.setStretchAllColumns(true);
        tableLayout.setPadding(16, 16, 16, 16);
        
        // 创建标题行
        TableRow headerRow = new TableRow(this);
        headerRow.setBackgroundColor(Color.parseColor("#2196F3"));
        
        String[] headers = {"姓名", "年龄", "职业"};
        for (String header : headers) {
            TextView tv = new TextView(this);
            tv.setText(header);
            tv.setTextColor(Color.WHITE);
            tv.setTextSize(16);
            tv.setGravity(Gravity.CENTER);
            tv.setPadding(12, 12, 12, 12);
            headerRow.addView(tv);
        }
        tableLayout.addView(headerRow);
        
        // 创建数据行
        String[][] data = {
            {"张三", "25", "工程师"},
            {"李四", "30", "设计师"},
            {"王五", "28", "产品经理"}
        };
        
        for (int i = 0; i < data.length; i++) {
            TableRow dataRow = new TableRow(this);
            dataRow.setBackgroundColor(
                i % 2 == 0 ? Color.WHITE : Color.parseColor("#F5F5F5")
            );
            
            for (String cell : data[i]) {
                TextView tv = new TextView(this);
                tv.setText(cell);
                tv.setTextSize(14);
                tv.setGravity(Gravity.CENTER);
                tv.setPadding(12, 12, 12, 12);
                dataRow.addView(tv);
            }
            
            tableLayout.addView(dataRow);
        }
        
        setContentView(tableLayout);
    }
}

5.10 TableLayout典型应用场景

应用场景 说明 示例
📊 数据表格 展示规则数据 成绩单、价格表
📅 日历界面 日期按表格排列 月历、课程表
🧮 计算器 按钮按行列排列 科学计算器
📝 表单布局 标签和输入框对齐 注册表单
🏪 商品对比 多个商品参数对比 电商对比页

🎲 六、GridLayout - 灵活的网格布局

6.1 GridLayout是什么?

GridLayout(网格布局) 是Android 4.0(API 14)引入的新布局,它将界面划分成行和列的网格,比TableLayout更加灵活强大。

6.2 GridLayout vs TableLayout

对比项 TableLayout GridLayout
引入版本 API 1 API 14
灵活性 较低 非常高
跨行支持 ❌ 不支持 ✅ 支持
权重支持 ❌ 不支持 ✅ 支持
性能 较好 更好
推荐度 ⭐⭐⭐ ⭐⭐⭐⭐⭐

6.3 GridLayout核心属性

属性 作用 使用示例
columnCount 总列数 android:columnCount="4"
rowCount 总行数 android:rowCount="5"
orientation 排列方向 android:orientation="horizontal"
layout_row 所在行 android:layout_row="0"
layout_column 所在列 android:layout_column="1"
layout_rowSpan 跨行数 android:layout_rowSpan="2"
layout_columnSpan 跨列数 android:layout_columnSpan="3"
layout_columnWeight 列权重 android:layout_columnWeight="1"
layout_rowWeight 行权重 android:layout_rowWeight="1"

6.4 实战案例:计算器界面(GridLayout版)

xml 复制代码
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="4"
    android:rowCount="6"
    android:padding="8dp"
    android:background="#263238">

    <!-- 第0行:显示屏(跨4列) -->
    <TextView
        android:id="@+id/display"
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_row="0"
        android:layout_column="0"
        android:layout_columnSpan="4"
        android:layout_columnWeight="1"
        android:text="0"
        android:textSize="48sp"
        android:textColor="@android:color/white"
        android:gravity="right|center_vertical"
        android:padding="16dp"
        android:background="#37474F"
        android:layout_margin="4dp"/>

    <!-- 第1行:C ÷ × ← -->
    <Button
        android:layout_row="1"
        android:layout_column="0"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="C"
        android:textSize="20sp"
        android:background="#EF5350"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="1"
        android:layout_column="1"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="÷"
        android:textSize="20sp"
        android:background="#546E7A"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="1"
        android:layout_column="2"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="×"
        android:textSize="20sp"
        android:background="#546E7A"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="1"
        android:layout_column="3"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="←"
        android:textSize="20sp"
        android:background="#546E7A"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <!-- 第2行:7 8 9 - -->
    <Button
        android:layout_row="2"
        android:layout_column="0"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="7"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="2"
        android:layout_column="1"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="8"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="2"
        android:layout_column="2"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="9"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="2"
        android:layout_column="3"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="-"
        android:textSize="24sp"
        android:background="#546E7A"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <!-- 第3行:4 5 6 + -->
    <Button
        android:layout_row="3"
        android:layout_column="0"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="4"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="3"
        android:layout_column="1"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="5"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="3"
        android:layout_column="2"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="6"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="3"
        android:layout_column="3"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="+"
        android:textSize="24sp"
        android:background="#546E7A"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <!-- 第4行:1 2 3 = (=跨2行) -->
    <Button
        android:layout_row="4"
        android:layout_column="0"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="1"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="4"
        android:layout_column="1"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="2"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="4"
        android:layout_column="2"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="3"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <!-- = 按钮跨2行 -->
    <Button
        android:layout_row="4"
        android:layout_column="3"
        android:layout_rowSpan="2"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_rowWeight="1"
        android:text="="
        android:textSize="24sp"
        android:background="#4CAF50"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <!-- 第5行:0跨2列 . -->
    <Button
        android:layout_row="5"
        android:layout_column="0"
        android:layout_columnSpan="2"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="0"
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

    <Button
        android:layout_row="5"
        android:layout_column="2"
        android:layout_columnWeight="1"
        android:layout_width="0dp"
        android:text="."
        android:textSize="24sp"
        android:background="#455A64"
        android:textColor="@android:color/white"
        android:layout_margin="4dp"/>

</GridLayout>

布局示意图

复制代码
┌────────────────────────────┐
│         显示屏(跨4列)      │
├──────┬──────┬──────┬──────┤
│  C   │  ÷   │  ×   │  ←   │
├──────┼──────┼──────┼──────┤
│  7   │  8   │  9   │  -   │
├──────┼──────┼──────┼──────┤
│  4   │  5   │  6   │  +   │
├──────┼──────┼──────┤      │
│  1   │  2   │  3   │  =   │
├──────┴──────┼──────┤ (跨2行)
│      0      │  .   │      │
└─────────────┴──────┴──────┘

6.5 实战案例:九宫格相册

xml 复制代码
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:columnCount="3"
    android:rowCount="3"
    android:padding="4dp"
    android:background="#F5F5F5">

    <!-- 9张图片,自动按3x3排列 -->
    <ImageView
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_columnWeight="1"
        android:src="@drawable/photo1"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"/>

    <ImageView
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_columnWeight="1"
        android:src="@drawable/photo2"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"/>

    <ImageView
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_columnWeight="1"
        android:src="@drawable/photo3"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"/>

    <ImageView
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_columnWeight="1"
        android:src="@drawable/photo4"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"/>

    <ImageView
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_columnWeight="1"
        android:src="@drawable/photo5"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"/>

    <ImageView
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_columnWeight="1"
        android:src="@drawable/photo6"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"/>

    <ImageView
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_columnWeight="1"
        android:src="@drawable/photo7"
        android:scaleType="centerCrop"
        android:layout_margin="2dp"/>

    <ImageView
		android:layout_width="0dp"
		android:layout_height="120dp"
		android:layout_columnWeight="1"
		android:src="@drawable/photo8"
		android:scaleType="centerCrop"
		android:layout_margin="2dp"/>               

效果预览

复制代码
┌─────┬─────┬─────┐
│ 图1 │ 图2 │ 图3 │
├─────┼─────┼─────┤
│ 图4 │ 图5 │ 图6 │
├─────┼─────┼─────┤
│ 图7 │ 图8 │ 图9 │
└─────┴─────┴─────┘

6.6 实战案例:不规则网格布局

xml 复制代码
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="4"
    android:rowCount="4"
    android:padding="8dp">

    <!-- 大图:跨2行2列 -->
    <ImageView
        android:layout_row="0"
        android:layout_column="0"
        android:layout_rowSpan="2"
        android:layout_columnSpan="2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_rowWeight="1"
        android:layout_columnWeight="1"
        android:src="@drawable/featured"
        android:scaleType="centerCrop"
        android:layout_margin="4dp"
        android:background="#E3F2FD"/>

    <!-- 右上小图1 -->
    <ImageView
        android:layout_row="0"
        android:layout_column="2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_rowWeight="1"
        android:layout_columnWeight="1"
        android:src="@drawable/small1"
        android:scaleType="centerCrop"
        android:layout_margin="4dp"
        android:background="#C8E6C9"/>

    <!-- 右上小图2 -->
    <ImageView
        android:layout_row="0"
        android:layout_column="3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_rowWeight="1"
        android:layout_columnWeight="1"
        android:src="@drawable/small2"
        android:scaleType="centerCrop"
        android:layout_margin="4dp"
        android:background="#FFECB3"/>

    <!-- 右侧中间:跨2行1列 -->
    <ImageView
        android:layout_row="1"
        android:layout_column="2"
        android:layout_rowSpan="2"
        android:layout_columnSpan="2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_rowWeight="1"
        android:layout_columnWeight="1"
        android:src="@drawable/medium"
        android:scaleType="centerCrop"
        android:layout_margin="4dp"
        android:background="#FFCDD2"/>

    <!-- 底部3个小图 -->
    <ImageView
        android:layout_row="2"
        android:layout_column="0"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_rowWeight="1"
        android:layout_columnWeight="1"
        android:src="@drawable/small3"
        android:scaleType="centerCrop"
        android:layout_margin="4dp"
        android:background="#E1BEE7"/>

    <ImageView
        android:layout_row="2"
        android:layout_column="1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_rowWeight="1"
        android:layout_columnWeight="1"
        android:src="@drawable/small4"
        android:scaleType="centerCrop"
        android:layout_margin="4dp"
        android:background="#B2DFDB"/>

    <!-- 最后一行:跨4列的横幅 -->
    <TextView
        android:layout_row="3"
        android:layout_column="0"
        android:layout_columnSpan="4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"
        android:text="浏览更多精彩内容"
        android:textSize="18sp"
        android:textColor="@android:color/white"
        android:gravity="center"
        android:padding="16dp"
        android:background="#2196F3"
        android:layout_margin="4dp"/>

</GridLayout>

布局示意图

复制代码
┌─────────────┬─────┬─────┐
│             │ 小1 │ 小2 │
│    大图     ├─────┴─────┤
│  (跨2×2)    │           │
├─────────────┤   中图    │
│ 小3 │ 小4   │  (跨2×2)  │
└─────┴───────┴───────────┘
┌───────────────────────────┐
│      浏览更多精彩内容      │
└───────────────────────────┘

6.7 GridLayout权重详解

🎯 列权重(columnWeight)
xml 复制代码
<!-- 三个按钮平分宽度 -->
<Button
    android:layout_width="0dp"
    android:layout_columnWeight="1"
    android:text="按钮1"/>

<Button
    android:layout_width="0dp"
    android:layout_columnWeight="1"
    android:text="按钮2"/>

<Button
    android:layout_width="0dp"
    android:layout_columnWeight="1"
    android:text="按钮3"/>

关键点

  • 必须设置 layout_width="0dp" 权重才生效
  • 权重比例决定宽度分配
🎯 行权重(rowWeight)
xml 复制代码
<!-- 控件填满整个单元格 -->
<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_columnWeight="1"
    android:layout_rowWeight="1"
    android:src="@drawable/image"/>

6.8 Java代码动态创建GridLayout

java 复制代码
public class GridLayoutDemo extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 创建GridLayout
        GridLayout gridLayout = new GridLayout(this);
        gridLayout.setColumnCount(3);  // 3列
        gridLayout.setRowCount(3);     // 3行
        gridLayout.setPadding(16, 16, 16, 16);
        
        // 动态创建9个按钮
        for (int i = 0; i < 9; i++) {
            Button button = new Button(this);
            button.setText("按钮 " + (i + 1));
            button.setTextSize(16);
            
            // 设置GridLayout布局参数
            GridLayout.LayoutParams params = new GridLayout.LayoutParams();
            
            // 指定行列位置
            params.rowSpec = GridLayout.spec(i / 3, 1f);      // 行号,权重
            params.columnSpec = GridLayout.spec(i % 3, 1f);   // 列号,权重
            
            // 设置宽高为0,配合权重使用
            params.width = 0;
            params.height = GridLayout.LayoutParams.WRAP_CONTENT;
            
            // 设置外边距
            params.setMargins(8, 8, 8, 8);
            
            button.setLayoutParams(params);
            
            // 设置背景颜色(交替)
            if ((i / 3 + i % 3) % 2 == 0) {
                button.setBackgroundColor(Color.parseColor("#E3F2FD"));
            } else {
                button.setBackgroundColor(Color.parseColor("#C8E6C9"));
            }
            
            gridLayout.addView(button);
        }
        
        setContentView(gridLayout);
    }
}

6.9 GridLayout典型应用场景

应用场景 说明 优势
🧮 计算器 按钮规则排列,支持跨行列 比TableLayout更灵活
📷 相册九宫格 图片网格展示 自动适配屏幕
🎮 游戏界面 棋盘、关卡选择 精确控制位置
📱 App启动器 应用图标网格 类似Android桌面
🎨 调色板 颜色选择器 规整的网格布局

6.10 GridLayout常见问题

问题 原因 解决方案
控件大小不一致 未设置权重 添加 layout_columnWeightlayout_rowWeight
权重不生效 宽高未设置为0dp 设置 layout_width="0dp"layout_height="0dp"
控件位置错乱 未指定行列位置 明确设置 layout_rowlayout_column
跨行列不生效 Span属性设置错误 检查 layout_rowSpanlayout_columnSpan

⚠️ 七、AbsoluteLayout - 已废弃的绝对布局

7.1 为什么要学习已废弃的布局?

虽然AbsoluteLayout在Android 1.5(API Level 3)就被废弃了,但作为学习Android发展历程的一部分,了解它可以:

  1. 理解为什么被废弃:避免在新项目中犯类似错误
  2. 维护旧代码:可能遇到使用该布局的老项目
  3. 对比学习:更好地理解现代布局的优势

7.2 AbsoluteLayout是什么?

AbsoluteLayout(绝对布局) 通过精确的X、Y坐标来定位每个控件的位置。

7.3 核心属性

属性 作用 示例
layout_x X坐标(水平位置) android:layout_x="100dp"
layout_y Y坐标(垂直位置) android:layout_y="200dp"

坐标系统

复制代码
(0,0) ─────────→ X轴
  │
  │
  │
  ↓
 Y轴

7.4 示例代码

xml 复制代码
<!-- ⚠️ 不推荐使用!仅供学习参考 -->
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="位置(50, 50)"
        android:layout_x="50dp"
        android:layout_y="50dp"
        android:background="#FFCDD2"
        android:padding="10dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="位置(150, 150)"
        android:layout_x="150dp"
        android:layout_y="150dp"
        android:background="#C8E6C9"
        android:padding="10dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="位置(250, 250)"
        android:layout_x="250dp"
        android:layout_y="250dp"
        android:background="#FFECB3"
        android:padding="10dp"/>

</AbsoluteLayout>

7.5 为什么被废弃?

缺点 说明 影响
不适配不同屏幕 固定坐标在不同分辨率下显示不一致 在大屏幕上可能显示很小,小屏幕上可能超出范围
横竖屏切换问题 坐标不会自动调整 横屏时布局错乱
维护困难 每次调整都要重新计算坐标 开发效率低下
国际化困难 不同语言文本长度不同 固定坐标无法适应

7.6 替代方案

需求 推荐使用 原因
相对定位 RelativeLayout 自动适配屏幕
复杂布局 ConstraintLayout 最强大灵活
简单排列 LinearLayout 简单高效
网格布局 GridLayout 规整美观

7.7 对比示例

❌ 不好的做法(AbsoluteLayout)
xml 复制代码
<AbsoluteLayout>
    <Button
        android:layout_x="100dp"
        android:layout_y="200dp"
        android:text="登录"/>
    <!-- 在不同屏幕上位置固定,可能显示异常 -->
</AbsoluteLayout>
✅ 推荐做法(RelativeLayout)
xml 复制代码
<RelativeLayout>
    <Button
        android:layout_centerInParent="true"
        android:text="登录"/>
    <!-- 自动居中,适配所有屏幕 -->
</RelativeLayout>

🎯 八、布局选择指南与最佳实践

8.1 布局选择决策树

简单列表 中等复杂 非常复杂 是 否 是 否 开始选择布局 界面复杂度? LinearLayout 需要层叠效果? ConstraintLayout FrameLayout 规则表格? TableLayout/GridLayout RelativeLayout

8.2 各布局综合对比

布局 学习难度 性能 灵活性 推荐指数 适用场景
LinearLayout ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ 简单列表、按钮组
RelativeLayout ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ 复杂界面、表单
FrameLayout ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ 层叠效果、遮罩
TableLayout ⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐ 规则表格
GridLayout ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 网格、计算器
AbsoluteLayout ⭐⭐⭐ 已废弃

8.3 实际开发场景推荐

📱 登录界面
复制代码
推荐:LinearLayout (垂直排列)
理由:标题、输入框、按钮垂直排列,简单明了
<LinearLayout
    android:orientation="vertical"
    android:padding="24dp">
    
    <TextView android:text="登录"/>
    <EditText android:hint="用户名"/>
    <EditText android:hint="密码"/>
    <Button android:text="登录"/>
    
</LinearLayout>
📋 设置页面
复制代码
推荐:LinearLayout + RelativeLayout 嵌套
理由:每个设置项内部用RelativeLayout,整体用LinearLayout垂直排列
<LinearLayout android:orientation="vertical">
    <!-- 每个设置项 -->
    <RelativeLayout>
        <TextView android:layout_alignParentLeft="true" android:text="通知"/>
        <Switch android:layout_alignParentRight="true"/>
    </RelativeLayout>
    <RelativeLayout>
        <TextView android:layout_alignParentLeft="true" android:text="声音"/>
        <Switch android:layout_alignParentRight="true"/>
    </RelativeLayout>
</LinearLayout>
🎮 游戏界面
复制代码
推荐:FrameLayout (多层叠加)
理由:背景、游戏区、UI控件分层显示
<FrameLayout>
    <ImageView android:src="@drawable/background"/>  <!-- 背景层 -->
    <GameView/>  <!-- 游戏层 -->
    <LinearLayout android:layout_gravity="top">      <!-- UI层 -->
        <TextView android:text="分数: 100"/>
    </LinearLayout>
</FrameLayout>
🧮 计算器
复制代码
推荐:GridLayout
理由:按钮规则排列,支持跨行跨列
💬 聊天界面
复制代码
推荐:RelativeLayout
理由:顶部标题栏、底部输入栏、中间消息列表,相对定位最合适

8.4 布局嵌套最佳实践

✅ 推荐做法
xml 复制代码
<!-- 最多2-3层嵌套 -->
<LinearLayout>  <!-- 第1层 -->
    <RelativeLayout>  <!-- 第2层 -->
        <TextView/>
        <ImageView/>
    </RelativeLayout>
</LinearLayout>
❌ 不推荐做法
xml 复制代码
<!-- 过度嵌套(5层以上) -->
<LinearLayout>
    <LinearLayout>
        <LinearLayout>
            <LinearLayout>
                <LinearLayout>
                    <TextView/>  <!-- 第5层!性能差! -->
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

8.5 性能优化技巧

技巧 说明 效果
减少嵌套层级 尽量保持在3层以内 ⬆️ 提升渲染速度
使用merge标签 减少不必要的ViewGroup ⬆️ 减少层级
使用ViewStub 延迟加载不常用的视图 ⬆️ 加快启动速度
使用include 复用布局文件 ⬆️ 提高可维护性
避免过度绘制 移除不必要的背景 ⬆️ 提升流畅度
使用<merge>减少层级
xml 复制代码
<!-- child_layout.xml -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView android:text="标题"/>
    <Button android:text="按钮"/>
</merge>
<!-- activity_main.xml -->
<LinearLayout>
    <include layout="@layout/child_layout"/>
    <!-- merge会直接将内容合并到LinearLayout中,不增加层级 -->
</LinearLayout>

8.6 屏幕适配建议

方法 说明 示例
使用dp单位 密度无关像素,自动适配 android:layout_width="100dp"
使用权重 按比例分配空间 android:layout_weight="1"
使用限定符 不同屏幕使用不同布局 layout-land/, layout-sw600dp/
避免硬编码 不要写死尺寸 layout_width="200px"
不同屏幕方向的布局
复制代码
res/
  layout/              ← 默认布局(竖屏)
    activity_main.xml
  layout-land/         ← 横屏布局
    activity_main.xml
  layout-sw600dp/      ← 平板布局(最小宽度600dp)
    activity_main.xml

📝 九、综合实战案例

9.1 案例一:完整的登录界面

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F5F5F5">

    <!-- Logo和标题区域 -->
    <LinearLayout
        android:id="@+id/headerLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:orientation="vertical"
        android:padding="32dp"
        android:gravity="center">

        <ImageView
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:src="@drawable/logo"
            android:layout_marginBottom="16dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="欢迎登录"
            android:textSize="28sp"
            android:textColor="#333333"
            android:textStyle="bold"/>

    </LinearLayout>

    <!-- 登录表单区域 -->
    <LinearLayout
        android:id="@+id/formLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/headerLayout"
        android:layout_marginStart="24dp"
        android:layout_marginEnd="24dp"
        android:layout_marginTop="32dp"
        android:orientation="vertical"
        android:background="@android:color/white"
        android:padding="24dp"
        android:elevation="4dp">

        <!-- 用户名输入框 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:background="#F5F5F5"
            android:padding="12dp"
            android:layout_marginBottom="16dp">

            <ImageView
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:src="@drawable/ic_user"
                android:layout_marginEnd="12dp"/>

            <EditText
                android:id="@+id/etUsername"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="请输入用户名"
                android:textSize="16sp"
                android:background="@null"
                android:inputType="text"/>

        </LinearLayout>

        <!-- 密码输入框 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:background="#F5F5F5"
            android:padding="12dp"
            android:layout_marginBottom="24dp">

            <ImageView
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:src="@drawable/ic_lock"
                android:layout_marginEnd="12dp"/>

            <EditText
                android:id="@+id/etPassword"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="请输入密码"
                android:textSize="16sp"
                android:background="@null"
                android:inputType="textPassword"/>

        </LinearLayout>

        <!-- 记住密码和忘记密码 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="24dp">

            <CheckBox
                android:id="@+id/cbRemember"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="记住密码"
                android:textSize="14sp"/>

            <View
                android:layout_width="0dp"
                android:layout_height="1dp"
                android:layout_weight="1"/>

            <TextView
                android:id="@+id/tvForgetPassword"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="忘记密码?"
                android:textSize="14sp"
                android:textColor="#2196F3"/>

        </LinearLayout>

        <!-- 登录按钮 -->
        <Button
            android:id="@+id/btnLogin"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="登录"
            android:textSize="18sp"
            android:textColor="@android:color/white"
            android:background="#4CAF50"
            android:padding="14dp"
            android:layout_marginBottom="16dp"/>

        <!-- 第三方登录 -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="或使用第三方登录"
            android:textSize="14sp"
            android:textColor="#999999"
            android:layout_gravity="center"
            android:layout_marginBottom="16dp"/>

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

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:src="@drawable/ic_wechat"
                android:layout_margin="8dp"/>

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:src="@drawable/ic_qq"
                android:layout_margin="8dp"/>

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:src="@drawable/ic_weibo"
                android:layout_margin="8dp"/>

        </LinearLayout>

    </LinearLayout>

    <!-- 底部注册提示 -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal"
        android:layout_marginBottom="32dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="还没有账号?"
            android:textSize="14sp"
            android:textColor="#666666"/>

        <TextView
            android:id="@+id/tvRegister"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="立即注册"
            android:textSize="14sp"
            android:textColor="#2196F3"
            android:layout_marginStart="4dp"/>

    </LinearLayout>

</RelativeLayout>

9.2 案例二:商品详情页

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

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

        <!-- 商品图片轮播区 -->
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="400dp"
		   android:background="#F5F5F5">
            <!-- ViewPager轮播图 -->
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <!-- 轮播指示器 -->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:layout_marginBottom="16dp"
            android:orientation="horizontal"
            android:background="#80000000"
            android:padding="8dp">

            <View
                android:layout_width="8dp"
                android:layout_height="8dp"
                android:background="@drawable/dot_selected"
                android:layout_margin="4dp"/>

            <View
                android:layout_width="8dp"
                android:layout_height="8dp"
                android:background="@drawable/dot_normal"
                android:layout_margin="4dp"/>

            <View
                android:layout_width="8dp"
                android:layout_height="8dp"
                android:background="@drawable/dot_normal"
                android:layout_margin="4dp"/>

        </LinearLayout>

        <!-- 收藏按钮 -->
        <ImageView
            android:id="@+id/ivFavorite"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:src="@drawable/ic_favorite"
            android:layout_gravity="top|right"
            android:layout_margin="16dp"
            android:padding="8dp"
            android:background="@drawable/bg_circle_white"/>

    </FrameLayout>

    <!-- 商品信息区 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:background="@android:color/white">

        <!-- 价格和标题 -->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="12dp">

            <!-- 价格 -->
            <LinearLayout
                android:id="@+id/priceLayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:orientation="horizontal"
                android:gravity="center_vertical">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="¥"
                    android:textSize="16sp"
                    android:textColor="#FF5722"/>

                <TextView
                    android:id="@+id/tvPrice"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="299"
                    android:textSize="32sp"
                    android:textColor="#FF5722"
                    android:textStyle="bold"/>

                <TextView
                    android:id="@+id/tvOriginalPrice"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="¥499"
                    android:textSize="14sp"
                    android:textColor="#999999"
                    android:layout_marginStart="8dp"/>

            </LinearLayout>

            <!-- 已售数量 -->
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:text="已售 1000+ 件"
                android:textSize="14sp"
                android:textColor="#999999"/>

        </RelativeLayout>

        <!-- 商品标题 -->
        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="【新品上市】高品质无线蓝牙耳机,降噪效果好,续航时间长"
            android:textSize="18sp"
            android:textColor="#333333"
            android:lineSpacingExtra="4dp"
            android:layout_marginBottom="12dp"/>

        <!-- 标签 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="包邮"
                android:textSize="12sp"
                android:textColor="#FF5722"
                android:background="@drawable/bg_tag_red"
                android:padding="4dp"
                android:layout_marginEnd="8dp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="7天无理由退换"
                android:textSize="12sp"
                android:textColor="#4CAF50"
                android:background="@drawable/bg_tag_green"
                android:padding="4dp"
                android:layout_marginEnd="8dp"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="正品保证"
                android:textSize="12sp"
                android:textColor="#2196F3"
                android:background="@drawable/bg_tag_blue"
                android:padding="4dp"/>

        </LinearLayout>

    </LinearLayout>

    <!-- 分隔线 -->
    <View
        android:layout_width="match_parent"
        android:layout_height="8dp"
        android:background="#F5F5F5"/>

    <!-- 选择规格区 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:background="@android:color/white">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择规格"
            android:textSize="16sp"
            android:textColor="#333333"
            android:textStyle="bold"
            android:layout_marginBottom="12dp"/>

        <!-- 颜色选择 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="12dp">

            <TextView
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:text="颜色:"
                android:textSize="14sp"
                android:textColor="#666666"/>

            <GridLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:columnCount="3">

                <TextView
                    android:layout_width="0dp"
                    android:layout_columnWeight="1"
                    android:layout_height="wrap_content"
                    android:text="黑色"
                    android:textSize="14sp"
                    android:gravity="center"
                    android:padding="8dp"
                    android:background="@drawable/bg_spec_selected"
                    android:layout_margin="4dp"/>

                <TextView
                    android:layout_width="0dp"
                    android:layout_columnWeight="1"
                    android:layout_height="wrap_content"
                    android:text="白色"
                    android:textSize="14sp"
                    android:gravity="center"
                    android:padding="8dp"
                    android:background="@drawable/bg_spec_normal"
                    android:layout_margin="4dp"/>

                <TextView
                    android:layout_width="0dp"
                    android:layout_columnWeight="1"
                    android:layout_height="wrap_content"
                    android:text="蓝色"
                    android:textSize="14sp"
                    android:gravity="center"
                    android:padding="8dp"
                    android:background="@drawable/bg_spec_normal"
                    android:layout_margin="4dp"/>

            </GridLayout>

        </LinearLayout>

        <!-- 容量选择 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:text="容量:"
                android:textSize="14sp"
                android:textColor="#666666"/>

            <GridLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:columnCount="3">

                <TextView
                    android:layout_width="0dp"
                    android:layout_columnWeight="1"
                    android:layout_height="wrap_content"
                    android:text="64GB"
                    android:textSize="14sp"
                    android:gravity="center"
                    android:padding="8dp"
                    android:background="@drawable/bg_spec_selected"
                    android:layout_margin="4dp"/>

                <TextView
                    android:layout_width="0dp"
                    android:layout_columnWeight="1"
                    android:layout_height="wrap_content"
                    android:text="128GB"
                    android:textSize="14sp"
                    android:gravity="center"
                    android:padding="8dp"
                    android:background="@drawable/bg_spec_normal"
                    android:layout_margin="4dp"/>

                <TextView
                    android:layout_width="0dp"
                    android:layout_columnWeight="1"
                    android:layout_height="wrap_content"
                    android:text="256GB"
                    android:textSize="14sp"
                    android:gravity="center"
                    android:padding="8dp"
                    android:background="@drawable/bg_spec_normal"
                    android:layout_margin="4dp"/>

            </GridLayout>

        </LinearLayout>

    </LinearLayout>

    <!-- 分隔线 -->
    <View
        android:layout_width="match_parent"
        android:layout_height="8dp"
        android:background="#F5F5F5"/>

    <!-- 商品详情 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:background="@android:color/white">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="商品详情"
            android:textSize="16sp"
            android:textColor="#333333"
            android:textStyle="bold"
            android:layout_marginBottom="12dp"/>

        <!-- 参数表格 -->
        <TableLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:stretchColumns="1"
            android:background="#F5F5F5">

            <TableRow
                android:padding="12dp"
                android:background="@android:color/white">

                <TextView
                    android:text="品牌"
                    android:textSize="14sp"
                    android:textColor="#666666"
                    android:layout_width="100dp"/>

                <TextView
                    android:text="Apple"
                    android:textSize="14sp"
                    android:textColor="#333333"/>

            </TableRow>

            <View
                android:layout_height="1dp"
                android:background="#F5F5F5"/>

            <TableRow
                android:padding="12dp"
                android:background="@android:color/white">

                <TextView
                    android:text="型号"
                    android:textSize="14sp"
                    android:textColor="#666666"/>

                <TextView
                    android:text="AirPods Pro 2"
                    android:textSize="14sp"
                    android:textColor="#333333"/>

            </TableRow>

            <View
                android:layout_height="1dp"
                android:background="#F5F5F5"/>

            <TableRow
                android:padding="12dp"
                android:background="@android:color/white">

                <TextView
                    android:text="续航时间"
                    android:textSize="14sp"
                    android:textColor="#666666"/>

                <TextView
                    android:text="6小时(单次)/ 30小时(充电盒)"
                    android:textSize="14sp"
                    android:textColor="#333333"/>

            </TableRow>

            <View
                android:layout_height="1dp"
                android:background="#F5F5F5"/>

            <TableRow
                android:padding="12dp"
                android:background="@android:color/white">

                <TextView
                    android:text="防水等级"
                    android:textSize="14sp"
                    android:textColor="#666666"/>

                <TextView
                    android:text="IPX4"
                    android:textSize="14sp"
                    android:textColor="#333333"/>

            </TableRow>

        </TableLayout>

        <!-- 详情图片 -->
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/product_detail"
            android:adjustViewBounds="true"
            android:layout_marginTop="16dp"/>

    </LinearLayout>

    <!-- 底部占位,防止被底部栏遮挡 -->
    <View
        android:layout_width="match_parent"
        android:layout_height="80dp"/>

</LinearLayout>

9.3 案例三:设置页面

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#F5F5F5">

    <!-- 标题栏 -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:background="#4CAF50"
        android:elevation="4dp">

        <ImageView
            android:id="@+id/ivBack"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:src="@drawable/ic_back"
            android:padding="12dp"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="设置"
            android:textSize="20sp"
            android:textColor="@android:color/white"
            android:textStyle="bold"
            android:layout_centerInParent="true"/>

    </RelativeLayout>

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

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

            <!-- 账户设置分组 -->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="账户设置"
                android:textSize="14sp"
                android:textColor="#999999"
                android:padding="16dp"
                android:paddingStart="16dp"/>

            <!-- 个人信息 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="@android:color/white"
                android:paddingStart="16dp"
                android:paddingEnd="16dp">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentLeft="true"
                    android:orientation="horizontal"
                    android:gravity="center_vertical">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:src="@drawable/ic_person"
                        android:layout_marginEnd="12dp"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="个人信息"
                        android:textSize="16sp"
                        android:textColor="#333333"/>

                </LinearLayout>

                <ImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:src="@drawable/ic_arrow_right"
                    android:layout_centerVertical="true"
                    android:layout_alignParentRight="true"/>

            </RelativeLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#F5F5F5"
                android:layout_marginStart="52dp"/>

            <!-- 修改密码 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="@android:color/white"
                android:paddingStart="16dp"
                android:paddingEnd="16dp">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentLeft="true"
                    android:orientation="horizontal"
                    android:gravity="center_vertical">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:src="@drawable/ic_lock"
                        android:layout_marginEnd="12dp"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="修改密码"
                        android:textSize="16sp"
                        android:textColor="#333333"/>

                </LinearLayout>

                <ImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:src="@drawable/ic_arrow_right"
                    android:layout_centerVertical="true"
                    android:layout_alignParentRight="true"/>

            </RelativeLayout>

            <!-- 通知设置分组 -->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="通知设置"
                android:textSize="14sp"
                android:textColor="#999999"
                android:padding="16dp"
                android:layout_marginTop="8dp"/>

            <!-- 消息通知开关 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="@android:color/white"
                android:paddingStart="16dp"
                android:paddingEnd="16dp">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentLeft="true"
                    android:orientation="horizontal"
                    android:gravity="center_vertical">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:src="@drawable/ic_notification"
                        android:layout_marginEnd="12dp"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="消息通知"
                        android:textSize="16sp"
                        android:textColor="#333333"/>

                </LinearLayout>

                <Switch
                    android:id="@+id/switchNotification"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentRight="true"
                    android:checked="true"/>

            </RelativeLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#F5F5F5"
                android:layout_marginStart="52dp"/>

            <!-- 声音开关 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="@android:color/white"
                android:paddingStart="16dp"
                android:paddingEnd="16dp">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentLeft="true"
                    android:orientation="horizontal"
                    android:gravity="center_vertical">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:src="@drawable/ic_sound"
                        android:layout_marginEnd="12dp"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="声音"
                        android:textSize="16sp"
                        android:textColor="#333333"/>

                </LinearLayout>

                <Switch
                    android:id="@+id/switchSound"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentRight="true"
                    android:checked="true"/>

            </RelativeLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#F5F5F5"
                android:layout_marginStart="52dp"/>

            <!-- 震动开关 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="@android:color/white"
                android:paddingStart="16dp"
                android:paddingEnd="16dp">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentLeft="true"
                    android:orientation="horizontal"
                    android:gravity="center_vertical">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:src="@drawable/ic_vibrate"
                        android:layout_marginEnd="12dp"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="震动"
                        android:textSize="16sp"
                        android:textColor="#333333"/>

                </LinearLayout>

                <Switch
                    android:id="@+id/switchVibrate"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentRight="true"
                    android:checked="false"/>

            </RelativeLayout>

            <!-- 其他设置分组 -->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="其他"
                android:textSize="14sp"
                android:textColor="#999999"
                android:padding="16dp"
                android:layout_marginTop="8dp"/>

            <!-- 清除缓存 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="@android:color/white"
                android:paddingStart="16dp"
                android:paddingEnd="16dp">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentLeft="true"
                    android:orientation="horizontal"
                    android:gravity="center_vertical">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:src="@drawable/ic_clean"
                        android:layout_marginEnd="12dp"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="清除缓存"
                        android:textSize="16sp"
                        android:textColor="#333333"/>

                </LinearLayout>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="23.5 MB"
                    android:textSize="14sp"
                    android:textColor="#999999"
                    android:layout_centerVertical="true"
                    android:layout_alignParentRight="true"/>

            </RelativeLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="#F5F5F5"
                android:layout_marginStart="52dp"/>

            <!-- 关于我们 -->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:background="@android:color/white"
                android:paddingStart="16dp"
                android:paddingEnd="16dp">

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_alignParentLeft="true"
                    android:orientation="horizontal"
                    android:gravity="center_vertical">

                    <ImageView
                        android:layout_width="24dp"
                        android:layout_height="24dp"
                        android:src="@drawable/ic_info"
                        android:layout_marginEnd="12dp"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="关于我们"
                        android:textSize="16sp"
                        android:textColor="#333333"/>

                </LinearLayout>

                <ImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:src="@drawable/ic_arrow_right"
                    android:layout_centerVertical="true"
                    android:layout_alignParentRight="true"/>

            </RelativeLayout>

            <!-- 退出登录按钮 -->
            <Button
                android:id="@+id/btnLogout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="退出登录"
                android:textSize="16sp"
                android:textColor="#FF5722"
                android:background="@android:color/white"
                android:padding="16dp"
                android:layout_margin="16dp"/>

        </LinearLayout>

    </ScrollView>

</LinearLayout>

📚 十、本章总结与复习要点

10.1 核心知识点回顾

🎯 六大布局特点总结
布局 一句话总结 记忆口诀
LinearLayout 线性排列,支持权重 排队买票,一个跟一个
RelativeLayout 相对定位,灵活多变 家具摆放,互相参照
FrameLayout 层层叠加,简单实用 扑克牌叠,后来居上
TableLayout 表格结构,规则排列 Excel表,行列分明
GridLayout 网格布局,最强大 棋盘格,精确控制
AbsoluteLayout 绝对定位,已废弃 坐标死板,不要使用

10.2 必须掌握的属性

LinearLayout必会属性
xml 复制代码
android:orientation="vertical"           <!-- 方向 -->
android:layout_weight="1"               <!-- 权重 -->
android:gravity="center"                <!-- 子控件对齐 -->
android:layout_gravity="center"         <!-- 自身对齐 -->
RelativeLayout必会属性
xml 复制代码
android:layout_centerInParent="true"    <!-- 父容器居中 -->
android:layout_alignParentTop="true"    <!-- 父容器顶部对齐 -->
android:layout_below="@id/view1"        <!-- 在控件下方 -->
android:layout_toRightOf="@id/view2"    <!-- 在控件右边 -->
GridLayout必会属性
xml 复制代码
android:columnCount="3"                 <!-- 列数 -->
android:rowCount="4"                    <!-- 行数 -->
android:layout_row="0"                  <!-- 所在行 -->
android:layout_column="1"               <!-- 所在列 -->
android:layout_columnSpan="2"           <!-- 跨列数 -->
android:layout_columnWeight="1"         <!-- 列权重 -->

10.3 期末考试高频考点

✅ 选择题常考点
  1. LinearLayout权重计算
  2. LinearLayout使用______属性来设置排列方向。(答案:orientation)
  3. GridLayout可以通过______属性实现跨列显示。(答案:layout_columnSpan)
  4. RelativeLayout中,______属性可以让控件在父容器中居中。(答案:layout_centerInParent)
  5. TableLayout中,______属性用于指定可拉伸的列。(答案:stretchColumns)
✅ 简答题常考点

Q1: 简述LinearLayout的权重(weight)机制及计算方法。

答:

  1. 权重用于按比例分配剩余空间
  2. 计算公式:实际大小 = 原始大小 + (剩余空间 × 权重比例)
  3. 使用时需设置layout_width或layout_height为0dp
  4. 权重比例 = 当前控件权重 / 所有控件权重总和

Q2: RelativeLayout和LinearLayout的区别是什么?各适用于什么场景?

答:

  • RelativeLayout
    • 通过相对位置定位控件
    • 适合复杂界面,减少嵌套层级
    • 性能略差于LinearLayout
    • 适用场景:表单、复杂布局
  • LinearLayout
    • 按线性方向排列控件
    • 简单易用,性能好
    • 可能需要多层嵌套
    • 适用场景:简单列表、按钮组

Q3: 为什么AbsoluteLayout被废弃?应该用什么替代?

答: 废弃原因:

  1. 不适配不同屏幕尺寸和分辨率
  2. 横竖屏切换时布局错乱
  3. 维护困难,修改需重新计算坐标
  4. 无法适应国际化需求

替代方案:

  • 简单定位:LinearLayout
  • 相对定位:RelativeLayout
  • 复杂布局:ConstraintLayout
✅ 编程题常考点

题目1:使用LinearLayout实现一个登录界面

要求:

  • 垂直排列
  • 包含标题、用户名输入框、密码输入框、登录按钮
  • 登录按钮占满宽度
xml 复制代码
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="24dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="欢迎登录"
        android:textSize="24sp"
        android:layout_gravity="center"
        android:layout_marginBottom="32dp"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入用户名"
        android:layout_marginBottom="16dp"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入密码"
        android:inputType="textPassword"
        android:layout_marginBottom="24dp"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录"/>

</LinearLayout>

题目2:使用GridLayout实现一个3×3的九宫格

xml 复制代码
<GridLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:columnCount="3"
    android:rowCount="3"
    android:padding="8dp">

    <!-- 9个按钮,自动按3×3排列 -->
    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"
        android:text="1"
        android:layout_margin="4dp"/>

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"
        android:text="2"
        android:layout_margin="4dp"/>

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"
        android:text="3"
        android:layout_margin="4dp"/>

    <!-- ...继续添加4-9按钮... -->

</GridLayout>

题目3:使用RelativeLayout实现顶部标题栏+底部按钮+中间内容的布局

xml 复制代码
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 顶部标题栏 -->
    <TextView
        android:id="@+id/titleBar"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_alignParentTop="true"
        android:text="标题"
        android:gravity="center"
        android:background="#4CAF50"/>

    <!-- 底部按钮 -->
    <Button
        android:id="@+id/bottomButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="确定"/>

    <!-- 中间内容 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/titleBar"
        android:layout_above="@id/bottomButton"
        android:text="中间内容区域"
        android:gravity="center"/>

</RelativeLayout>

10.4 实战能力检测清单

在期末考试前,请确保你能够:

✅ 基础能力(必须掌握)
  • 能够说出六大布局的名称和基本特点
  • 能够使用LinearLayout实现垂直和水平排列
  • 理解并能计算LinearLayout的权重分配
  • 能够使用RelativeLayout实现相对定位
  • 能够使用FrameLayout实现层叠效果
  • 知道AbsoluteLayout为什么被废弃
✅ 进阶能力(重点掌握)
  • 能够熟练使用GridLayout实现网格布局
  • 能够使用TableLayout实现表格数据展示
  • 能够根据需求选择合适的布局类型
  • 能够合理嵌套布局实现复杂界面
  • 能够在Java代码中动态创建布局
✅ 高级能力(加分项)
  • 能够优化布局层级,减少嵌套
  • 能够使用merge标签优化性能
  • 理解不同布局的性能差异
  • 能够实现屏幕适配
  • 能够独立完成复杂页面布局

10.5 快速记忆口诀

复制代码
六大布局记心间,各有特点要牢记:

Linear线性排一排,
横竖方向orientation,
权重分配要记牢,
width设零weight才妙。

Relative相对定位强,
above below左右忙,
centerInParent最中央,
父容器内任你放。

Frame帧布局很简单,
控件叠加一层层,
layout_gravity定位置,
轮播遮罩都能用。

Table表格行和列,
stretchColumns要拉伸,
layout_span跨列显,
规则数据展示佳。

Grid网格最灵活,
columnCount定列数,
columnSpan跨列显,
计算器用它最合适。

Absolute已废弃,
坐标固定不灵活,
屏幕适配有问题,
千万不要再使用。

选择布局有诀窍,
简单用Linear最高效,
复杂界面Relative好,
层叠效果Frame不少,
表格Grid看需要,
性能优化记得好!

10.6 常见错误与解决方案

❌ 错误1:LinearLayout权重不生效
xml 复制代码
<!-- 错误写法 -->
<Button
    android:layout_width="wrap_content"
    android:layout_weight="1"/>

正确写法

xml 复制代码
<Button
    android:layout_width="0dp"
    android:layout_weight="1"/>

原因:使用权重时,对应方向的尺寸必须设置为0dp。

❌ 错误2:RelativeLayout引用未定义的ID
xml 复制代码
<!-- 错误写法 -->
<TextView
    android:layout_below="@id/titleView"/>

<TextView
    android:id="@+id/titleView"/>

正确写法

xml 复制代码
<!-- 先定义被引用的控件 -->
<TextView
    android:id="@+id/titleView"/>

<TextView
    android:layout_below="@id/titleView"/>

原因:RelativeLayout中引用的ID必须已经在前面定义过。

❌ 错误3:过度嵌套导致性能问题
xml 复制代码
<!-- 不推荐:5层嵌套 -->
<LinearLayout>
    <LinearLayout>
        <LinearLayout>
            <LinearLayout>
                <LinearLayout>
                    <TextView/>
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

优化方案

xml 复制代码
<!-- 使用RelativeLayout减少嵌套 -->
<RelativeLayout>
    <TextView
        android:layout_centerInParent="true"/>
</RelativeLayout>
❌ 错误4:GridLayout权重不生效
xml 复制代码
<!-- 错误写法 -->
<Button
    android:layout_columnWeight="1"/>

正确写法

xml 复制代码
<Button
    android:layout_width="0dp"
    android:layout_columnWeight="1"/>

原因:GridLayout使用权重时,也需要设置对应方向为0dp。

❌ 错误5:FrameLayout控件被遮挡
xml 复制代码
<!-- 问题:后添加的控件会覆盖先添加的 -->
<FrameLayout>
    <TextView android:text="我会被遮挡"/>
    <ImageView android:src="@drawable/cover"/>
</FrameLayout>

解决方案

xml 复制代码
<!-- 调整添加顺序或使用layout_gravity -->
<FrameLayout>
    <ImageView 
        android:src="@drawable/background"
        android:layout_gravity="center"/>
    
    <TextView 
        android:text="我在最上层"
        android:layout_gravity="top|center_horizontal"/>
</FrameLayout>

10.7 期末复习时间规划建议

📅 考前7天复习计划

Day 1-2:基础巩固

  • 复习LinearLayout和RelativeLayout
  • 重点:权重计算、相对定位
  • 练习:实现3-5个简单界面

Day 3-4:进阶学习

  • 复习FrameLayout、TableLayout、GridLayout
  • 重点:层叠效果、表格布局、网格布局
  • 练习:实现计算器、表格界面

Day 5-6:综合应用

  • 复习布局嵌套技巧
  • 完成3个综合案例
  • 练习:登录界面、商品详情页、设置页面

Day 7:冲刺复习

  • 回顾易错点和重点知识
  • 快速过一遍所有布局特点
  • 模拟考试题目练习

10.8 实用工具推荐

🛠️ 布局预览工具
  1. Android Studio Layout Editor
    • 可视化拖拽设计
    • 实时预览不同屏幕尺寸
    • 自动生成XML代码
  2. Hierarchy Viewer
    • 查看布局层级
    • 分析性能问题
    • 优化布局结构
  3. Layout Inspector
    • 运行时查看布局
    • 调试布局问题
    • 查看实际渲染效果

10.9 学习资源推荐

📚 官方文档
🎥 视频教程
  • B站搜索:"Android布局详解"
  • 慕课网:Android UI设计课程
  • YouTube:Android Layout Tutorials
📖 推荐书籍
  • 《第一行代码 Android》- 郭霖
  • 《Android开发艺术探索》- 任玉刚
  • 《Android群英传》- 徐宜生

🎓 十一、课后作业与练习

11.1 基础练习题

练习1:权重计算题

题目: 一个水平LinearLayout,总宽度为1200dp,包含三个Button:

  • Button1:layout_width="100dp",layout_weight="1"
  • Button2:layout_width="200dp",layout_weight="2"
  • Button3:layout_width="100dp",layout_weight="1"

请计算每个Button的实际宽度。

答案

复制代码
剩余空间 = 1200 - 100 - 200 - 100 = 800dp
总权重 = 1 + 2 + 1 = 4

Button1实际宽度 = 100 + (800 × 1/4) = 100 + 200 = 300dp
Button2实际宽度 = 200 + (800 × 2/4) = 200 + 400 = 600dp
Button3实际宽度 = 100 + (800 × 1/4) = 100 + 200 = 300dp

验证:300 + 600 + 300 = 1200dp ✓
练习2:布局选择题

为以下场景选择最合适的布局:

  1. 场景A :一个包含标题、两个输入框、一个按钮的垂直排列的登录界面
    • 答案:LinearLayout(orientation="vertical")
  2. 场景B :一个顶部有标题栏、底部有导航栏、中间是内容区域的主界面
    • 答案:RelativeLayout
  3. 场景C :一个图片上方显示半透明遮罩和文字的Banner
    • 答案:FrameLayout
  4. 场景D :一个3×4的数字键盘
    • 答案:GridLayout
  5. 场景E :一个展示学生成绩的表格
    • 答案:TableLayout

11.2 编程实战题

实战1:实现微信聊天界面布局

要求

  1. 顶部:标题栏(固定56dp高度,显示"聊天")
  2. 底部:输入栏(包含输入框和发送按钮)
  3. 中间:消息列表区域(ScrollView包裹)
  4. 使用RelativeLayout实现

参考代码框架

xml 复制代码
<RelativeLayout>
    <!-- 顶部标题栏 -->
    <LinearLayout android:id="@+id/titleBar" 
        android:layout_alignParentTop="true"/>
    
    <!-- 底部输入栏 -->
    <LinearLayout android:id="@+id/inputBar" 
        android:layout_alignParentBottom="true"/>
    
    <!-- 中间消息区 -->
    <ScrollView 
        android:layout_below="@id/titleBar"
        android:layout_above="@id/inputBar"/>
</RelativeLayout>
实战2:实现电商商品列表项

要求

  1. 左侧:商品图片(100dp×100dp)
  2. 右侧上方:商品名称
  3. 右侧中间:商品价格(红色、粗体)
  4. 右侧下方:购买按钮
  5. 使用RelativeLayout实现

提示

  • 图片使用layout_alignParentLeft
  • 右侧内容使用layout_toRightOf
  • 价格使用android:textColor="#FF5722"
实战3:实现计算器界面

要求

  1. 使用GridLayout实现
  2. 4列5行布局
  3. 第一行:显示屏(跨4列)
  4. 其他行:数字和运算符按钮
  5. "0"按钮跨2列
  6. "="按钮跨2行

挑战

  • 所有按钮使用权重平分空间
  • 按钮之间有4dp间距
  • 显示屏高度120dp

11.3 综合项目作业

项目:个人信息管理App界面

第一阶段:登录页面

  • 使用LinearLayout实现
  • 包含Logo、标题、输入框、登录按钮
  • 底部有"注册"和"忘记密码"链接

第二阶段:主界面

  • 使用RelativeLayout实现
  • 顶部导航栏
  • 中间内容区(使用ViewPager)
  • 底部Tab栏(4个图标按钮)

第三阶段:个人信息页

  • 使用LinearLayout + RelativeLayout嵌套
  • 头像和昵称区域
  • 多个设置项(每项包含图标、文字、箭头)

第四阶段:数据展示页

  • 使用TableLayout或GridLayout
  • 展示个人数据统计表格
  • 支持数据排序和筛选

提交要求

  1. 完整的XML布局文件
  2. 布局层级不超过3层
  3. 适配不同屏幕尺寸
  4. 代码注释清晰

🎉 结语

🌟 恭喜你完成本章学习!

通过本章的学习,你已经:

掌握了Android六大基本布局的使用方法理解了每种布局的特点和适用场景学会了如何选择合适的布局实现界面能够嵌套使用多种布局创建复杂界面了解了布局优化和性能提升技巧

💪 继续学习的方向

学完布局后,建议按以下顺序继续学习:

  1. ConstraintLayout(现代布局的首选)
  2. 事件处理(让界面"动"起来)
  3. 自定义View(创建个性化控件)
  4. Material Design(遵循设计规范)
  5. RecyclerView(高效列表展示)

📝 期末备考建议

  1. 多练习:每种布局至少独立实现3个案例
  2. 多对比:理解不同布局的优缺点和使用场景
  3. 多思考:为什么要这样设计?有没有更好的方案?
  4. 多总结:整理易错点和重点知识
  5. 多复习:考前一周每天看一遍本教程

🎯 最后的叮嘱

布局是Android开发的基础,也是面试的高频考点。

不要死记硬背,要理解原理和应用场景。

多动手实践,遇到问题多思考多查资料。

相信经过系统学习,你一定能在期末考试中取得好成绩!


📞 学习交流

如果在学习过程中遇到问题,可以:

  1. 📖 查阅Android官方文档
  2. 🔍 搜索CSDN、Stack Overflow
  3. 👥 加入Android开发学习群
  4. 💬 向老师或同学请教
  5. 🎥 观看B站相关教学视频

记住:遇到问题不要慌,查阅文档、动手实践是最好的学习方法!


🎓 祝你期末考试顺利!加油!💪

如果本教程对你有帮助,请分享给更多需要的同学!

相关推荐
恋猫de小郭3 小时前
Snapchat 开源全新跨平台框架 Valdi ,一起来搞懂它究竟有什么特别之处
android·前端·flutter
AI科技星3 小时前
引力编程时代:人类文明存续与升维
数据结构·人工智能·经验分享·算法·计算机视觉
LBuffer7 小时前
破解入门学习笔记题四十六
数据库·笔记·学习
我是好小孩10 小时前
【Android】布局优化:include、merge、ViewStub以及Inflate()源码浅析
android
GISer_Jing11 小时前
2025年Flutter与React Native对比
android·flutter·react native
MasterLi802311 小时前
我的读书清单
android·linux·学习
hssfscv11 小时前
JAVA学习笔记——集合的概念和习题
笔记·学习
怪兽201411 小时前
fastjson在kotlin不使用kotlin-reflect库怎么使用?
android·开发语言·kotlin
彭同学学习日志12 小时前
Kotlin Fragment 按钮跳转报错解决:Unresolved reference ‘floatingActionButton‘
android·开发语言·kotlin