全部笔记All notes

Android界面布局开发实战指南

阅读 10m 30s10m 30s read

系列导航

概述

Android界面布局是构建用户界面的基础。本指南深入介绍Android平台的布局系统,从传统的View系统到现代的Jetpack Compose,帮助开发者构建响应式、美观的用户界面。

学习目标

  • 掌握Android五大基础布局的使用
  • 理解View和ViewGroup的层级关系
  • 学习Material Design设计规范
  • 了解Jetpack Compose声明式UI
  • 掌握布局性能优化技巧

核心概念

View与ViewGroup

在Android中,所有用户界面元素都是基于View和ViewGroup构建的:

  • View(视图):UI组件的基类,代表屏幕上的一个矩形区域

    • 负责绘制和事件处理
    • 如TextView、Button、ImageView等
  • ViewGroup(视图组):View的子类,可以包含其他View

    • 是布局容器的基类
    • 负责管理子View的位置和大小
    • 如LinearLayout、RelativeLayout等

视图层级结构

ViewGroup (根布局)
├── ViewGroup (子布局)
│   ├── View (控件)
│   └── View (控件)
└── View (控件)

尺寸单位

单位说明使用场景
dp (density-independent pixels)密度无关像素布局尺寸、边距
sp (scale-independent pixels)缩放无关像素文字大小
px (pixels)像素不推荐使用
match_parent匹配父容器填充可用空间
wrap_content包裹内容根据内容自适应

💡 最佳实践:

  • 始终使用dp作为布局尺寸单位
  • 文字大小必须使用sp,支持用户字体缩放
  • 避免使用px,会导致适配问题

资源管理

Android使用资源限定符来支持不同设备:

res/
├── drawable/       # 默认图片资源
├── drawable-hdpi/  # 高密度屏幕(~240dpi)
├── drawable-xhdpi/ # 超高密度屏幕(~320dpi)
├── drawable-xxhdpi/# 超超高密度屏幕(~480dpi)
├── drawable-xxxhdpi/# 超超超高密度屏幕(~640dpi)
└── mipmap/        # 应用图标资源

布局基础

通用属性

属性名称功能描述
android:id设置布局的标识
android:layout_width设置布局的宽度
android:layout_height设置布局的高度
android:background设置布局的背景
android:layout_margin设置当前布局与屏幕边界或与周围控件的距离
android:padding设置当前布局与该布局中控件的距离

五大布局详解

1. LinearLayout(线性布局)

线性布局是最简单也是最常用的布局,子视图按照水平或垂直方向线性排列。

核心属性

属性名称功能描述示例值
android:orientation设置排列方向"vertical" / "horizontal"
android:layout_weight设置权重分配"1"
android:gravity设置内容对齐方式"center"
android:weightSum设置权重总和"3"
android:divider设置分隔线"@drawable/divider"
android:showDividers显示分隔线位置"middle"

使用示例

Java实现:

public class LinearLayoutActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 创建LinearLayout
        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        linearLayout.setGravity(Gravity.CENTER);
        linearLayout.setPadding(16, 16, 16, 16);
        
        // 添加子视图
        TextView textView = new TextView(this);
        textView.setText("Hello LinearLayout");
        textView.setTextSize(18);
        linearLayout.addView(textView);
        
        setContentView(linearLayout);
    }
}

Kotlin实现:

class LinearLayoutActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 使用Kotlin DSL创建布局
        val linearLayout = LinearLayout(this).apply {
            orientation = LinearLayout.VERTICAL
            gravity = Gravity.CENTER
            setPadding(16, 16, 16, 16)
            
            addView(TextView(context).apply {
                text = "Hello LinearLayout"
                textSize = 18f
            })
        }
        
        setContentView(linearLayout)
    }
}

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:gravity="center"
    android:padding="16dp">
    
    <!-- 权重分配示例 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="占1/3空间"
        android:gravity="center"
        android:background="#FFE0E0" />
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:text="占2/3空间"
        android:gravity="center"
        android:background="#E0FFE0" />
    
</LinearLayout>

性能优化建议

  1. 避免嵌套过深:LinearLayout嵌套会影响性能
  2. 合理使用weight:weight会导致二次测量,影响性能
  3. 使用merge标签:减少层级
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView ... />
    <Button ... />
</merge>

2. RelativeLayout(相对布局)

相对布局通过相对定位的方式管理子视图位置,灵活性高,适合复杂界面。

核心属性

属性类别属性名称功能描述
android:layout_centerInParent设置当前控件位于父布局的中央位置
android:layout_centerVertical设置当前控件位于父布局的垂直居中位置
android:layout_centerHorizontal设置当前控件位于父控件的水平居中位置
android:layout_above设置当前控件位于某控件上方
android:layout_below设置当前控件位于某控件下方
android:layout_toLeftOf设置当前控件位于某控件左侧
android:layout_toRightOf设置当前控件位于某控件右侧
android:layout_alignParentTop设置当前控件是否与父控件顶端对齐
android:layout_alignParentLeft设置当前控件是否与父控件左对齐
android:layout_alignParentRight设置当前控件是否与父控件右对齐
android:layout_alignParemtBottom设置当前控件是否与父控件底端对齐
android:layout_alignTop设置当前控件的上边界与某控件的上边界对齐
android:layout_alignBottom设置当前控件的下边界与某控件的下边界对齐
android:layout_alignLeft设置当前控件的左边界与某控件的左边界对齐
android:layout_alignRight设置当前控件的右边界与某控件的右边界对齐

使用示例

复杂界面布局:

<?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:padding="16dp">
    
    <!-- 顶部标题栏 -->
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="相对布局示例"
        android:textSize="20sp"
        android:textStyle="bold"
        android:gravity="center"
        android:padding="12dp"
        android:background="#E3F2FD" />
    
    <!-- 中心内容 -->
    <ImageView
        android:id="@+id/iv_center"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_centerInParent="true"
        android:src="@drawable/ic_android"
        android:background="#F5F5F5" />
    
    <!-- 围绕中心的按钮 -->
    <Button
        android:id="@+id/btn_top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/iv_center"
        android:layout_centerHorizontal="true"
        android:text="上" />
    
    <Button
        android:id="@+id/btn_left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/iv_center"
        android:layout_alignTop="@id/iv_center"
        android:layout_alignBottom="@id/iv_center"
        android:text="左" />
    
    <!-- 底部按钮栏 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        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" />
        
    </LinearLayout>
    
</RelativeLayout>

Java代码动态创建:

public class RelativeLayoutActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        RelativeLayout relativeLayout = new RelativeLayout(this);
        relativeLayout.setPadding(16, 16, 16, 16);
        
        // 创建中心ImageView
        ImageView centerImage = new ImageView(this);
        centerImage.setId(View.generateViewId());
        centerImage.setImageResource(R.drawable.ic_android);
        RelativeLayout.LayoutParams centerParams = new RelativeLayout.LayoutParams(
            dpToPx(120), dpToPx(120));
        centerParams.addRule(RelativeLayout.CENTER_IN_PARENT);
        relativeLayout.addView(centerImage, centerParams);
        
        // 创建顶部按钮
        Button topButton = new Button(this);
        topButton.setText("顶部按钮");
        RelativeLayout.LayoutParams topParams = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);
        topParams.addRule(RelativeLayout.ABOVE, centerImage.getId());
        topParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
        relativeLayout.addView(topButton, topParams);
        
        setContentView(relativeLayout);
    }
    
    private int dpToPx(int dp) {
        return (int) (dp * getResources().getDisplayMetrics().density);
    }
}

性能优化建议

  1. 减少布局层级:RelativeLayout可以实现扁平化布局
  2. 避免循环依赖:确保视图之间的相对关系不形成循环
  3. 使用ID引用:使用@+id创建ID,@id引用已存在的ID
属性名称功能描述
android:oriemtation设置布局内控件的排列顺序(写在LinearLayout标签里面的)
android:layout_weight在布局内设置控件权重,属性值可直接写 int 值(需要把控件的宽度设置成0dp)

3. ConstraintLayout(约束布局)

ConstraintLayout是Android推荐的现代布局方式,功能强大,性能优秀,支持可视化编辑。

核心特性

  1. 扁平化布局:减少视图层级
  2. 灵活约束:支持相对定位、比例、链式布局
  3. 性能优化:单次测量完成布局
  4. 可视化编辑:Android Studio完美支持

基础约束属性

约束类型属性示例说明
位置约束layout_constraintLeft_toLeftOf左边对齐
边距约束layout_constraintTop_toBottomOf顶部对齐到底部
居中约束layout_constraintCenterInParent父容器居中
比例约束layout_constraintDimensionRatio宽高比
权重约束layout_constraintHorizontal_weight水平权重

高级特性示例

1. 链式布局(Chain):

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <!-- 水平链式布局 -->
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮1"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button2"
        app:layout_constraintTop_toTopOf="parent" />
    
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮2"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintRight_toLeftOf="@+id/button3"
        app:layout_constraintTop_toTopOf="parent" />
    
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按钮3"
        app:layout_constraintLeft_toRightOf="@+id/button2"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

2. 比例约束:

<ImageView
    android:id="@+id/iv_ratio"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scaleType="centerCrop"
    app:layout_constraintDimensionRatio="16:9"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

3. Guideline辅助线:

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />

<TextView
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="左侧内容"
    app:layout_constraintRight_toLeftOf="@id/guideline"
    app:layout_constraintLeft_toLeftOf="parent" />

4. Barrier屏障:

<androidx.constraintlayout.widget.Barrier
    android:id="@+id/barrier"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierDirection="end"
    app:constraint_referenced_ids="tv_label1,tv_label2" />

Kotlin代码创建ConstraintLayout:

class ConstraintLayoutActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val constraintLayout = ConstraintLayout(this).apply {
            id = View.generateViewId()
        }
        
        val textView = TextView(this).apply {
            id = View.generateViewId()
            text = "ConstraintLayout示例"
            textSize = 20f
        }
        
        constraintLayout.addView(textView)
        
        // 使用ConstraintSet设置约束
        val constraintSet = ConstraintSet().apply {
            clone(constraintLayout)
            
            // 设置TextView居中
            connect(
                textView.id, ConstraintSet.LEFT,
                ConstraintSet.PARENT_ID, ConstraintSet.LEFT, 0
            )
            connect(
                textView.id, ConstraintSet.RIGHT,
                ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 0
            )
            connect(
                textView.id, ConstraintSet.TOP,
                ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0
            )
            connect(
                textView.id, ConstraintSet.BOTTOM,
                ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0
            )
        }
        
        constraintSet.applyTo(constraintLayout)
        setContentView(constraintLayout)
    }
}

4. TableLayout(表格布局)

表格布局将子视图组织成行和列的形式,适合显示表格数据。

三个布局属性:

属性名称功能描述
android:stretchColumns设置可被拉伸的列。如:android:stretchColumns=“0”,表示第 1 列可被拉伸
android:shrinkColumns设置可被收缩的列。如:android:shrinkColumns=“1,2”,表示2,3列可收缩
android:collapseColumns设置可被隐藏的列。如:android:collapscColumns=“0”,表示第 1 列可被隐藏

二个控件属性:

属性名称功能描述
android:layout_column设置该控件显示的位置,如android:layout_colum=“1”表示在第2个位置显示
android:layout_span设置该控件占据几行,默认为1行

使用示例

创建登录表单:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:stretchColumns="1">
    
    <TableRow>
        <TextView
            android:text="用户名:"
            android:textSize="16sp"
            android:padding="8dp" />
        
        <EditText
            android:id="@+id/et_username"
            android:hint="请输入用户名"
            android:inputType="text" />
    </TableRow>
    
    <TableRow>
        <TextView
            android:text="密码:"
            android:textSize="16sp"
            android:padding="8dp" />
        
        <EditText
            android:id="@+id/et_password"
            android:hint="请输入密码"
            android:inputType="textPassword" />
    </TableRow>
    
    <TableRow>
        <Button
            android:text="登录"
            android:layout_column="1"
            android:layout_marginTop="16dp" />
    </TableRow>
    
</TableLayout>

5. FrameLayout(帧布局)

帧布局是最简单的布局,所有子视图都堆叠在左上角,后添加的视图会覆盖先添加的视图。

属性名称功能描述
android:foreground设置帧布局容器的前景图像(始终在所有子控件之上)
android:foregroundGravity设置前景图像显示的位置

使用示例

创建图片预览界面:

<?xml version="1.0" encoding="utf-8"?>
<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" />
    
    <!-- 居中的文字 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="FrameLayout示例"
        android:textColor="#FFFFFF"
        android:textSize="24sp"
        android:layout_gravity="center" />
    
    <!-- 角标 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="NEW"
        android:textColor="#FFFFFF"
        android:background="#FF0000"
        android:padding="4dp"
        android:layout_gravity="top|end"
        android:layout_margin="8dp" />
    
</FrameLayout>

Material Design布局

CoordinatorLayout

CoordinatorLayout是Material Design的核心布局,支持子视图之间的交互行为。

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        
        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="200dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
            
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:src="@drawable/header"
                app:layout_collapseMode="parallax" />
            
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin" />
            
        </com.google.android.material.appbar.CollapsingToolbarLayout>
        
    </com.google.android.material.appbar.AppBarLayout>
    
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        android:src="@drawable/ic_add" />
    
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Jetpack Compose布局

Jetpack Compose是Android的现代声明式UI工具包,使用Kotlin构建原生界面。

基础布局组件

@Composable
fun ComposeLayoutExample() {
    // Column - 垂直排列
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = "Jetpack Compose",
            style = MaterialTheme.typography.h4
        )
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // Row - 水平排列
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceEvenly
        ) {
            Button(onClick = { /* 处理点击 */ }) {
                Text("按钮1")
            }
            Button(onClick = { /* 处理点击 */ }) {
                Text("按钮2")
            }
        }
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // Box - 堆叠布局
        Box(
            modifier = Modifier
                .size(200.dp)
                .background(Color.LightGray)
        ) {
            Text(
                "居中文本",
                modifier = Modifier.align(Alignment.Center)
            )
            Text(
                "角标",
                modifier = Modifier
                    .align(Alignment.TopEnd)
                    .padding(8.dp)
                    .background(Color.Red)
                    .padding(4.dp),
                color = Color.White
            )
        }
    }
}

高级布局

@Composable
fun ConstraintLayoutExample() {
    ConstraintLayout(
        modifier = Modifier.fillMaxSize()
    ) {
        // 创建引用
        val (button, text, image) = createRefs()
        
        Button(
            onClick = { /* 处理点击 */ },
            modifier = Modifier.constrainAs(button) {
                top.linkTo(parent.top, margin = 16.dp)
                start.linkTo(parent.start)
                end.linkTo(parent.end)
            }
        ) {
            Text("按钮")
        }
        
        Text(
            "文本内容",
            modifier = Modifier.constrainAs(text) {
                top.linkTo(button.bottom, margin = 16.dp)
                centerHorizontallyTo(parent)
            }
        )
        
        Image(
            painter = painterResource(id = R.drawable.ic_android),
            contentDescription = null,
            modifier = Modifier
                .size(100.dp)
                .constrainAs(image) {
                    top.linkTo(text.bottom, margin = 16.dp)
                    centerHorizontallyTo(parent)
                }
        )
    }
}

性能优化

1. 布局层级优化

问题: 过深的视图层级会导致性能问题

解决方案:

  • 使用ConstraintLayout减少层级
  • 使用merge标签重用布局
  • 使用ViewStub延迟加载
<!-- 使用ViewStub延迟加载 -->
<ViewStub
    android:id="@+id/stub_import"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout="@layout/heavy_layout" />
// 需要时才加载
ViewStub stub = findViewById(R.id.stub_import);
View inflated = stub.inflate();

2. 过度绘制优化

检测工具: 开发者选项 > 调试GPU过度绘制

优化策略:

  • 移除不必要的背景
  • 使用clipChildren属性
  • 优化自定义View的onDraw方法

3. 布局性能测试

class LayoutPerformanceTest {
    
    @Test
    fun measureLayoutPerformance() {
        val view = LayoutInflater.from(context)
            .inflate(R.layout.complex_layout, null)
        
        // 测量布局时间
        val startTime = System.nanoTime()
        view.measure(
            View.MeasureSpec.makeMeasureSpec(1080, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(1920, View.MeasureSpec.EXACTLY)
        )
        val measureTime = System.nanoTime() - startTime
        
        // 布局时间
        val layoutStart = System.nanoTime()
        view.layout(0, 0, 1080, 1920)
        val layoutTime = System.nanoTime() - layoutStart
        
        println("Measure time: ${measureTime / 1_000_000}ms")
        println("Layout time: ${layoutTime / 1_000_000}ms")
    }
}

最佳实践

1. 响应式设计

使用限定符支持不同屏幕:

res/
├── layout/              # 默认布局
├── layout-sw600dp/      # 7"平板
├── layout-sw720dp/      # 10"平板
├── layout-land/         # 横屏
└── layout-large-land/   # 大屏横屏

2. 适配不同屏幕密度

object DimensionUtils {
    fun dpToPx(context: Context, dp: Float): Int {
        return (dp * context.resources.displayMetrics.density).toInt()
    }
    
    fun pxToDp(context: Context, px: Float): Float {
        return px / context.resources.displayMetrics.density
    }
    
    fun getScreenWidth(context: Context): Int {
        return context.resources.displayMetrics.widthPixels
    }
    
    fun getScreenHeight(context: Context): Int {
        return context.resources.displayMetrics.heightPixels
    }
}

3. 主题和样式

<!-- res/values/styles.xml -->
<resources>
    <!-- 应用主题 -->
    <style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
    </style>
    
    <!-- 通用样式 -->
    <style name="TitleTextStyle">
        <item name="android:textSize">20sp</item>
        <item name="android:textColor">?attr/colorOnSurface</item>
        <item name="android:textStyle">bold</item>
        <item name="android:layout_marginBottom">8dp</item>
    </style>
    
    <style name="ButtonStyle" parent="Widget.MaterialComponents.Button">
        <item name="android:minHeight">48dp</item>
        <item name="android:textAllCaps">false</item>
        <item name="cornerRadius">8dp</item>
    </style>
</resources>

调试技巧

1. Layout Inspector

使用步骤:

  1. 运行应用
  2. Tools > Layout Inspector
  3. 选择进程和Activity
  4. 查看3D视图层级

2. 布局边界显示

开启方法:

// 开发者选项中开启
// 或通过代码
if (BuildConfig.DEBUG) {
    ViewGroup rootView = findViewById(android.R.id.content)
    showLayoutBounds(rootView)
}

fun showLayoutBounds(view: View) {
    // 绘制边界的自定义实现
}

3. Systrace分析

# 捕获trace
python systrace.py --time=10 -o mynewtrace.html sched freq idle am wm gfx view res

常见问题

问题1:布局显示不正确

原因:

  • 属性设置错误
  • 约束关系冲突
  • 尺寸计算问题

解决方案:

// 调试布局问题
view.viewTreeObserver.addOnGlobalLayoutListener {
    Log.d("Layout", "Width: ${view.width}, Height: ${view.height}")
    Log.d("Layout", "X: ${view.x}, Y: ${view.y}")
}

问题2:性能问题

症状: 界面卡顿、掉帧

分析工具:

  • GPU Profiler
  • Systrace
  • Layout Inspector

优化方案:

  1. 减少布局层级
  2. 使用ConstraintLayout
  3. 避免在onDraw中创建对象
  4. 使用RecyclerView替代ListView

问题3:适配问题

问题表现: 不同设备显示效果差异大

解决方案:

<!-- 使用百分比布局 -->
<androidx.percentlayout.widget.PercentRelativeLayout>
    <View
        app:layout_widthPercent="50%"
        app:layout_heightPercent="30%" />
</androidx.percentlayout.widget.PercentRelativeLayout>

相关文章

Android开发基础

进阶技术

相关技术栈

总结

Android布局系统是构建优秀用户界面的基础。从传统的五大布局到现代的ConstraintLayout和Jetpack Compose,每种布局都有其适用场景。

🎯 核心要点

  • 选择合适的布局:根据界面需求选择最适合的布局类型
  • 性能优先:始终关注布局性能,避免过度嵌套
  • 响应式设计:确保在不同设备上都有良好表现
  • 遵循规范:遵循Material Design设计规范

🛠️ 开发建议

  • 优先使用ConstraintLayout构建复杂界面
  • 新项目考虑使用Jetpack Compose
  • 使用工具进行性能分析和优化
  • 重视用户体验和界面流畅度