5、布局与UI组件(上):布局管理器与常用控件
各位同学,今天我们来聊聊Android开发里最基础、也最绕不开的话题——布局和控件。说白了,你写的每一个界面,都是靠这些东西堆出来的。我刚开始学Android那会儿,觉得布局就是拖拖拽拽,后来才发现,布局选得好不好,直接决定了你后面维护代码的心情。
嗯,咱们今天先讲上半部分:布局管理器和几个最常用的控件。我会把我在项目里踩过的坑、积累的经验,都揉进去讲。
5.1 布局管理器:界面骨架
布局管理器,就是用来摆放控件的容器。Android提供了好几种,我挑三个最常用的讲:LinearLayout、RelativeLayout、ConstraintLayout。这三个你搞明白了,90%的界面都能搞定。
5.1.1 LinearLayout:线性布局
LinearLayout,顾名思义,就是让子控件按一条线排开。要么横着排,要么竖着排。这个布局最简单,也最直观。
核心属性:
android:orientation:设置方向,horizontal或verticalandroid: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_alignParentTop、layout_alignParentBottom、layout_centerInParent等 - 相对于其他控件:
layout_toRightOf、layout_below、layout_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_below和layout_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,结果文字只有几个像素宽,用户点都点不到。我一般会给按钮加个minWidth和minHeight,或者用padding扩大点击区域。
5.2.3 EditText:文本输入
EditText是用户输入文本的控件。它比TextView多了光标、输入法、输入类型等特性。
关键属性:
android:hint:提示文字,用户输入后消失android:inputType:输入类型,比如textPassword、number、phoneandroid: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 知识体系总览
为了让你更直观地理解本章的知识结构,我画了一张图:
5.4 本章小结
好了,这一章的内容就这么多。我们讲了三种布局管理器:LinearLayout适合简单线性排列,RelativeLayout适合相对定位,ConstraintLayout是现在的首选。还讲了四个常用控件:TextView显示文字,Button处理点击,EditText接收输入,ImageView展示图片。
这些内容看起来基础,但每一个都有不少细节。我建议你动手写几个界面,把今天讲的属性都试一遍。遇到问题很正常,多查文档、多调试,慢慢就熟练了。
嗯,今天就到这里。下一章我们继续讲布局和控件的进阶内容,包括一些更高级的控件和自定义布局。到时候见。