5、布局与UI组件(上):布局管理器与常用控件

各位同学,今天我们来聊聊Android开发里最基础、也最绕不开的话题——布局和控件。说白了,你写的每一个界面,都是靠这些东西堆出来的。我刚开始学Android那会儿,觉得布局就是拖拖拽拽,后来才发现,布局选得好不好,直接决定了你后面维护代码的心情。

嗯,咱们今天先讲上半部分:布局管理器和几个最常用的控件。我会把我在项目里踩过的坑、积累的经验,都揉进去讲。

5.1 布局管理器:界面骨架

布局管理器,就是用来摆放控件的容器。Android提供了好几种,我挑三个最常用的讲:LinearLayout、RelativeLayout、ConstraintLayout。这三个你搞明白了,90%的界面都能搞定。

5.1.1 LinearLayout:线性布局

LinearLayout,顾名思义,就是让子控件按一条线排开。要么横着排,要么竖着排。这个布局最简单,也最直观。

核心属性:

  • android:orientation:设置方向,horizontalvertical
  • android:layout_weight:权重,按比例分配剩余空间
  • android:gravity:控制子控件的对齐方式

举个例子,一个简单的登录界面,用LinearLayout竖着排:

<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="16dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="用户名"
        android:textSize="16sp"/>

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="密码"
        android:textSize="16sp"
        android:layout_marginTop="12dp"/>

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

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

</LinearLayout>

我的经验:LinearLayout虽然简单,但嵌套多了性能会下降。我曾经在一个列表项里嵌套了5层LinearLayout,结果滑动卡成PPT。后来全改成ConstraintLayout,流畅多了。所以,能用一层LinearLayout解决的,就别用两层。

5.1.2 RelativeLayout:相对布局

RelativeLayout允许你通过相对位置来摆放控件。比如“A在B的右边”、“C在D的下方”。这种布局比LinearLayout灵活,但写起来稍微复杂一点。

核心属性分两类:

  • 相对于父容器:layout_alignParentToplayout_alignParentBottomlayout_centerInParent
  • 相对于其他控件:layout_toRightOflayout_belowlayout_alignLeft

举个例子,一个“确定”和“取消”按钮并排,且靠右对齐:

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

    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="取消"
        android:layout_alignParentRight="true"/>

    <Button
        android:id="@+id/btn_ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="确定"
        android:layout_toLeftOf="@id/btn_cancel"
        android:layout_marginRight="12dp"/>

</RelativeLayout>

避坑指南:我曾经在RelativeLayout里用了大量layout_belowlayout_toRightOf,结果改一个控件的位置,其他控件全乱了。后来我学乖了:如果控件之间有复杂的依赖关系,优先考虑ConstraintLayout。

5.1.3 ConstraintLayout:约束布局

ConstraintLayout是Google官方推荐的布局,也是我现在项目里用得最多的。它解决了RelativeLayout的依赖混乱问题,又比LinearLayout更灵活。说白了,它就是RelativeLayout的升级版。

核心概念就一个:约束。每个控件通过约束来确定自己的位置。比如“左边框对齐父容器左边框”、“上边框对齐另一个控件的下边框”。

看个例子,实现一个居中显示的文字:

<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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello ConstraintLayout"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

关键属性速查表:

属性 作用
layout_constraintLeft_toLeftOf 左边框对齐某个控件的左边框
layout_constraintRight_toRightOf 右边框对齐某个控件的右边框
layout_constraintTop_toBottomOf 上边框对齐某个控件的下边框
layout_constraintBottom_toTopOf 下边框对齐某个控件的上边框
layout_constraintHorizontal_bias 水平偏移比例(0~1)
layout_constraintVertical_bias 垂直偏移比例(0~1)

我的建议:新项目直接用ConstraintLayout。它性能好,布局扁平,而且Android Studio的布局编辑器对它的支持最好。你拖拽控件的时候,它会自动帮你生成约束代码,省事不少。

5.2 常用控件:界面元素

布局搭好了,接下来就是往里面填控件。我挑四个最常用的讲:TextView、Button、EditText、ImageView。这四个你每天都会用到。

5.2.1 TextView:文本显示

TextView就是用来显示文字的。看似简单,但坑不少。

常用属性:

  • android:text:显示的文字
  • android:textSize:字号,推荐用sp单位
  • android:textColor:文字颜色
  • android:maxLines:最大行数,超出显示省略号
  • android:ellipsize:省略号位置(end、start、middle)

举个例子,显示一段长文本,超出两行显示省略号:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="这是一段很长的文本,可能会超出两行,所以我们需要设置maxLines和ellipsize来限制显示。"
    android:maxLines="2"
    android:ellipsize="end"
    android:textSize="14sp"/>

避坑指南:我曾经在TextView里直接拼接HTML标签,结果在某些机型上显示异常。后来发现,用Html.fromHtml()方法处理一下就好了。另外,textSize一定要用sp,别用dp,否则用户改了系统字体大小,你的界面就崩了。

5.2.2 Button:按钮

Button继承自TextView,所以TextView的属性它都能用。但Button有自己的特色:默认有背景和文字颜色。

常用操作:

  • 设置点击事件:setOnClickListener
  • 自定义背景:用android:background设置颜色或drawable
  • 禁用状态:android:enabled="false"

代码示例:

Button myButton = findViewById(R.id.my_button);
myButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 点击后的逻辑
        Toast.makeText(MainActivity.this, "按钮被点击了", Toast.LENGTH_SHORT).show();
    }
});

我的经验:按钮的点击区域不要太小。我见过有人把按钮设成wrap_content,结果文字只有几个像素宽,用户点都点不到。我一般会给按钮加个minWidthminHeight,或者用padding扩大点击区域。

5.2.3 EditText:文本输入

EditText是用户输入文本的控件。它比TextView多了光标、输入法、输入类型等特性。

关键属性:

  • android:hint:提示文字,用户输入后消失
  • android:inputType:输入类型,比如textPasswordnumberphone
  • android:maxLength:最大输入长度
  • android:lines:固定行数,多行输入时用

举个例子,一个密码输入框:

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

避坑指南:我曾经在EditText里设置了android:digits来限制输入字符,结果发现某些输入法会绕过这个限制。后来我改用TextWatcher在代码里过滤,才彻底解决问题。另外,密码输入框别忘了加个“显示/隐藏密码”的切换按钮,用户体验会好很多。

5.2.4 ImageView:图片显示

ImageView用来显示图片。图片可以来自资源文件、网络、本地文件等。

常用属性:

  • android:src:设置图片资源
  • android:scaleType:图片缩放方式(centerCrop、fitCenter、centerInside等)
  • android:adjustViewBounds:是否根据图片比例调整视图大小

举个例子,显示一张本地图片,并裁剪成正方形:

<ImageView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:src="@drawable/my_image"
    android:scaleType="centerCrop"/>

我的建议:scaleType这个属性一定要搞明白。我见过很多人把图片显示得变形,就是因为用了fitXY。如果你想让图片完整显示且不变形,用fitCenter;如果你想裁剪成固定尺寸,用centerCrop。另外,加载网络图片时,建议用Glide或Coil这样的图片加载库,别自己写。

5.3 知识体系总览

为了让你更直观地理解本章的知识结构,我画了一张图:

布局与UI组件(上)知识体系 布局管理器 LinearLayout RelativeLayout ConstraintLayout 常用控件 TextView Button EditText ImageView 核心要点 • 布局选型:简单界面用LinearLayout,复杂界面用ConstraintLayout • 控件使用:注意TextView的ellipsize、EditText的inputType、ImageView的scaleType • 性能优化:减少布局嵌套,避免过度使用RelativeLayout

5.4 本章小结

好了,这一章的内容就这么多。我们讲了三种布局管理器:LinearLayout适合简单线性排列,RelativeLayout适合相对定位,ConstraintLayout是现在的首选。还讲了四个常用控件:TextView显示文字,Button处理点击,EditText接收输入,ImageView展示图片。

这些内容看起来基础,但每一个都有不少细节。我建议你动手写几个界面,把今天讲的属性都试一遍。遇到问题很正常,多查文档、多调试,慢慢就熟练了。

嗯,今天就到这里。下一章我们继续讲布局和控件的进阶内容,包括一些更高级的控件和自定义布局。到时候见。


公众号:蓝海资料掘金营,微信deep3321