🎨 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>
关键点:
layout_width="0dp":让权重生效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_content或match_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使用技巧
✅ 推荐做法:
- 先定位关键的"锚点"控件(如中心控件)
- 其他控件相对于锚点定位
- 使用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_columnWeight 和 layout_rowWeight |
| 权重不生效 | 宽高未设置为0dp | 设置 layout_width="0dp" 或 layout_height="0dp" |
| 控件位置错乱 | 未指定行列位置 | 明确设置 layout_row 和 layout_column |
| 跨行列不生效 | Span属性设置错误 | 检查 layout_rowSpan 和 layout_columnSpan |
⚠️ 七、AbsoluteLayout - 已废弃的绝对布局
7.1 为什么要学习已废弃的布局?
虽然AbsoluteLayout在Android 1.5(API Level 3)就被废弃了,但作为学习Android发展历程的一部分,了解它可以:
- 理解为什么被废弃:避免在新项目中犯类似错误
- 维护旧代码:可能遇到使用该布局的老项目
- 对比学习:更好地理解现代布局的优势
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 期末考试高频考点
✅ 选择题常考点
- LinearLayout权重计算
- LinearLayout使用______属性来设置排列方向。(答案:orientation)
- GridLayout可以通过______属性实现跨列显示。(答案:layout_columnSpan)
- RelativeLayout中,______属性可以让控件在父容器中居中。(答案:layout_centerInParent)
- TableLayout中,______属性用于指定可拉伸的列。(答案:stretchColumns)
✅ 简答题常考点
Q1: 简述LinearLayout的权重(weight)机制及计算方法。
答:
- 权重用于按比例分配剩余空间
- 计算公式:实际大小 = 原始大小 + (剩余空间 × 权重比例)
- 使用时需设置layout_width或layout_height为0dp
- 权重比例 = 当前控件权重 / 所有控件权重总和
Q2: RelativeLayout和LinearLayout的区别是什么?各适用于什么场景?
答:
- RelativeLayout :
- 通过相对位置定位控件
- 适合复杂界面,减少嵌套层级
- 性能略差于LinearLayout
- 适用场景:表单、复杂布局
- LinearLayout :
- 按线性方向排列控件
- 简单易用,性能好
- 可能需要多层嵌套
- 适用场景:简单列表、按钮组
Q3: 为什么AbsoluteLayout被废弃?应该用什么替代?
答: 废弃原因:
- 不适配不同屏幕尺寸和分辨率
- 横竖屏切换时布局错乱
- 维护困难,修改需重新计算坐标
- 无法适应国际化需求
替代方案:
- 简单定位: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 实用工具推荐
🛠️ 布局预览工具
- Android Studio Layout Editor
- 可视化拖拽设计
- 实时预览不同屏幕尺寸
- 自动生成XML代码
- Hierarchy Viewer
- 查看布局层级
- 分析性能问题
- 优化布局结构
- 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:布局选择题
为以下场景选择最合适的布局:
- 场景A :一个包含标题、两个输入框、一个按钮的垂直排列的登录界面
- 答案:LinearLayout(orientation="vertical")
- 场景B :一个顶部有标题栏、底部有导航栏、中间是内容区域的主界面
- 答案:RelativeLayout
- 场景C :一个图片上方显示半透明遮罩和文字的Banner
- 答案:FrameLayout
- 场景D :一个3×4的数字键盘
- 答案:GridLayout
- 场景E :一个展示学生成绩的表格
- 答案:TableLayout
11.2 编程实战题
实战1:实现微信聊天界面布局
要求:
- 顶部:标题栏(固定56dp高度,显示"聊天")
- 底部:输入栏(包含输入框和发送按钮)
- 中间:消息列表区域(ScrollView包裹)
- 使用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:实现电商商品列表项
要求:
- 左侧:商品图片(100dp×100dp)
- 右侧上方:商品名称
- 右侧中间:商品价格(红色、粗体)
- 右侧下方:购买按钮
- 使用RelativeLayout实现
提示:
- 图片使用
layout_alignParentLeft - 右侧内容使用
layout_toRightOf - 价格使用
android:textColor="#FF5722"
实战3:实现计算器界面
要求:
- 使用GridLayout实现
- 4列5行布局
- 第一行:显示屏(跨4列)
- 其他行:数字和运算符按钮
- "0"按钮跨2列
- "="按钮跨2行
挑战:
- 所有按钮使用权重平分空间
- 按钮之间有4dp间距
- 显示屏高度120dp
11.3 综合项目作业
项目:个人信息管理App界面
第一阶段:登录页面
- 使用LinearLayout实现
- 包含Logo、标题、输入框、登录按钮
- 底部有"注册"和"忘记密码"链接
第二阶段:主界面
- 使用RelativeLayout实现
- 顶部导航栏
- 中间内容区(使用ViewPager)
- 底部Tab栏(4个图标按钮)
第三阶段:个人信息页
- 使用LinearLayout + RelativeLayout嵌套
- 头像和昵称区域
- 多个设置项(每项包含图标、文字、箭头)
第四阶段:数据展示页
- 使用TableLayout或GridLayout
- 展示个人数据统计表格
- 支持数据排序和筛选
提交要求:
- 完整的XML布局文件
- 布局层级不超过3层
- 适配不同屏幕尺寸
- 代码注释清晰
🎉 结语
🌟 恭喜你完成本章学习!
通过本章的学习,你已经:
✅ 掌握了Android六大基本布局的使用方法 ✅ 理解了每种布局的特点和适用场景 ✅ 学会了如何选择合适的布局实现界面 ✅ 能够嵌套使用多种布局创建复杂界面 ✅ 了解了布局优化和性能提升技巧
💪 继续学习的方向
学完布局后,建议按以下顺序继续学习:
- ConstraintLayout(现代布局的首选)
- 事件处理(让界面"动"起来)
- 自定义View(创建个性化控件)
- Material Design(遵循设计规范)
- RecyclerView(高效列表展示)
📝 期末备考建议
- 多练习:每种布局至少独立实现3个案例
- 多对比:理解不同布局的优缺点和使用场景
- 多思考:为什么要这样设计?有没有更好的方案?
- 多总结:整理易错点和重点知识
- 多复习:考前一周每天看一遍本教程
🎯 最后的叮嘱
布局是Android开发的基础,也是面试的高频考点。
不要死记硬背,要理解原理和应用场景。
多动手实践,遇到问题多思考多查资料。
相信经过系统学习,你一定能在期末考试中取得好成绩!
📞 学习交流
如果在学习过程中遇到问题,可以:
- 📖 查阅Android官方文档
- 🔍 搜索CSDN、Stack Overflow
- 👥 加入Android开发学习群
- 💬 向老师或同学请教
- 🎥 观看B站相关教学视频
记住:遇到问题不要慌,查阅文档、动手实践是最好的学习方法!
🎓 祝你期末考试顺利!加油!💪
如果本教程对你有帮助,请分享给更多需要的同学!