Chapter 03 初级UI组件
组件是Android程序设计的基本组成单位,通过使用组件可以高效地开发Android应用程序。所以熟练掌握组件的使用是合理、有效地进行Android程序开发的重要前提。
3.1 文本类组件
Android中提供了一些与文本显示、输入相关的组件,通过这些组件可以显示或输入文字。其中,用于显示文本的组件为文本框组件,用TextView类表示;用于编辑文本的组件为编辑框组件,用EditText类表示。这两个组件最大的区别是TextView类不允许用户编辑文本内容,而EditText类则允许用户编辑文本内容。
TextView组件继承自View,而EditView组件又继承自TextView组件。下面将对这两个组件分别进行介绍。
3.1.1 文本框
在Android中,可以使用两种方法像屏幕中添加文本框:一种是通过在XML布局文件中使用<TextView>标记添加;另一种是在Java文件中,通过new关键字创建。推荐采用第一种方法,也就是通过<TextView>标记在XML布局文件中添加文本框,其基本的语法格式如下:
<TextView
属性列表
>
</TextView>
TextView支持的常用的XML属性如下表所示:
XML属性 | 描述 |
---|---|
android:autoLink | 用于指定是否将指定格式的文本转换成可单击的超链接形式,其属性值有none、web、email、phone、map和all |
android:drawableBottom | 用户在文本框内文本的底部绘制指定图像,该图像可以是放在res\mipmap目录下的图片,通过“@mipmap/文件名(不包含文件的扩展名)”设置 |
android:drawableLeft | 用户在文本框内文本的左侧绘制指定图像,该图像可以是放在res\mipmap目录下的图片,通过“@mipmap/文件名(不包含文件的扩展名)”设置 |
android:drawableStart | 在Android 4.2 中新增的属性,用户在文本框内文本的左侧绘制指定图像,该图像可以是放在res\mipmap目录下的图片,通过“@mipmap/文件名(不包含文件的扩展名)”设置 |
android:drawableRight | 用户在文本框内文本的右侧绘制指定图像,该图像可以是放在res\mipmap目录下的图片,通过“@mipmap/文件名(不包含文件的扩展名)”设置 |
android:drawableEnd | 在Android 4.2 中新增的属性,用户在文本框内文本的右侧绘制指定图像,该图像可以是放在res\mipmap目录下的图片,通过“@mipmap/文件名(不包含文件的扩展名)”设置 |
android:drawableTop | 用户在文本框内文本的顶部绘制指定图像,该图像可以是放在res\mipmap目录下的图片,通过“@mipmap/文件名(不包含文件的扩展名)”设置 |
android:gravity | 用于设置文本框内文本的对齐方式,可选值有top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical和clip_horizontal等。这些属性值也可以同时指定,各属性值之间用竖线“|”隔开。例如,要指定组件靠右下角对齐,可以使用属性值right|bottom |
android:hint | 用于设置当文本框文本内容为空时,默认显示的提示文本 |
android:inputType | 用于指定该文本框显示内容的文本类型,其可选值有textPassword、textEmailAddress、phone和date等,可以同时指定多个,使用“|”分隔 |
android:singleLine | 用于指定该文本框是否为单行模式,其属性值为true或false,为true表示该文本框不会换行,当文本框的文本超过一行时,其超过的部分将被省略,同时在结尾处添加“...” |
android:text | 用于指定该文本框中显示的文本内容,可以直接在该属性值中指定,也可以通过在string.xml文件中定义文本常量的方式指定 |
android:textColor | 用于设置文本框内文本的颜色,其属性值可以是#rgb、#argb、#rrggbb和#aarrggbb格式指定的颜色值 |
android:textSize | 用于设置文本框内文本的字体大小,其属性由代表大小的数值和单位组成,其党委可以是dp、px、pt、sp和in等 |
android:width | 用于指定文本框的宽度,其单位可以是dp、px、pt、sp和in等 |
android:height | 用于指定文本框的高度,其单位可以是dp、px、pt、sp和in等 |
提示:在上表中,只给出了TextView组件常用的部分属性,关于该组件的其他属性,可以参阅Android官方提供的API文档。在下载SDK时,如果已经下载Android API文档,那么可以在已经下载好的SDK文件夹下找到(docs文件夹中的内容即为API文档),否则需要自行下载。下载完成后,打开Android API文档主页(index.html),在Develop/Reference左侧的Android APIs列表中,单击android.widget节点,在下方找到TextView类并单击,在右侧就可以看到该类的相关介绍,其中XML Attributes表格中列出的就是该类的全部属性。
下面通过一个小例子(模拟福卡排行榜列表)进行演示:
布局文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="130dp"
android:layout_marginTop="350dp"/>
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="130dp"
android:layout_marginTop="85dp"/>
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="130dp"
android:layout_marginTop="85dp"/>
<TextView
android:id="@+id/text4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="130dp"
android:layout_marginTop="85dp"/>
<TextView
android:id="@+id/text5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="130dp"
android:layout_marginTop="85dp"/>
<TextView
android:id="@+id/text6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="130dp"
android:layout_marginTop="85dp"/>
</LinearLayout>
MainActivity内容如下:
public class MainActivity extends AppCompatActivity {
private int[] text_Id = {
R.id.text1, R.id.text2, R.id.text3,
R.id.text4, R.id.text5, R.id.text6
};
private String[] text_String = {
"巴拉巴拉一大堆", "小可",
"鞋盒宝宝", "昭仪", "2047", "流浪的风"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.initView();
}
private void initView() {
for(int i = 0; i < text_Id.length; i++) {
TextView textView = findViewById(text_Id[i]);
textView.setText(text_String[i]);
}
}
}
3.1.2 编辑框
通过<EditText>标记在XML布局文件中添加编辑框的基本语法如下:
<EditText
属性列表
>
</EditText>
由于EditText类时TextView的子类,所以上表中TextView支持的XML属性,同样是用于EditText属性,同样适用于EditText组件中,android:inputType属性可以控制输入框的显示类型。例如,要添加一个密码框,可以将android:inputType属性设置为textPassword。
在屏幕中添加编辑框后,还需要获取编辑框中输入的内容,这可以通过编辑框提供的getText()方法实现。使用该方法时,先要获取编辑框组件,然后再调用getText()方法。例如,要获取布局文件中添加的id属性为login的编辑框的内容,可以通过以下代码实现:
EditText login = (EditText) findViewById(R.id.LOGIN);
String loginText = login.getText().toString();
下面编写一个小例子(QQ空间说说界面)进行演示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EAEAEA"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="10"
android:hint="说点什么吧..."
android:padding="5dp"
android:background="#FFFFFF"
android:gravity="top"
android:layout_marginBottom="10dp"
android:inputType="textMultiLine"/>
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@mipmap/addpicture"
android:text="添加图片"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:padding="8dp"
android:background="#FFFFFF"
android:textColor="#767676"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="地点 >"
android:background="#FFFFFF"
android:padding="8dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="权限设置"
android:gravity="center_vertical"
android:background="#FFFFFF"
android:layout_marginTop="10dp"
android:padding="8dp"/>
</LinearLayout>
3.2 按钮类组件
在Android中,提供了一些按钮类的组件,主要包括普通按钮、图片按钮、单选按钮和复选框等。其中,普通按钮使用Button类表示,用于触发一个指定的事件;图片按钮ImageButton类表示,也用于触发一个指定的事件,只不过该按钮以图像来表现;单选按钮使用RadioButton类表示;复选框使用CheckBox表示。这两个组件最大的区别是在一组RadioButton中,只有一个被选中,而在一组CheckBox中,则可以同时选中多个。
Button组件继承自TextView,而ImageButton组件继承自ImageView组件,所以这两个组件在添加上不同,但是作用相同,都可以触发一个事件;RadioButton和CheckBox都间接继承自Button,都可以直接使用Button支持的属性和方法,所不同的是它们都比Button多了可选中的功能。下面将对4个按钮类组件分别进行介绍。
3.2.1 普通按钮
在Android手机应用中,按钮应用十分广泛,例如,QQ登录界面中的“登录”按钮。
通过<Button>标记在XML布局文件中添加普通按钮的基本格式如下:
<Button
android:id="@+id/ID号"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示文本">
</Button>
说明:Button继承自TextView的子类,所以TextView支持的属性,Button都是支持的。
例如,在屏幕中添加一个“开始游戏”的按钮,代码如下:
<Button
android:id="@+id/start
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始游戏">
</Button>
在屏幕上添加按钮后,还需要为按钮添加单击事件监听器,这样才能让按钮发挥其特有的用途。Android提供了两种为按钮添加单击事件监听器的方法:一种是在Java代码中完成,例如,在Activity的onCreate()方法中添加如下代码:
Button login = (Button) findViewById(r.id.login);
login.setOnClickListener(new View.OnCLickListener() {
@Override
public void onClick() {
//编写要执行的代码
}
)};
说明:监听器类似于安防系统中安装的红外线报警器。安装了红外线报警器后,当有物体阻断红外线光束时,就会自动报警。同理,当我们为组件设置监听器后,如果有动作触发该监听器,那么旧执行监听器中编写的代码。例如,为按钮设置一个单击事件监听器,那么单击这个按钮时,就会触发这个监听器,从而执行一些操作(如弹出一个对话框)。
另一种是在Activity中编写一个包含View类型参数的方法,并且将要触发的动作代码放在该方法中,然后在布局文件中,通过android:onClick属性指定对应的方法名实现。例如,在Activity中编写一个名为myClick()的方法,关键打码如下:
public void myClick(View v) {
//编写要执行的动作
}
那么就可以在布局文件中通过android:onClick="myClick"语句为按钮添加单击事件监听器。
下面编写一个小例子(模拟微信登录界面)进行演示:
布局文件activity_main.xml如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/head"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@mipmap/girlhead"
android:layout_centerHorizontal="true"
android:layout_marginTop="150dp"/>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="账 号:"
android:textSize="24sp"
android:layout_below="@+id/head"
android:layout_marginTop="20dp"
android:layout_marginLeft="50dp" />
<EditText
android:id="@+id/editView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="QQ号/手机号"
android:layout_below="@+id/head"
android:layout_alignBottom="@+id/textView1"
android:layout_toRightOf="@id/textView1"
android:layout_marginLeft="10dp"
android:layout_marginRight="50dp"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密 码:"
android:textSize="24sp"
android:layout_below="@+id/textView1"
android:layout_marginTop="5dp"
android:layout_marginLeft="50dp" />
<EditText
android:id="@+id/editView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
android:layout_alignBottom="@+id/textView2"
android:layout_toRightOf="@id/textView2"
android:layout_marginLeft="10dp"
android:layout_marginRight="50dp"/>
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"
android:onClick="onLogin"
android:layout_centerHorizontal="true"
android:layout_below="@+id/textView2"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"/>
<!-- 提示文本框 -->
<TextView
android:id="@+id/notice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/button1"
android:textColor="#FFFFFFFF"
android:background="#22000000"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"/>
</RelativeLayout>
MainActivity.java文件内容如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onLogin(View v) {
TextView textView = findViewById(R.id.notice);
textView.setText("您单击了登录按钮!");
}
}
3.2.2 图片按钮
在Android手机应用中,图片按钮应用也很常见,例如,开心消消乐游戏的开始游戏界面中的“开始游戏”和“切换账号”。
图片按钮与普通按钮的使用方法基本相同,只不过图片按钮使用<ImageButton>标记定义,并且可以为其设置android:src属性,用于设置要显示的图片。在布局文件中添加图片按钮的基本语法格式如下:
<ImageButton
android:id="@+id/ID号"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@mipmap/图片文件名"
android:scaleType="缩放方式">
</ImageButton>
重要属性说明如下:
- android:src属性:用于指定按钮上显示的图片。
- android:scaleType属性:用于指定图片的缩放方式,其属性值如下表所示:
属性值 | 描述 |
---|---|
matrix | 使用matrix方式进行缩放 |
fitXY | 对图片横向、纵向独立缩放,使得该图片完全适应于该ImageButton,图片的纵横比可能会改变 |
fitStart | 保持纵横比缩放图片,直到该图片能完全显示在ImageButton中,缩放完成后该图片放在ImageButton的左上角 |
fitCenter | 保持纵横比缩放图片,直到该图片能完全显示在ImageButton中,缩放完成后的图片放在ImageButton的中间 |
fitEnd | 保持纵横比缩放图片,直到该图片能完全显示在ImageButton中,缩放完成后的图片放在ImageButton的右下角 |
center | 把图片放在ImageButton的中间,但不进行任何缩放 |
centerCrop | 保持纵横比缩放图片,使图片能完全覆盖ImageButton |
centerInside | 保持纵横比缩放图片,使ImageButton能完全显示该图片 |
同普通按钮一样,也需要为图片按钮添加单击事件监听器,具体添加方法同普通按钮。下面通过一个小例子(开心消消乐的“开始按钮”和“切换账号”按钮)进行演示:
布局文件activity_main.xml代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="bottom|center_horizontal"
android:paddingBottom="20dp"
android:background="@mipmap/bg"
tools:context=".MainActivity">
<TextView
android:id="@+id/notice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#AA000000"
android:textSize="32sp"
android:textColor="#FFFF0000"
android:textStyle="bold"/>
<ImageView
android:id="@+id/start"
android:layout_width="200dp"
android:layout_height="150dp"
android:src="@mipmap/bt_start"
android:onClick="onClick"/>
<ImageView
android:id="@+id/switchButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/bt_switch"
android:layout_marginTop="10dp"/>
</LinearLayout>
MainActivity.java文件内容如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View v) {
TextView textView = findViewById(R.id.notice);
textView.setText("你单击了开始游戏按钮!");
}
}
3.3 图像类组件
Android提供了比较丰富的图像类组件。用于显示图像的组件称为图像视图组件,用ImageView表示;用于按照行、列的方式来显示多个元素(如图片、文字等)的组件称为网格视图,用GridView表示。
3.3.1 图像视图
图像组件(ImageView)用于在屏幕中显示任何Drawable对象,通常用来显示图片。例如,美图秀秀的美化图片界面中显示的图片,以及有道词典的主界面中的图片。
说明:在使用ImageView组件显示图像时,通常需要将要显示的图片放置在res\drawable或者res\mipmap目录中。
在布局文件中添加图像视图,可以使用<ImageView>标记来实现,具体的语法格式如下:
<ImageView
属性列表
>
</ImageView>
ImageView组件支持的常用XML属性如下表所示:
XML属性 | 描述 |
---|---|
android:adjustViewBounds | 用于设置ImageView组件是否通过调整自己的边界来保持所显示图片的长宽比 |
android:maxHeight | 设置ImageView组件的最大高度,需要设置android:adjustViewBounds属性值为true,否则不起作用 |
android:maxWidth | 设置ImageView组件的最大宽度,需要设置android:adjustViewBounds属性值为true,否则不起作用 |
android:scaleType | 用于设置所显示的图片如何缩放或移动以适应ImageView的大小,其属性值可以是:matrix、fitXY、fitStart、fitCenter、fitEnd、center、centerCrop、centerInside |
android:src | 设置ImageView所显示的Drawable对象的ID,例如,设置显示保存在res\drawable目录下的名称为flower.jpg的图片,可以将属性值设置为android:src="@drawable/flower" |
android:tint | 用于为图片着色,其属性值可以是#rgb、#argb、#rrggbb或#aarrggbb表示的颜色值 |
3.3.2 网格视图
网格视图(GridView)是按照行、列分布的方式来显示多个组件,通常用于显示图片或图标等。例如,QQ相册相片预览界面。
在使用网格视图时,需要在屏幕上添加GridView组件,通常在XML布局文件中使用标记实现,其基本语法如下:
<GridView
属性列表
>
</GridView>
XML属性 | 描述 |
---|---|
android:columnWidth | 用于设置列的宽度 |
android:gravity | 用于设置对齐方式 |
android:horizontalSpacing | 用于设置各元素之间的水平间距 |
android:numColumns | 用于设置列数,其属性值通常为大于1的值,如果只有1列,那么最好使用ListView实现 |
android:stretchMode | 用于设置拉伸模式,其中属性值可以是none(不拉伸)、spacingWidth(仅拉伸元素之间的间距)、columnWidth(仅拉伸表格元素本身)或spacingWidthUniform(表格元素本身、元素之间的间距一起拉伸) |
android:verticalSpacing | 用于设置个元素之间的垂直间距 |
在使用GridView组件时,通常使用Adapter类为GridView组件提供数据。
Adapter类是一个接口,代表适配器。它是组件与数据之间的桥梁,通过它可以处理数据并将其绑定到相应的组件上,它的常用实现类包括以下几个:
- ArrayAdapter:数组适配器,通常用于将数组的多个值包装成多个列表项,只能显示一行文字。
- SimpleaAdapter:简单适配器,通常用于将List集合的多个值包装成多个列表项。可以自定义各种效果,功能强大。
- SimpleCursorAdapter:与SimpleAdapter类似,只不过它须将Cursor(数据库的游标对象)的字段与组件ID对应,从而实现将数据库的内容以列表形式展示出来。
- BaseAdapter:是一个抽象类,继承它需要实现较多的方法,通常它可以对各列表项进行最大限度的定制,也具有很高的灵活性。
下面编写一个小例子(手机QQ相册)进行演示:
布局文件activity_main.xml内容如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<!-- 标题栏 -->
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/qqxiang"
android:scaleType="fitXY"/>
<!-- 年日月 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="2024 年 4 月 26 日"/>
<!-- 网格布局 -->
<GridView
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="100dp"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="5dp">
</GridView>
</LinearLayout>
MainActivity.java内容如下:
public class MainActivity extends AppCompatActivity {
private Integer[] picture = {
R.mipmap.img01, R.mipmap.img02, R.mipmap.img03, R.mipmap.img04,
R.mipmap.img05, R.mipmap.img06, R.mipmap.img07, R.mipmap.img08,
R.mipmap.img09, R.mipmap.img10, R.mipmap.img11, R.mipmap.img12
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridView = (GridView) findViewById(R.id.gridView); //获取布局文件中的GridView组件
gridView.setAdapter(new ImageAdapter(this));
}
public class ImageAdapter extends BaseAdapter {
private Context mContext; //获取上下文
public ImageAdapter(Context context) {
mContext = context;
}
@Override
public int getCount() {
return picture.length; //图片数组的长度
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if(convertView == null) { //判断传过来的值是否为空
imageView = new ImageView(mContext); //创建ImageView组件
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.width = 100;
params.height = 90;
imageView.setLayoutParams(params); //设置宽高
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); //设置铺设方式
}
else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(picture[position]); //将获取图片方法放到ImageView组件中
return imageView; //返回ImageView
}
}
}