<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" | 最下方 |
此外,对于 水平/垂直 对齐方向,也可以使用 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" | 该控件横跨的行数 |
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" | 指定按钮是否可用 |
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
ToggleButtom 和 Switch 可以在两种状态之间进行切换。其中 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" | 指定模拟时钟的分针图片 |
属性:
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 组件 |
使用说明:
- 通过
Toast.makeText(this, str, 1)
方法创建控件 - 通过
getView()
方法获取布局,并可以自定义其布局 - 需要该信息弹出时,调用
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() | 将对话框弹出 |
使用说明:
- 通过
new AlertDialog.Builder(this)
构造器,创建 AlertDialog.Builder 对象 - 通过上文表中的方法设置标题、内容、图标等
- 通过
create()
方法创建对象 - 通过对象的
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 |