Android开发详解:第4章《UI 控件》
控件是Android程序设计的基本组成单位,通过使用控件可以高效地开发Android应用程序。所以熟练掌握控件的使用是合理、有效地进行Android程序开发的重要前提。本章将对Android中提供的初级控件进行详细介绍。
View家族的继承关系图
4.1 文本类控件
Android中提供了一些与文本显示、输入相关的控件,通过这些控件可以显示或输入文字。其中,用于显示文本的控件为文本框控件,用 TextView 类表示;用于编辑文本的控件为编辑框控件,用 EditText 类表示。这两个控件最大的区别是 TextView 类不允许用户编辑文本内容,而 EditText 类则允许用户编辑文本内容。
从关系图中可以看出:TextView控件继承自View,而EditText控件又继承自TextView控件。下面将对这两个控件分别进行介绍。
文本框【TextView】
在Android中,可以使用两种方法向屏幕中添加文本框:一种是通过在XML布局文件中使用就是通过属性列表。
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 | 用于指定该文本框中显示的文本内容,可以直接在该属性值中指定,也可以通过在 strings.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 表格中列出的就是该类的全部属性。
对于文本框控件,默认为多行文本框,也可以设置为单行文本框,只需要将 android:singleLine 属性设置为 ture 就可以显示为单行文本框。
编辑框【EditView】
<EditView></EditView>
由于 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();
自动完成文本框【AutoCompleteTextView】
<AutoCompleteTextView></AutoCompleteTextView>
AutoCompleteTextView 是 EditText 的子类,从外表上看它就是一个普通的编辑框控件,其实它内在的功能是在用户输入一定的字符时,该控件会显示一个下拉列表。在这个列表中用户单击需要的字符,该字符将自动填写在编辑框中。
AutoCompleteTextView支持的XML属性及描述
XML属性 | 描述 |
android:completionHint | 设置下拉菜单中显示的提示 |
android:completionHintView | 设置下拉菜单中显示的提示视图 |
android:completionThreshold | 设置用户至少输入几个字符才显示提示列表 |
android:dropDownAnchor | 设置提示列表显示在某个控件的下面,值为某控件的ID |
android:dropDownHeight | 设置下拉列表的高度 |
android:dropDownHorizontalOffset | 设置下拉列表与文本框之间的水平偏移,下拉菜单默认与文本框左对齐 |
android:dropDownSelector | 设置下拉列表选择器的背景 |
android:dropDownVerticalOffset | 设置下拉列表与文本框之间的垂直偏移,下拉菜单默认在文本框下面 |
android:dropDownWidth | 设置下拉列表的宽度 |
android:popupBackground | 设置下拉列表的背景 |
AutoCompleteTextView 控件的用法其实很简单,只需要为它设置一个 Adapter 适配器,并在该适配器中添加 AutoCompleteTextView 提示列表中显示的文本信息即可。
下面通过一个具体的实例演示自动完成文本框 AutoCompleteTextView 的应用。
例:模拟淘宝搜索宝贝时的提示列表
【数组适配器 ArrayAdapter 为 AutoCompleteTextView 提供数据】
在 Android Studio 中创建 Module,名称为【Auto Complete TextView】,实现本实例的具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为相对布局管理器并将 TextView 控件删除,然后为布局管理器设置背景图片,最后添加一个 AutoCompleteTextView 控件用于显示淘宝搜索宝贝时的提示列表。activity_main.xml具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg"
tools:context=".MainActivity">
<!--添加自动完成文本框-->
<AutoCompleteTextView
android:id="@+id/at"
android:layout_width="150dp"
android:layout_height="40dp"
android:layout_centerHorizontal="true"
android:background="@null"
android:dropDownWidth="match_parent" />
</RelativeLayout>
(2) 打开主活动 MainActivity.java 文件,修改默认生成的代码:
package com.so.autocompletetextview;
import android.app.Activity;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
//(2) 直接继承Activity,并导入android.app.Activity类
public class MainActivity extends Activity {
//(3) 创建一个名称为 book 并且是 String 类型的数组,该数组用于显示列表中的书名
private static final String[] book = new String[]{
"Android 入门到精通", "Android 开发实战", "Android 范例宝典"
, "Android 精彩编程200例", "Android 项目开发|实战入门"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//(4) 设置全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//(5) 获取布局文件中的 AutoCompleteTextView 控件
AutoCompleteTextView autoCompleteTextView = findViewById(R.id.at);
//(6) 创建一个数组适配器
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_dropdown_item_1line, book);
//(7) 为 AutoCompleteTextView 控件设置数组适配器
autoCompleteTextView.setAdapter(adapter);
}
}
(8) 运行本实例,将显示如图所示的界面。输入关键字“An”将显示如图所示的界面。
文本切换器【TextSwitcher】
<TextSwitcher></TextSwitcher>
TextSwitcher 是 ViewSwitcher 的子类,它与 ImageSwitcher 很相似,都需要设置一个ViewFactory,并且都可以设置切换时所显示的动画效果。不同的是 TextSwitcher 在实现 ViewFactory 接口中的 makeView() 方法时,需要返回一个 TextView 控件。文本切换器可以用来实现一个通过垂直滚动的动画显示唐诗中的文字。
文本切换器支持的XML属性及说明
XML属性 | 说明 |
android:inAnimation | 设置文本进入时的动画文件 |
android:outAnimation | 设置文本退出时的动画文件 |
下面通过一个具体的实例演示文本切换器的具体应用。
例:单击屏幕滚动切换每句唐诗
在 Android Studio 中创建 Module,名称为【Text Switcher】,具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为相对布局管理器并将TextView控件删除,然后为布局管理器设置背景图片,最后添加一个 TextSwitcher 控件用于实现切换每句唐诗。activity_main.xml具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg"
tools:context=".MainActivity">
<TextSwitcher
android:id="@+id/textSwitcher"
android:layout_width="260dp"
android:layout_height="100dp"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
android:inAnimation="@android:anim/slide_in_left"
android:outAnimation="@android:anim/slide_out_right" />
</RelativeLayout>
说明:在 XML 文件中设置 TextSwitcher 控件时,需要指定文字切换时进入与退出的动画文件,如代码中的 "anim/in_animation" 表示文字切换时的进入动画文件,"anim/out_animation" 表示文字切换时的退出动画文件。这两个动画文件需要手动创建。
(2) 打开主活动MainActivity.java 文件,修改默认生成的代码:
package com.so.textswitcher;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher;
//直接继承 Activity 类
public class MainActivity extends Activity {
private TextSwitcher textSwitcher;//定义文本切换器
private int index;//定义用于计算诗句数组下标
private String[] poetry = new String[]{//定义数据数组
"望庐山瀑布",
"[作者] 李白",
"日照香炉生紫烟",
"遥看瀑布挂前川",
"飞流直下三千尺",
"疑似银河落九天"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//获取TextSwitcher控件
textSwitcher = findViewById(R.id.textSwitcher);
//为控件设置数据工厂
textSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
@Override
public View makeView() {
//创建文本框用于显示诗句
TextView textView = new TextView(MainActivity.this);
textView.setTextSize(30);//字体大小
textView.setTextColor(Color.RED);//字体颜色
return textView;
}
});
}
/**
* 重写触摸事件
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
//判断手指单机屏幕时
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//切换显示得我诗句
textSwitcher.setText(poetry[index++ % poetry.length]);
}
return super.onTouchEvent(event);
}
}
(3) 运行本资例,将显示如图所示的背景图片,单击手机或模拟器屏幕,会显示下一条诗句
4.2 按钮类控件
在Android中,提供了一些按钮类的控件,主要包括:
- 普通按钮【Button】用于触发一个指定的事件,继承自 TextView
- 图片按钮【 ImageButton】用于触发一个指定的事件,继承自 ImageView
- 单选按钮【RadioButton】用于单选,间接继承自 Button
- 复选框使用【CheckBox】用于多选,间接继承自 Button
普通按钮【Button】
<Button></Button>
由于 Button 是 TextView 的子类,所以凡是 TextView 支持的属性,Button 都是支持的
在屏幕上添加按钮后,还需要为按钮添加单击事件监听器,才能让按钮发挥其特有的用途。Android提供了两种为按钮添加单击事件监听器的方法,一种是在Java代码中完成,例如,在Activity 的 onCreate() 方法中添加如下代码:
btn = findViewById(R.id.b);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//编写要执行的动作
}
});
说明:监听器类似于安防系统中安装的红外线报警器。安装了红外线报警器后,当有物体阻断红外线光束时,就会自动报警。同理,当我们为控件设置监听器后,如果有动作触发该监听器,那么就执行监听器中编写的代码。例如,为按钮设置一个单击事件监听器,那么单击这个按钮时,就会触发这个监听器,从而执行一些操作(如弹出一个对话框)。
另一种是在 Activity 中编写一个包含 View 类型参数的方法,并且将要触发的动作代码放在该方法中,然后在布局文件中,通过 android:onClick 属性指定对应的方法名实现。例如,在Activity 中编写一个名为 myClick() 的方法,关键代码如下:
public void myClick(View view){
//此处编写要执行的动作代码
}
那么就可以在布局文件中通过 android:onClick="myClick" 语句为按钮添加单击事件监听器。
图片按钮【ImageButton】
图片按钮与普通按钮的使用方法基本相同,只不过图片按钮使用且可以为其指定 android:src 属性,用于设置要显示的图片。在布局文件中添加图片按钮的基本语法格式如下:
<ImageButton
android:id="@+id/id1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:src="@drawable/ic_launcher_foreground">
</ImageButton>
属性说明:
- ◆ android:src 属性:用于指定按钮上显示的图片
- ◆ android:scaleType 属性:用于指定图片的缩放方式
android:scaleType 属性的属性值及说明
属性值 | 说 明 |
matrix | 使用matrix方式进行缩放 |
fitXY | 对图片横向、纵向独立缩放,使得该图片完全适应于该 ImageButton,图片的纵横比可能会改变 |
fitStart | 保持纵横比缩放图片,直到该图片能完全显示在 ImageButton 中,缩放完成后该图片放在 ImageButton 的左上角 |
fitCenter | 保持纵横比缩放图片,直到该图片能完全显示在 ImageButton 中,缩放完成后该图片放在 ImageButton 的中间 |
fitEnd | 保持纵横比缩放图片,直到该图片能完全显示在 ImageButton 中,缩放完成后该图片放在 ImageButton 的右下角 |
center | 把图像放在 ImageButton 的中间,但不进行任何缩放 |
centerCrop | 保持纵横比缩放图片,使图片能完全覆盖 ImageButton |
centerInside | 保持纵横比缩放图片,使 ImageButton 能完全显示该图片 |
说明:如果在添加图片按钮时,不为其设置 android:background 属性,那么作为按钮的图片将显示在一个灰色的按钮上,也就是说所添加的图片按钮,将带有一个灰色立体的边框。不过这时的图片按钮,将会随着用户的动作而改变。一旦为其设置了 android:background 属性后,它将不会随着用户的动作而改变。如果要让其随着用户的动作而改变,就需要使用 StateListDrawable 资源来对其进行设置。
注意:在设置控件ID时,不能使用Java关键字。例如上面代码中,就不能把ID属性值设置为@+id switch,否则将出现资源名不能使用Java关键字(Resource name cannot be a Java keyword...)的错误。
状态开关按钮【Switch】
<Switch></Switch>
状态开关按钮 Switch 也是由 Button 派生出来的,所以在本质上它也算是一个比较高级的按钮,用户可以来回拖动“拇指”控制该按钮的开启与关闭,或者只需轻按,就像选择复选框一样来开启该控件。在 Android 中,该控件经常被使用到 App 的设置界面中。
Switch支持的XML属性及说明
XML属性 | 说明 |
android:switchMinWidth | 设置开关控件的最小宽度 |
android:switchPadding | 设置开关控件与左侧标题文本之间的距离 |
android:switchTextAppearance | 设置开关控件标题文本的样式 |
android:textOff | 设置开关控件关闭时显示的文本 |
android:textOn | 设置开关控件开启时显示的文本 |
android:showText | 是否显示该控件打开或关闭时所显示的文本 |
android:textStyle | 设置开关控件的文本风格 |
android:thumb | 指定该控件切换开关的图标 |
android:track | 指定该控件开关滑动的轨道 |
由于状态开关在使用时无法确定当前开关处于开启或者是关闭的状态,所以需要为该控件设置一个事件监听器:setOnCheckedChangeListener()
下面通过一个具体的实例演示状态开关(Switch)的具体应用。
例:模拟微信通用界面中开启横屏模式的开关
在 Android Studio 中创建 Module,名称为【Status Switch】,实现本实例的具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为相对布局管理器并将 TextView 控件删除,然后为布局管理器设置背景图片,最后添加一个 Switch 控件用于实现开启横屏模式的开关。activity_main.xml具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/ic_launcher"
tools:context=".MainActivity">
<Switch
android:id="@+id/sw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="13dp"
android:layout_marginTop="75dp"
android:switchPadding="170dp"
android:text="开启横屏模式"
android:textColor="#000000" />
</RelativeLayout>
(2) 打开主活动 MainActivity.java 文件,修改默认生成的代码,让 MainActivity 直接继承 Activity,并导入 android.app.Activity 类,然后在 onCreate() 方法中添加设置当前 Activity 全屏的代码。修改后的具体代码如下:
package com.so.statusswitch;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.Toast;
//直接继承 Activity
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//获取状态开关
Switch sw = findViewById(R.id.sw);
//给开关设置监听器
sw.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (sw.isChecked()) {//如果被选中
Toast.makeText(MainActivity.this, "开启横屏模式", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "关闭横屏模式", Toast.LENGTH_SHORT).show();
}
}
});
}
}
(3) 运行本实例,将显示如图所示的界面效果。
单选按钮【RadioButton】
<RadioButton></RadioButton>
在默认情况下,单选按钮显示为一个圆形图标,并且在该图标旁边放置一些说明性文字。在程序中,一般将多个单选按钮放置在按钮组中,使这些单选按钮表现出某种功能,当用户选中某个单选按钮后,按钮组中的其他按钮将被自动取消选中状态。在 Android 手机应用中,单选按钮应用也十分广泛。例如,在使用陌陌社交工具注册新用户填写基本资料时,填写基本资料界面中的选择性别单选按钮。
RadioButton 控件的 android:checked 属性用于指定选中状态,属性值为 true 时,表示选中;属性值为 false 时,表示取消选中,默认为 false。
通常情况下,RadioButton 控件需要与 RadioGroup 控件一起使用,组成一个单选按钮组
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RadioGroup>
在屏幕中添加单选按钮组后,还需要获取单选按钮组中选中项的值,通常存在以下两种情况:
◆ 在改变单选按钮组的值时获取
在改变单选按钮组的值时获取选中的单选按钮的值,首先需要获取单选按钮组,然后为其添加 OnCheckedChangeListener,并在其 onCheckedChanged() 方法中根据参数 checkedld 获取被选中的单选按钮,可以通过下面的代码实现:
//获单选按钮组控件对象
RadioGroup radioGroup = findViewById(R.id.rg);
//给单选组对象设置单机改变事件监听器
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
//此处的 checkedId 就是被选中的单选框下标,通过它获取被选中的单选框对象
RadioButton button = findViewById(checkedId);
button.getText();//获取被选择测单选框文本
}
});
◆ 单击其他按钮时获取
单击其他按钮时获取选中项的值时,首先需要在该按钮的单击事件监听器的 onClick() 方法中,通过 for 循环语句遍历当前单选按钮组,并根据被遍历到的单选按钮的 isChecked() 方法判断该按钮是否被选中,可以通过下面的代码实现:
//获单选按钮组控件对象
RadioGroup radioGroup = findViewById(R.id.rg);
//获取提交按钮控件对象
Button button = findViewById(R.id.bt);
//给提交按钮添加监听事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//循环单选按组
for (int i = 0; i < radioGroup.getChildCount(); i++) {
//获取单选按钮
RadioButton radioButton = (RadioButton) radioGroup.getChildAt(i);
if (radioButton.isChecked()) {//判断当前按钮被选中
radioButton.getText();//获取被选中的单选按钮文本
break;//跳出结束循环
}
}
}
});
例:逻辑推理题
在 Android Studio 中创建 Module,名称为【Radio Button】。实现本实例的具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为垂直线性布局管理器,activity_main.xml关键代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="你是很靓仔吗?"
android:textSize="16sp" />
<RadioGroup
android:id="@+id/rg"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/rb_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="是的" />
<RadioButton
android:id="@+id/rb_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="不是" />
<RadioButton
android:id="@+id/rb_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="不确定" />
</RadioGroup>
<Button
android:id="@+id/bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提交" />
</LinearLayout>
(2) 在主活动 MainActivity 的 onCreate() 方法中,获取提交按钮并为其添加单击事件监听器。在按钮的单击事件监听器的 onClick() 方法中,通过for循环语句遍历当前单选按钮组,并根据被通方法获取对应的值,并且将获取的值与正确答案的值进行比较,关键代码如下:
package com.so.radiobutton;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Button bt;//声明提交按钮对象
private RadioGroup rg;//声明单选按钮组对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = findViewById(R.id.bt);//获取提交按钮控件对象
rg = findViewById(R.id.rg);//获单选按钮组控件对象
bt.setOnClickListener(new View.OnClickListener() {//为提交按钮设置点击监听器
@Override
public void onClick(View v) {
for (int i = 0; i < rg.getChildCount(); i++) {//循环获取所有单选按钮组数据
//根据索引获取单选按钮
RadioButton radioButton = (RadioButton) rg.getChildAt(i);
if (radioButton.isChecked()) {//如果当前单选按钮被选中
if ("是的".contentEquals(radioButton.getText())) {//如果选中的是"是的"
//显示消息提示用户
Toast.makeText(MainActivity.this, "回答正确", Toast.LENGTH_SHORT).show();
} else {
//错误消息提示框
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("在我心目中你是最靓的靓仔!");
builder.setPositiveButton("确定", null).show();
break;//跳出并结束循环
}
}
}
}
});
}
}
(3)运行本实例,将显示如图所示的界面。
复选框【CheckBox】
<CheckBox></CheckBox>
在默认情况下,复选框显示为一个方块图标,并且在该图标旁边放置一些说明性文字。与单选按钮唯一不同的是,复选框可以进行多选设置,每一个复选框都提供“选中”和“不选中”两种状态。在 Android 手机应用中,复选框控件的应用也十分广泛。
由于使用复选框可以选中多项,所以为了确定用户是否选择了某一项,还需要为每一个选项添加事件监听器:
//获取复选框对象
CheckBox checkBox = findViewById(R.id.checkbox1);
//给复选框添加被选中监听事件
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (checkBox.isChecked()) {//如果被选中
checkBox.getText();//获取文本
}
}
});
下面通过一个实例来演示复选框的应用。
例:模拟12306车票预订
在 Android Studio 中创建 Module,名称为【Check Box】。实现本实例的具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为相对布局管理器,然后添加两个 CheckBox 复选框控件与一个 Button 按钮控件,activity_main.xml关键代码如下:
<?xml version="1.0" encoding="utf-8"?>
<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">
<CheckBox
android:id="@+id/checkbox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/checkbox2"
android:layout_alignRight="@+id/checkbox2"
android:layout_alignParentBottom="true"
android:layout_marginEnd="69dp"
android:layout_marginRight="69dp"
android:layout_marginBottom="258dp"
android:scaleX="0.9"
android:scaleY="0.9"
android:text="学生"
android:textColor="#000000" />
<CheckBox
android:id="@+id/checkbox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginTop="51dp"
android:layout_marginEnd="22dp"
android:layout_marginRight="22dp"
android:scaleX="0.9"
android:scaleY="0.9"
android:text="兑换车次"
android:textColor="#000000" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/checkbox2"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="15dp"
android:layout_marginTop="25dp"
android:layout_marginRight="15dp"
android:background="@mipmap/ic_launcher"
android:onClick="onClick"
android:text="查询"
android:textSize="18sp" />
</RelativeLayout>
(2) 在主活动 MainActivity 中,定义两个复选框并且在 onCreate() 方法中获取这两个复选框控件,代码如下:
package com.so.checkbox;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
//声明两个复选框
private CheckBox checkBox1, checkBox2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//获取并初始化两个复选框对象
checkBox1 = findViewById(R.id.checkbox1);
checkBox2 = findViewById(R.id.checkbox2);
}
//定义按钮单击事件
public void onClick(View view) {
String checked = "";
if (checkBox1.isChecked()) {//如果第一个被选中,追加文本信息保存
checked += checkBox1.getText().toString();
}
if (checkBox2.isChecked()) {//如果第二个被选中,追加文本信息保存
checked += checkBox2.getText().toString();
}
if ("".equals(checked)) {//内容为空时提示消息
Toast.makeText(MainActivity.this, "请选择复选框内容", Toast.LENGTH_SHORT).show();
} else {//不为空时显示被选中的消息
Toast.makeText(MainActivity.this, checked, Toast.LENGTH_SHORT).show();
}
}
}
(3) 运行本实例,将显示如图所示的界面。
4.3 图像类控件
在Android中,提供了比较丰富的图像类控件。用于显示图像的控件称为图像视图控件,用ImageView 表示;用于按照行、列的方式来显示多个元素(如图片、文字等)的控件称为网格视图,用 GridView 表示。它们的继承关系如图所示。
- 图像视图【ImageView】控件继承自View,它主要用于呈现图像
- 网格视图【GridView】控件间接继承自AdapterView控件,可以包括多个列表项,并且可以通过合适的方式显示
说明:AdapterView是一个抽象基类,它继承自ViewGroup,属于容器,可以包括多个列表项,并且可以通过合适的方式显示。在指定多个列表项时,可以使用Adapter对象提供。
图像视图【ImageView】
用于在屏幕中显示任何Drawable对象,通常用来显示图片。在使用ImageView控件显示图像时,通常需要将要显示的图片放置在 res/drawable 或者 res/mipmap 目录中。
在布局文件中添加图像视图,可以使用
<ImageView></ImageView>
ImageView控件支持的XML属性及描述
XML属性 | 描 述 |
android:adjustViewBounds | 用于设置ImageView控件是否调整自己的边界来保持所显示图片的长宽比 |
android:maxHeight | 设置ImageView控件的最大高度,需要设置 android:adjustViewBounds 属性值为true,否则不起作用 |
android:max Width | 设置ImageView控件的最大宽度,需要设置android:adjustViewBounds属性值为true,否则不起作用 |
android:scaleType | 用于设置所显示的图片如何缩放或移动以适应ImageView的大小,其属性值可以是: matrix:使用matrix方式进行缩放 fitXY:对图片横向、纵向独立缩放,使得该图片完全适应于该ImageView,图片的纵横比可能会改变 fitStart:保持纵横比缩放图片,直到该图片能完全显示在ImageView中,缩放完成后该图片放在ImageView的左上角 fitCenter:保持纵横比缩放图片,直到该图片能完全显示在ImageView中,缩放完成后该图片放在ImageView的中间 fitEnd:保持纵横比缩放图片,直到该图片能完全显示在ImageView中,缩放完成后该图片放在ImageView的右下角 center:把图像放在ImageView的中间,但不进行任何缩放 centerCrop:保持纵横比缩放图片,以使得图片能完全覆盖ImageView centerInside:保持纵横比缩放图片,以使得ImageView能完全显示该图片 |
android:src | 用于设置ImageView所显示的Drawable对象的ID,例如,设置显示保存在res/drawable目录下的名称为flower.jpg的图片,可以将属性值设置为android:src="@drawable/flower" |
说明:在表中只给出了ImageView控件常用的部分属性,关于该控件的其他属性,可以参阅Android官方提供的API文档。
例:单击 ImageView 更换显示的图像
在Android Studio中创建Module,名称为 ImageView。实现本实例的具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为相对布局管理器,并将默认添加的TextView控件删除,然后在布局管理器中添加一个ImageView控件并设置默认显示的图片与单击事件的方法,activity_main.xml 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<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/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="50dp"
android:background="@drawable/ic_launcher_foreground"
android:onClick="onImageView" />
</RelativeLayout>
(2) 打开MainActivity类,首先定义图像视图控件与图像标记,然后在onCreate()方法中获取图像视图控件,最后创建onImageView()方法,用于实现更换图像,MainActivity.java 代码如下:
package com.so.imageview;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private int i = 2;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.imageView);
}
/**
* 单击图像事件处理方法
* 名称与 ImageView标签中文件中的 android:onClick="onImageView" 一致
* 根据标记更换图片
*
* @param view 视图控件对象
*/
public void onImageView(View view) {
if (i == 2) {
imageView.setImageResource(R.drawable.ic_launcher_background);
i = 1;
} else {
imageView.setImageResource(R.drawable.ic_launcher_foreground);
i = 2;
}
}
}
(3) 运行本实例,将显示如图效果
网格视图【GridView】
网格视图 GridView 是按照行、列分布的方式来显示多个控件,通常用于显示图片或图标等。
GridView控件支持的XML属性及描述
XML属性 | 描 述 |
android:columnWidth | 用于设置列的宽度 |
android:gravity | 用于设置对齐方式 |
android:horizontalSpacing | 用于设置各元素之间的水平间距 |
android:numColumns | 用于设置列数,其属性值通常为大于1的值,如果只有1列,那么最好使用ListView实现 |
android:stretchMode | 用于设置拉伸模式,其中属性值可以是: none:不拉伸 spacingWidth:仅拉伸元素之间的间距 columnWidth:仅拉伸表格元素本身 spacingWidthUniform:表格元素本身、元素之间的间距一起拉伸 |
android:verticalSpacing | 用于设置各元素之间的垂直间距 |
在使用 GridView 控件时,通常使用 Adapter 类为 GridView 控件提供数据。
Apapter 类是一个接口,代表适配器对象。它是控件与数据之间的桥梁,通过它可以处理数据并将其绑定到相应的控件上。它的常用实现类包括以下几个:
- ArrayAdapter:数组适配器,通常用于将数组的多个值包装成多个列表项,只能显示一行文字
- SmipleAdapter:简单适配器,通常用于将List集合的多个值包装成多个列表项,可以自定义各种效果,功能强大
- SmipleCursorAdapter:与SmipleAdapter类似,只不过它需将Cursor(数据库的游标对象)的字段与控件ID对应,从而实现将数据库的内容以列表形式展示出来
- BaseAdapter:是一个抽象类,继承它需要实现较多的方法,通常它可以对各列表项进行最大限度的定制,也具有很高的灵活性
下面通过一个具体的实例演示如何通过BaseAdapter适配器指定内容的方式创建GridView。
match_parent:表示让当前控件的大小和父布局的大小一样,即由父布局来决定当前控件的大小
wrap_content:表示让当前控件的大小刚好能够包含里面的内容,即由控件内容决定当前控件的大小
例:手机QQ相册界面【适配器 Adapter 类为 GridView 控件提供数据】
在 Android Studio 中创建 Module,名称为【QQ Album】。实现本实例的具体步骤如下:
准备图片资源:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为垂直线性布局管理器,然后在 TextView 控件上面添加一个 ImageView,最后在 ImageView 下面添加 ID 为 GridView 的 GridView 控件,并设置其列数为自动排列。修改后的activity_main.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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/qq_title" />
<!--年月日-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="2023年3月23号" />
<!--网格布局-->
<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" />
</LinearLayout>
(2) 创建一个 ImageAdapter 图片适配器,在该适配器中,首先创建一个新的ImageView,然后将图片通过适配器加载到新的 ImageView 中
ImageAdapter 具体代码如下:
package com.so.qqalbum;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
public class ImageAdapter extends BaseAdapter {
private Context mContext;//获取上下文
private Integer[] picture = {//要显示的图片资源ID数组
R.mipmap.img1, R.mipmap.img2, R.mipmap.img3, R.mipmap.img4,
R.mipmap.img5, R.mipmap.img6, R.mipmap.img7, R.mipmap.img8,
R.mipmap.img9, R.mipmap.img10, R.mipmap.img11, R.mipmap.img12
};
public ImageAdapter(Context context) {
this.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) {//判断传过来的值是否为空
Log.i("", "convertView == null, position=" + position);
imageView = new ImageView(mContext);//创建图像控件
imageView.setLayoutParams(new GridView.LayoutParams(100, 90));//为控件设置宽高
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);//选择图片铺设方式
} else {
Log.i("", "convertView != null, position=" + position);
imageView = (ImageView) convertView;
}
imageView.setImageResource(picture[position]);//将获取到的图片放到控件中
return imageView;//返回图片控件
}
}
(3) 打开主活动 MainActivity,修改默认生成的代码,让 MainActivity 直接继承 Activity,并导入 android.app.Activity 类,在主活动的 onCreate() 方法中,获取布局文件中添加的 GridView 控件,并且为其设置适配器,关键代码如下:
package com.so.qqalbum;
import android.app.Activity;
import android.os.Bundle;
import android.widget.GridView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridView = findViewById(R.id.gridView);//获取布局文件中网格布局控件
gridView.setAdapter(new ImageAdapter(this));//设置图片适配器
}
}
(4) 打开AndroidManifest.xml文件,将其中的AppTheme修改为"@style/Theme.AppCompat.Light.DarkActionBar",修改后的 android:theme 属性的代码如下:
android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
(5) 运行本实例,将显示如图所示的界面。
4.4 进度条类控件
在 Android 中,提供了:
- 进度条【ProgressBar】显示某个耗时操作完成的百分比的控件称为进度条控件
- 拖动条【SeekBar】 :允许用户通过拖动滑块来改变值的控件称为拖动条控件
- 星级评分条【RatingBar】:表示进度的控件称为星级评分条
从图可以看出:ProgressBar 控件继承自 View,而 SeekBar 和 RatingBar 控件又间接继承自 ProgressBar 控件。所以对于 ProgressBar 的属性,同样适用于 SeekBar 和 RatingBar 控件。下面将对这3个控件分别进行介绍。
进度条【ProgressBar】
<ProgressBar></ProgressBar>
当一个应用在后台执行时,前台界面不会有任何信息,这时用户根本不知道程序是否在执行以及执行进度等,因此需要使用进度条来提示程序执行的进度。在 Android 中,提供了两种进度条:一种是水平进度条,另一种是圆形进度条。
ProgressBar支持的XML属性及说明
XML属性 | 说明 |
android:max | 用于设置进度条的最大值 |
android:progress | 用于指定进度条已完成的进度值 |
android:progressDrawable | 用于设置进度条轨道的绘制形式 |
除了表介绍的属性外,进度条控件还提供了下面两个常用方法用于操作进度。
- ◆ setProgress(int progress) 方法:用于设置进度完成的百分比。
- ◆ incrementProgressBy(int diff) 方法:用于设置进度条的进度增加或减少。当参数值为正数时,表示进度增加;当参数值为负数时,表示进度减少。
下面编写一个关于在屏幕中使用进度条的实例。
例:模拟“开心消消乐”启动界面
在 Android Studio 中创建 Module,名称为【Horizontal Progress Bar】。实现本实例的具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml,将默认添加的布局管理器修改为相对布局管理器并将 TextView 控件删除,然后添加一个水平进度条,并且将名称为 xxll.jpg 的背景图片复制到 mipmap-mdpi 目录中,activity_main.xml修改后的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:background="@mipmap/ic_launcher"
tools:context=".MainActivity">
<ProgressBar
android:id="@+id/progressBar1"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="60dp"
android:max="100" />
</RelativeLayout>
说明:在上面的代码中,通过 android:max 属性设置水平进度条的最大进度值;通过 style 属性为 ProgressBar 指定风格,常用的 style 属性值如表所示。
ProgressBar的style属性的常用及说明值
XML属性 | 说明 |
?android:attr/progressBarStyleHorizontal | 细水平长条进度条 |
?android:attr/progressBarStyleLarge | 大圆形进度条 |
?android:attr/progressBarStyleSmall | 小圆形进度条 |
@android:style/Widget.ProgressBar.Large | 大跳跃、旋转画面的进度条 |
@android:style/Widget.ProgressBar.Small | 小跳跃、旋转画面的进度条 |
@android:style/Widget.ProgressBar.Horizontal | 粗水平长条进度条 |
(2) 打开主活动 MainActivity,修改默认生成的代码,让 MainActivity 直接继承 Activity,并导入 android.app.Activity 类,然后在 onCreate() 方法中添加设置当前 Activity 全屏的代码。修改后的具体代码如下:
package com.so.horizontalprogressbar;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
public class MainActivity extends Activity {
private ProgressBar horizonP;//声明水平进度条
private int mProgressStatus = 0;//完成进度状态
private Handler mHandler;//处理消息的Handler类对象
@SuppressLint("HandlerLeak")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//获取水平进度条
horizonP = findViewById(R.id.progressBar1);
//初始化Handler消息对象
mHandler = new Handler() {
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(@NonNull Message msg) {
if (msg.what == 0x111) {//0x111为自定义的消息代码
horizonP.setProgress(mProgressStatus);//更新进度
} else {
Toast.makeText(MainActivity.this, "耗时操作已完成",
Toast.LENGTH_SHORT).show();
horizonP.setVisibility(View.GONE);//隐藏进度条
}
super.handleMessage(msg);
}
};
//开启新线程用于模拟耗时操作
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
mProgressStatus = doWork();
Message message = new Message();
if (mProgressStatus < 100) {
message.what = 0x111;
mHandler.sendMessage(message);
} else {
message.what = 0x110;
mHandler.sendMessage(message);
break;//第100次后停止更新工作
}
}
}
//模拟耗时方法
private int doWork() {
mProgressStatus += Math.random() * 10;//给个随机数
try {
Thread.sleep(200);//休眠200ms
} catch (Exception e) {
e.printStackTrace();
}
return mProgressStatus;//返回新的进度
}
}).start();//启动线程
}
}
(3) 运行本实例,将显示如图所示的运行结果。
拖动条【SeekBar】
<SeekBar></SeekBar>
拖动条与进度条类似,所不同的是,拖动条允许用户拖动滑块来改变值,通常用于实现对某种数值的调节。
SeekBar 控件允许用户改变拖动滑块的外观,这可以使用 android:thumb 属性实现,该属性的属性值为一个 Drawable 对象,该 Drawable 对象将作为自定义滑块。
由于拖动条可以被用户控制,所以需要为其添加 OnSeekBarChangeListener 监听器,基本代码如下:
SeekBar seekBar = findViewById(R.id.set_light);
//设置拖动条监听器
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//将正在改变的监听
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//开始改变的监听
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//结束改变ed监听
}
});
在上面的代码中,onProgressChanged()方法中的参数progress表示当前进度,也就是拖动条的值。下面通过一个实例说明拖动条的应用。
例:可以设置屏幕亮度的拖动条
在 Android Studio 中创建 Module,名称为【SeekBar】。实现本实例的具体步骤如下:
(1) 修改新建 Module 的 res/layout 目录下的布局文件 activity_main.xml。首先将默认添加的布局管理器修改为相对布局管理器,并将默认添加的T extView 控件删除;然后添加一个拖动条,activity_main.xml关键代码如下:
<?xml version="1.0" encoding="utf-8"?>
<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">
<SeekBar
android:id="@+id/set_light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true" />
</RelativeLayout>
(2) 创建 BrightnessUtils 类,该类为亮度工具类,代码如下:
package com.so.seekbar;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.provider.Settings;
//亮度工具类
public class BrightnessUtils {
//定义修改亮度的字符串常量
private static final String SCREEN_BRIGHTNESS = "screen_brightness";
public static int getScreenBrightness(Context context) {
int nowBrightnessValue = 0;
//创建内容解析对象
ContentResolver resolver = context.getContentResolver();
try {
//获取当前屏幕亮度
nowBrightnessValue = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
return nowBrightnessValue;
}
public static void setSystemBrightness(Context context, int brightness) {
//异常处理
if (brightness < 1) {
brightness = 1;
} else if (brightness > 255) {
brightness = 255;
}
saveBrightness(context, brightness);//保存亮度
}
/**
* 保存亮度方法
*
* @param context 上下文
* @param brightness 亮度值 1~255 整数
*/
private static void saveBrightness(Context context, int brightness) {
//获取设置系统屏幕亮度的uri
Uri uri = Settings.System.getUriFor(SCREEN_BRIGHTNESS);
//获取内容解析对象
ContentResolver resolver = context.getContentResolver();
//保存修改后的亮度值
Settings.System.putInt(resolver, SCREEN_BRIGHTNESS, brightness);
//更改亮度值
resolver.notifyChange(uri, null);
}
}
(3) 在主活动MainActivity中,声明一个SeekBar类的对象用于表示拖动条,再声明一个BrightnessUtils对象用于代表屏幕亮度工具类,代码如下:
package com.so.seekbar;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.SeekBar;
public class MainActivity extends AppCompatActivity {
private SeekBar seekBar;//声明拖动条
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//判断安卓系统版本大于6.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//判断系统权限设置
if (!Settings.System.canWrite(MainActivity.this)) {
//没有权限时,跳转系统权限界面
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
//获取拖动条对象
seekBar = findViewById(R.id.set_light);
//设置进度条数据为为系统亮度值
seekBar.setProgress(BrightnessUtils.getScreenBrightness(MainActivity.this));
//设置最大值为225
seekBar.setMax(225);
//设置拖动条监听器
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//将正在改变的监听
//将改变的新值同步到系统亮度
BrightnessUtils.setSystemBrightness(MainActivity.this, progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//开始改变的监听
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//结束改变ed监听
}
});
}
}
(4) 在 AndroidManifest.xml 文件中添加修改系统设置的权限,代码如下:
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ManifestOrder,ProtectedPermissions" />
(5) 运行本实例,将显示如图所示的运行结果。