<Android>2 Android UI

本文最后更新于:2024年9月26日 晚上

2 Android UI

用户界面(User Interface,简称 UI)是系统和用户间交互和信息交换的媒介,其实现信息的内部形式和人类可以接受的形式间的转换

软件设计分为两部分:编码设计、UI 设计

Android UI 都是由 布局控件 组成的。

2.1 布局 ViewGroup

布局(layout)可以定义应用中的界面结构。布局中的所有元素都使用 View 和 ViewGroup 对象的层次结构进行创建。

View 对象通常称为 “微件”。绘制用户可查看并交互的内容。

ViewGroup 对象通常称为 “布局”。是不可见容器,用于定义 View 和 其他ViewGroup 对象的布局结构。

graph TB
classDef vg fill:#EFFFFF, stroke:#333
ROOT([ViewGroup])
ROOT:::vg---A1([ViewGroup])
ROOT---A2([View])
ROOT---A3([View])
A1:::vg---B4([...]):::vg
A1---B1([View])
A1---B2([View])
A1---B3([View])

编写 XML

利用 Android 的 XML 词汇,以元素嵌套方式,快速设计 UI 布局及其包含的同屏元素

每个布局都必须包含一个根元素,且该元素必须是视图对象或 ViewGroup 对象。定义根元素后,以子元素形式添加其他布局对象或控件,从而由外向内,逐步构建定义布局的视图层次结构。

在 XML 中声明布局后,以 .xml 扩展名将文件保存在 res/layout 目录中

下面是一个例子:最外层是一个 RelativeLayout,其包含 4 个子控件(Toolbar、ImageView、TextView、RelativeLayout)。作为子控件的 RelativeLayout,又包含 3 个 Button 控件。

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar...>
    <ImageView...>
    <TextView...>
    <RelativeLayout
        android:id="@+id/rl"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/content_title"
        android:layout_marginTop="30dp"
        android:layout_centerInParent="true">

        <Button...>
        <Button...>
        <Button...>

    </RelativeLayout>
            
</RelativeLayout>

编译应用时,系统会将每个 XML 布局文件编译成 View 资源,在 Activity.onCreate() 回调内,调用 setContentView() 方法,并以 R.layout.xxxxxxx 形式传参,以加载代码中的布局资源

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);		// 存在一个 activity_main.xml 文件
        ...
    }
}

要在 Java 内获取某个指定的 XML 布局资源,就要通过 LayoutInflater 类来实现。

View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.xxx, null, false);

属性与 ID

每个 View 和 ViewGroup 对象都可设置各种 XML 属性。此外,任何 View 对象均可拥有一个整形 ID 以对其进行唯一标识。在布局 XML 中,系统常常以字符串形式在 id 属性中指定该 ID。

<TextView
    android:id="@+id/content_title"
    android:layout_width="wrap_content"
    android:layout_height="50dp"  />

<RelativeLayout
    android:id="@+id/re"
    android:layout_height="match_parent"
    android:layout_below="@id/content_title" />

上述 XML 中定义了一个 TextView 对象,其设置了三条属性。其中,ID 为 content_title,宽度为 wrap_content(适应内容)。此外,还定义了一个 RelativeLayout 对象,其设置了三条属性,ID 为 re,高度为 match_parent(父视图允许的最大尺寸)

上述 XML 中出现了 @+id/... 以及 @id/... 语法。其中,@+id/... 表示在 R.java 文件中新增一个 ID 名称,而 @id/... 表示引用 R.java 文件中的一个 ID 名称。

可以利用 ID 在 java 中创建指定对象的实例。语法如下:

TextView tv = (TextView) findViewById(R.id.content_title);
RelativeLayout rl = (RelativeLayout) findViewById(R.id.re);

也能在 java 中通过 LayoutParams 类实现对 View 对象属性的操作:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.re);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) rl.getLayoutParams();

params.width = 100;
params.topMargin = 10;

事件分发机制

用户与程序交互时产生的动作或操作称为 事件。主要包括

名称 事件 触发场景 触发次数
按下 MontionEvent.ACTION_DOWN 屏幕被按下时 1 次
滑动 MontionEvent.ACTION_MOVE 在屏幕上滑动时 0 次或多次
抬起 MontionEvent.ACTION_UP 从屏幕上抬起时 0 次或 1 次
取消 MontionEvent.ACTION_CANCLE 事件被取消,如滑动超出控件边界等 0 次或 1 次

事件由以上动作组成。从手指按下屏幕开始,到手指离开屏幕不再操作为止,期间所产生的一系列事件组成了 事件流(事件序列)。换言之,所有事件流都由 ACTION_DOWN 开始。

当一个点击事件发生后,将按照 Acticity → ViewGroup → View 的方向依次传递。下面是三者大致的包含关系

graph TB
subgraph Activity
    subgraph ViewGroup
        v1[view]
        v2[view]
    end
end
style v1 fill:#eeeeeeee, stroke:#000000
style v2 fill:#eeeeeeee, stroke:#000000
style ViewGroup fill:#eeeeee88, stroke:#000000
style Activity fill:#a0dfffff, stroke:#000000

安卓的布局结构中,组件会重叠在一起,这导致了事件可能发生冲突。为此,引入了 事件分发机制。主要有以下方法负责事件分发

方法 dispatchTouchEvent() onInterceptTouchEvent() onTouchEvent()
说明 向下通知事件的发生(事件分发)
返回 true 时结束事件分发
是否拦截向子组件的事件分发
返回 true 时拦截事件分发
向上通知事件已处理(事件消费)
返回 true 时事件已消费
在 Activity 中.. 存在 不存在 存在
在 ViewGroup 中.. 存在 存在 存在
在 View 中.. 存在 不存在 存在

下面是事件分发的流程图

(2_2_事件分发)

默认情况下,所有组件的上述方法都会返回 false。可以重写这些方法,以控制事件分发流程。

2.1.1 线性布局 LinearLayout

LinearLayout 是一个视图容器,使得子视图在单个方向(垂直/水平)保持对齐。

orientation 属性

在 LinearLayout 中,使用 orientation 指定子视图对齐的方向

android:orientation="horizontal" 水平对齐
android:orientation="vertical" 垂直对齐

layout_weight 属性

可以为 LinearLayout 的子视图设置 layout_weight 属性,从而指定权重,以分配子视图所占空间的比例。

有子视图添加 layout_weight 属性后,LinearLayout 中的所有剩余空间,将按权重分配给所有添加了 layout_weight 属性的子视图。

如下图所示,未添加 layout_weight 属性(或设置为 0)时,LinearLayout 的剩余空间未被分配

当 控件1 与 控件2 的 layout_weight 分别设置为 3 和 1 时,剩余空间分配如下图所示

gravity 属性

可以为 LinearLayout 的子视图设置 gravity 属性,从而指定子容器相对于父容器所在的位置

android:gravity="center" 正中心
android:gravity="center_vertical" 垂直方向的正中心
android:gravity="center_horizontal" 水平方向的正中心
android:gravity="left" 最左侧(默认)
android:gravity="right" 最右侧
android:gravity="top" 最上方(默认)
android:gravity="bottom" 最下方
上述取值有一部分可以组合使用。比如 `android:gravity="right|bottom"`

此外,对于 水平/垂直 对齐方向,也可以使用 layout_gravity 属性以改变子视图在 水平/垂直 方向的位置。

2.1.2 相对布局 RelativeLayout

相对布局下,子视图可以通过设置相应布局属性,设定相对于另一 兄弟视图 或 父视图 的相对位置。

相对兄弟元素

需要通过 ID 指定相对的目标元素。

android:layout_below="@id/xxx" 在指定 View 的下方
android:layout_above="@id/xxx" 在指定 View 的上方
android:layout_toLeftOf="@id/xxx" 在指定 View 的左边
android:layout_toRightOf="@id/xxx" 在指定 View 的右边
android:layout_alignTop="@id/xxx" 与指定 View 上边界一致
android:layout_alignBottom="@id/xxx" 与指定 View 下边界一致
android:layout_alignLeft="@id/xxx" 与指定 View 左边界一致
android:layout_alignRight="@id/xxx" 与指定 View 右边界一致

相对父元素

android:alignParentLeft="true" 在父元素内的左侧
android:alignParentRight="true" 在父元素内的右侧
android:alignParentTop="true" 在父元素内的顶部
android:alignParentBottom="true" 在父元素内的底部
android:centerInParent="true" 居中布局
android:centerVertical="true" 垂直居中布局
android:centerHorizontal="true" 水平居中布局

2.1.3 帧布局 FrameLayout

帧布局没有任何布局方式。添加子控件时,默认将其放置于区域左上角。帧布局大小由最大的子空间决定,后续添加的子控件将覆盖在原先子控件上面进行显示。

2.1.4 网格布局 GridLayout

一种基于网格的布局方式。加入的组件会默认按照由左至右、由上至下的顺序摆放。

在 GridLayout 中可以指定布局的行列数。若仅指定其中一项,则系统会自动计算出另一项

android:columnCount="10" 指定布局的列数
android:rowCount="10" 指定布局的行数
在 子控件 中可以指定横跨的行列数
android:columnSpan="2" 该控件横跨的列数
android:rowSpan="2" 该控件横跨的行数
此外,可以指定子控件所在的行列。行列的序号从 0 开始计算
android:layout_row="0" 该控件显示在第几行
android:layout_column="0" 该控件显示在第几列

2.2 组件 View

2.2.1 文本框 TextView

TextView 是一种用于显示文本的控件

常用属性如下

android:text="@string/content" 指定文本的内容。
可以直接给出字符串,也能调用 strings.xml 中的字符串
android:textColor="@color/my_color" 指定字体颜色。
可以直接给出颜色,也能调用 color.xml 中的颜色
android:Style="normal" 指定字体风格。
可选值为:normal(默认)、bold、italic
android:textSize="10sp" 指定字体大小。单位通常是 sp
android:autoLink="web" 识别链接类型。
可选值为:web、email、phone、map、none(默认)、all

2.2.2 文本输入框 EditText

EditText 由 TextView 派生而来,可以接受用户输入

除了 TextView 的属性外,EditText 特有的属性有

android:hint="@string/hint" 指定默认的提示文本
android:textColorHint="@color/my_color" 指定默认提示文本的颜色
android:selectAllOnFocus="true" 点击输入框时,自动选中其内容
android:inputType="none" 限制输入类型
可选值有:none、text、textPassword、number、datetime、phone 等
要查看所有的可选值,请查阅 官方API文档
android:minLines="1" 指定最小行数
android:maxLines="1" 指定最大行数。超过时,文字将向上滚动
android:singleLine="true" 是否仅允许单行输入
android:textScaleX="1.5" 设置字符的水平间隔
android:textScaleY="1.5" 设置字符的垂直间隔
android:capitalize="sentences" 指定英文字母大写类型
可选值为:sentences(仅首字母大写)、words(每个单词的首字母大写、以空格区分单词)、characters(全部字母大写)

2.2.3 按钮 Buttom

Buttom 由 TextView 派生而来,可见 TextView 非常能生,连 Buttom 都是你家仔

Buttom 具有默认的背景,文本默认居中对齐且全部大写

Buttom 特有的属性有

android:textAllCaps="true" 按钮英文字母是否全大写,默认 true
android:onClick="onButtomClick" 指定按钮按下时调用的方法。值为方法名
android:enable="true" 指定按钮是否可用
亦能通过 Buttom 对象的 `setOnClickListener(view -> {...})` 方法添加点击响应事件

2.2.4 图像视图 ImageView

ImageView 可以用于显示图片以及任何 Drawable 对象

ImageView 的一些属性如下

android:src="@mipmap/pic" 指定要显示的图片路径。按图片大小填充
android:background="@drawable/bg" 指定 ImageView 的背景。
背景位于图片下方,且以 ImageView 的长宽进行拉伸
android:adjustViewBounds="true" 仅当 ImageView 的宽高中,一方设为固定值,另一方设为自适应(warp_content)时,若图片尺寸大于 ImageView,则使得 ImageView 的宽高比与图片一致
其他情况下,该属性不生效
android:scaleType="center" 指定图片的填充方式。可选值有:
fitXY:拉伸图片以完全填充
fitStart:按比例缩放,使较长边符合容器边长。图片左上角与容器对齐
fitCenter:按比例缩放,使较长边符合容器边长。图片居中对齐
fitEnd:按比例缩放,使较长边符合容器边长。图片右下角与容器对齐
center:保持原图大小,居中对齐。裁剪多余部分
centerCrop:按比例缩放,使图片完全覆盖容器。裁剪多余部分
centerInside:按比例缩放,使图片完全显示
matrix(默认):保持原图大小,图片左上角与容器对齐。裁剪多余部分

2.2.5 单选按钮 RadioButtom、复选按钮 CheckBox

RadioButtom 是一个单选按钮。当其被添加到 RadioGroup 按钮组后,该组按钮同时只有一个可被选中。

RadioGroup 按钮组由 LinerLayout 派生而来,用法与 LinerLayout 相似。

使用 RadioGroup 对象的 setOnCheckedChangeListener(group, id -> {...}) 方法,以添加事件响应

CheckBox 是一个复选按钮,用户点击复选框可使其在 选中/未选中 状态间切换。

RadioButtom 和 CheckBox 的一些属性如下

android:checked="false" 指定按钮是否被选中
android:drawableLeft="@drawable/dl" 于按钮文本左侧添加一个 drawable 对象,可以控制图标与文本的距离
android:buttom="@null" 指定按钮样式。设置了 background 或 drawableft 时,应设为 @null

2.2.6 切换按钮 ToggleButtom、开关 Switch

ToggleButtomSwitch 可以在两种状态之间进行切换。其中 ToggleButtom 更为简洁,而 Switch 提供了可滑动的滑块和背景轨道,属性也更丰富。

ToggleButtom 的一些属性如下

android:checked="false" 指定按钮是否被选中
android:textOn="@string/on" 设置按钮处于按下状态时的文字
android:textOff="@string/off" 设置按钮处于未按下状态时的文字
android:disabledAlpha="1" 设置按钮处于未按下状态时的透明度

Switch 的一些属性如下

android:checked="false" 指定按钮是否被选中
android:textOn="@string/on" 设置按钮处于按下状态时的文字
android:textOff="@string/off" 设置按钮处于未按下状态时的文字
android:track="@drawable/tk" 设置按钮开关的滑轨图片
android:thumb="@drawable/tb" 设置按钮开关的滑块图片
android:typeface="normal" 设置字体
可选项有:sans、serif、monospace。也能使用其他字体文件

2.2.7 进度条 ProgressBar

ProgressBar 是一个图形控件,可以展示当前进度。可以选择 横向进度条 以及 圆形进度条。

ProgressBar 的一些属性如下

android:max="100" 指定进度条的最大值。默认值为 100。
android:indeterminate="false" 设置进度条是否为不确定模式。
为不确定模式的场合,加载时会无限循环进行 Loading 动画
关闭不确定模式的场合,进度条的样子会根据实时进度而改变
android:indeterminateDrawable="@drawable/idb" 设置不确定模式进度条对应的 drawable 样式
android:indeterminateDuration="1" 设置不确定模式进度条的持续时间
android:progress="0" 指定进度条的当前进度
android:style="android:attr/progressBarStyleHorizontal" 指定进度条样式
android:progressDrawable="@drawable/pdb" 指定进度条对应的 drawable 样式
android:secondaryProgress="0" 指定二级进度条的进度
视频播放窗口中的缓冲进度条,即为二级进度条

2.2.8 拖动条 SeekBar

拖动条 SeekBar 由进度条 ProgressBar 派生而来。其特性与进度条类似,但用户可以自由控制其进度。音量调节条就是一种拖动条。

SeekBar 继承了 ProgressBar,也包括一些 ProgressBar 的属性和方法

android:max="100" 指定进度条的最大值。默认值为 100。
android:progress="0" 指定进度条的当前进度
android:progressDrawable="@drawable/pdb" 指定进度条对应的 drawable 样式
android:secondaryProgress="0" 指定二级进度条的进度
android:thumb="@mipmap/thumb" 指定进度条的滑块图片
android:splitTrack="false" 指定进度条背景样式。false 为透明

对于 SeekBar,共需监听 3 个事件,分别是:

  • 数值的改变(onProgressChanged)
  • 开始拖动(onStartTrackingTouch)
  • 停止拖动(onStopTrackingTouch)

2.2.9 滚动条 ScrollView

滚动条 ScrollView 是一个滚动条。也有水平版本的滚动条 HorizontalScrollView

ScrollView 实际上是 FrameLayout 的派生类,本质上是一个布局。其包含的内容超出范围后,可以使用侧面的滚动条以调整内容的位置。

属性:

android:fillViewport="false" 指定内容是否填充视口。默认为 false
android:scrollbars="none" 指定滚动条的显示方式。可选值有 none、vertical、horizontal
android:scrollbarStyle="default" 指定滚动条样式。可选值有:
default:默认值
insideoverlay:覆盖内容上方
outsideoverlay:位于内容旁边
android:fadeScrollbars="true" 指定滚动条是否在非活动时渐隐。默认为 false

一些常用方法:

void scrollTo(int x, int y) 将滚动条设置到指定位置
void smoothScrollTo(int x, int y) 将滚动条平滑地滚动到指定位置
void smoothScrollBy(int dx, int dy) 将滚动条平滑地滚动指定偏移量
void fullScroll(int direction) 使ScrollView滚动到指定的边界。其中 direction 的取值为:
View.FOCUS_UP:滚动到顶部
View.FOCUS_DOWN:滚动到底部
boolean isSmoothScrollingEnabled() 滚动条是否是平滑滚动
void android:fling="int velocityY" 设置滚动条的滚动速度

2.2.10 日期时间组件

文本时钟 TextClock 由 TextView 派生而来,可以字符串格式,按照 24 小时制或 12 小时制显示日期和时间。

android:format24Hour="MM/dd/yyyy h:mmaa" 指定 24 小时制下的显示格式
android:format12Hour="MM/dd/yyyy h:mmaa" 指定 12 小时制下的显示格式
android:timeZone="null" 指定时钟时区。指定后会忽略系统时区变化

表盘时钟 AnalogClock 由 View 直接派生而来,是一个可以随时间自动更新的时钟组件。

android:dial="@minimap/anac_bg" 指定模拟时钟的背景图片
android:hand_hour="@minimap/anac_hour" 指定模拟时钟的时针图片
android:hand_minute="@minimap/anac_minute" 指定模拟时钟的分针图片
**计时器 Chronometer** 由 TextView 派生而来,显示从某时刻开始经过的时间。

属性:

android:format="MM/dd/yyyy h:mmaa" 指定计时器的计时格式

方法:

void setBase(long base) 设置计时器的起始时间
void setFormat(String format) 设置计时器的显示格式
void start() 计时器开始计时
void stop() 计时器停止计时
void setOnChronometerTickListener(L listener) 设置计时器改变事件监听器

日期选择器 DatePicker 派生自 FrameLayout,其允许用户选择一个日期。

属性:

android:calendarTextColor="@color/ct" 指定日历列表的文本颜色
android:calendarViewShown="true" 指定是否显示日历视图
android:datePickerMod="calender" 指定组件外观。可选值为:spinner、calender(默认)
android:dayOfWeekBackground="@color/dowbg"
android:dayOfWeekTextAppearance="@color/dowtapp"
指定顶部星期数部分的背景色
指定顶部星期数部分的文字颜色
android:yearLIstSelectorColor="@color/yaerlist_sel"
android:yearLIstItemAppearance="@color/yaerlist_item"
指定年列表选择的颜色
指定年列表文本颜色
android:headerBackground="@color/head_bg"
android:headerDayOfMonthAppearance="@color/head_day_text"
android:headerMonthAppearance="@color/head_month_text"
android:headerYearAppearance="@color/head_year_text"
指定头部的背景色
指定头部日数部分的文字颜色
指定头部月份数部分的文字颜色
指定头部年份数部分的文字颜色
android:firstDayOfWeek="1" 指定日历列表中每周的起始星期数
android:maxDate="12/31/2024"
android:minDate="01/01/2000"
指定日历列表的最大、最小日期
android:spinnerShown="false" 指定是否显示微调框
方法:
int getDayOfMonth()
int getMonth()
int getYear()
获取选定的日数/月份数/年份数
void setMaxDate(long maxDate)
void setMinDate(long minDate)
设置日历列表的最大/最小日期
int getFirstDayOfWeek() 获取每周的起始星期数
void setSpinnerShown(boolean shown) 设置是否显示微调框
void updateDate(int year, int month, int day) 设置当前日期
CalendarView getCalendarView() 获取日历视图

时间选择器 TImePicker 派生自 FrameLayout,其允许用户选择一个时间。

2.3 适配器 Adapter

**MCV **是一种软件设计模式,用于将应用程序的逻辑分离成三个主要部分:Model(模型)、View(视图)和 Controller(控制器)。

  • Model:负责应用程序的数据和业务逻辑,直接管理数据。

    其通过 View 获得用户输入的数据,也从数据库获得数据交给 View 来显示。

  • View:是用户的操作接口,即 GUI。

    负责显示数据(UI 部分),从 Model 获取数据,并将其呈现给用户。

  • Controller:负责处理输入,控制程序的执行流程、对象间的互动。

Adapter 是用来帮助填充数据的中间桥梁(属于 Controller),将各种数据以合适的形式显示到 AdapterView 上。使用时,先给 Adapter 填充内容,之后将设定好内容的 Adapter 设置到 AdapterView 上。

开发中常用的 Adapter 有:

  • BaseAdapter:是一个抽象类。实际开发中会继承这个类并且重写相关方法。用途最为广泛。
  • ArrayAdapter:最简单的一个Adapter。支持泛型操作,只能展现一行文字
  • SimpleAdapter:具有良好扩展性的一个Adapter。可以自定义多种效果
  • SimpleCursorAdapter:用于显示简单文本类型

2.3.1 基本适配器 BaseAdapter

BaseAdapter 定义了最基本的一些方法,开发时必须实现这些方法

int getCount() 获取填充的数据集数
Object getItem(int i) 获取指定索引的数据项
long getItemId(int i) 获取指定行对应的 ID
View getView(int i, View view, ViewGroup viewGroup) 获取某数据项对应的视图

下面是一个使用 BaseAdapter 的例子

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 这是 MyAdapter 的构造函数。如何使用取决于如何定义
        new MyAdapter(new ArrayList<Music>(), this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}


class MyAdapter extends BaseAdapter {
    private final List<Music> list;
    private final Context context;

    public MyAdapter(List<Music> list, Context context) {
        this.list = list;				// 数据集列表
        this.context = context;			// 主视图对象
    }

    @Override
    public int getCount() {				// 获取数据集大小
        return list.size();
    }

    @Override
    public Object getItem(int i) {		// 获取指定数据项
        return list.get(i);
    }

    @Override
    public long getItemId(int i) {		// 获取指定数据项 ID
        return i;
    }
    
    static class ViewHolder {			// 定义类 ViewHolder,以便后续 getView 方法复用
        								// 类的内容取决于数据项视图的布局
        TextView item_title;
        TextView item_content;
        ImageView item_icon;
        String src;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        								// 获取指定数据项对应的视图
        ViewHolder vh;
        if (view == null){
            view = LayoutInflater.from(context).inflate(R.layout.my_item_layout, viewGroup, false);
            							// my_item_layout 是一个自定义的数据项的布局文件
            							// 是在 res/layout 下创建的布局文件
            vh = new ViewHolder();
            vh.item_content =  view.findViewById(R.id.item_content);
            vh.item_title =  view.findViewById(R.id.item_title);
            vh.item_icon = view.findViewById(R.id.item_icon);
            vh.src = "";
            view.setTag(vh);
        } else {
            vh = (ViewHolder)view.getTag();
        }
        vh.item_title.setText(list.get(i).getName());
        vh.item_content.setText(list.get(i).getContent());
        vh.item_icon.setImageResource(list.get(i).getPic());
        vh.src = list.get(i).getSrc();
        return view;
    }
}

2.3.2 容器控件 AdapterView

AdapterView 是由 ViewGroup 派生而来的抽象类。其由一个个子元素组成,子元素的内容与数据由 Adapter 决定。

常用的 AdapterView 有 ListView(列表)、GridView(网格)、Spinner(下拉列表)

  • ListView 列表视图

    由 AdapterView 派生而来,以垂直滑动列表形式显示一组数据。

    ExpandableListView 折叠列表

    ExpandableListView 由 ListView 派生而来。其支持展开、折叠功能,可以展示带有分组和子项的层次结构数据。

    ExpandableListView 需要实现了 **ExpandableListAdapter(折叠列表适配器)**接口的适配器来提供数据源。使用时,分别为分组标签布局、子项布局准备布局与数据源。

    常用属性:

    android:groupIndicator="@drawable/group_indicator"
    android:childIndicator="@drawable/child_indicator"
    指定指示分组项展开/折叠(-/+)状态的图标
    指定指示子项展开/折叠状态的图标。默认无图标
    android:divider="@color/group_divider"
    android:childDivider="@color/child_divider"
    指定分组分隔线的样式
    指定子项分隔线的样式
    android:dividerHeight="1dp" 指定分组分隔线的高度

    常用方法:

    boolean isGroupExpanded(int group) 返回指定分组是否折叠
    boolean expandGroup(int groupPos)
    boolean collapseGroup(int groupPos)
    展开指定分组
    折叠指定分组
    void setAdapter(ListAdapter adapter) 设置适配器
  • GridView 网格视图

    由 AdapterView 派生而来,以网格形式显示子项目的视图容器。

    下面是一些常用属性:

    android:numColumns="5" 指定列数。默认为 1
    android:stretchMode="none" 指定当数据项不满一行时,如何填充空位。可选值有:
    none:默认值。不填充空位
    spacingWidth:不改变间距大小,拉伸数据项宽度以填充整行
    columnWidth:拉伸数据项宽度以填充整行。可能改变每列宽度
    android:horizontalSpacing="5dp"
    android:verticalSpacing="5dp"
    指定数据项间的水平间距
    指定数据项间的竖直间距
    android:columnWidth="5dp"
    android:rowHeight="5dp"
    指定数据项的宽度
    指定数据项的盖度
    android:gravity="center" 指定数据项的对齐方式。可选值有:center、left、right 等
  • Spinner 下拉列表

    由 AdapterView 派生而来,用于选择列表中的一个选项

    android:spannerMode="dropdown" 指定下拉列表的风格。可选值有:
    dialog:对话框风格
    dropdown:默认值。下拉菜单风格
    android:dropDownHorizontalOffset="5dp"
    android:dropDownVerticalOffset="5dp"
    指定列表框的水平偏移距离
    指定列表框的竖直偏移距离
    android:dropDownSelector="@minimap/dds"
    android:popupBackground="@minimap/pbg"
    指定列表框被选中时的背景
    指定列表框的背景
    android:dropDownWidth="5dp" 指定列表框宽度
    android:gravity="center" 指定数据项的对齐方式。可选值有:center、left、right 等
    android:prompt="@string/spinner_pp" 指定列表框的标题。只能引用 string.xml 的资源 id

2.4 其他控件

2.4.1 提示框 Toast

Toast 是一种非模态弹窗,用于弹出信息,作为提醒或消息反馈。常见的 Toast 提示框为一句简短的描述性文字。这种样式的弹窗可以出现在页面的任何位置。

弹窗分为模态弹窗和非模态弹窗两种,两者的区别在于需不需要用户对其进行回应

  • 模态弹窗:会打断用户的正常操作,要求用户必须对其进行回应,否则不能继续其它操作行为
  • 非模态弹窗:不会影响用户的操作,用户可以不对其进行回应。通常都有时间限制,一段时间后会自动消失

常用方法:

static Toast makeText(Context context, CharSequence text, int duration) 创建一个 Toast 控件。参数如下:
context:上下文对象
text:要提示的信息
duration:提示的时长。可以是 Toast.LENGTH_SHORT 或 Toast.LENGTH_LONG
void show() 提示该信息
void setGravity(int gravity, int xOffset, int yOffset) 设置该信息提示的位置
grivity 是 Grivity 类所记述的某个值
View getView() 获取该提示信息的布局。如此一来就能变更其布局
默认布局仅包含一个 id 为 message 的 TextView 组件

使用说明:

  1. 通过 Toast.makeText(this, str, 1) 方法创建控件
  2. 通过 getView() 方法获取布局,并可以自定义其布局
  3. 需要该信息弹出时,调用 show() 方法

2.4.2 对话框 AlertDialog

Dialog 是一种模态弹窗。用于以弹窗形式弹出信息,并要求用户进行选择。Dialog 通常由标题、信息内容和功能按钮组成,只有当用户点击了某个功能按钮后弹窗才会消失。

常用方法:

Builder(Context context) 构造器
Builder setTitle(int titleId)
Builder setCustomTitle(View customTitleView)
Builder setMessage(int messageId)
Builder setIcon(int iconId)
设置对话框标题。需要传入 string.xml 的资源 id
使用一个自定义的视图设置对话框标题
设置对话框内容。需要传入 string.xml 的资源 id
设置对话框图标。传入资源 id,并且设置过标题才能生效
Builder setPositiveButton(int text, OnClickListener)
Builder setNegativeButton(int text, OnClickListener)
Builder setNeutralButton(int text, OnClickListener)
设置确定/取消/普通按钮
第一个参数可以传入资源 id 或字符串
第二个参数是一个 DialogInterface.OnClickListener
AlertDialog create() 创建对话框对象
AlertDialog show() 将对话框弹出

使用说明:

  1. 通过 new AlertDialog.Builder(this) 构造器,创建 AlertDialog.Builder 对象
  2. 通过上文表中的方法设置标题、内容、图标等
  3. 通过 create() 方法创建对象
  4. 通过对象的 show() 方法弹出对话框

2.4.3 自定义对话框 PopupWindow

PopupWindow 是一种阻塞式对话框。相对的,AlertDialog 是非阻塞式的对话框。阻塞式对话框弹出后,直到对话框关闭前,程序会一直等待。而非阻塞式对话框弹出后,程序会在后台继续运行。

此外也有其他不同。PopupWindow 的位置可以自定义,而 AlertDialog 的位置是固定的。

常用方法:

PopupWindow(View contentView, int width, int height, boolean focusable) 构造器。也有其他参数的构造器。
这里的参数依次是:加载的 view、宽度、高度、是否可以获取焦点
void setAnimationStyle(int animationStyle) 设置加载动画。需要一个资源 id
void showAsDropDown(View anchor, int xoff, int yoff)
void showAtLocation(View parent, int gravity, int x, int y)
让对话框显示在某控件下方。即偏移基点为控件左下角
让对话框显示在某控件内部。偏移基点取决于 gravity,后者是 Gravity 类规定的常数
View getContentView()
void setContentView(View contentView)
获取/设置对话框显示的 View

<Android>2 Android UI
https://i-melody.github.io/2024/09/26/Android/2 Android UI/
作者
Melody
发布于
2024年9月26日
许可协议