用户接口(UserInterfaces)
活动通常显示用户界面。同时安卓为构建用户接口提供了很多类。
1. 视图(View)
绘制视图本身和处理事件。
一些预定义的视图:
(1)按钮(Button)
能够单击并表现行为的视图。
(2)状态按钮(ToggleButton)
2-状态按钮,拥有检查/未检查状态,灯光指示器显示按钮当前的状态。
(3)检查框(CheckBox)
另外一种2-状态按钮,拥有检查/未检查状态。
(4)评分条(RatingBar)
包含一行星的视图。用户可以点击或拖动星来表示它们的等级。
(5)自动完成的文本视图(AutocompleteTextView)
当用户输入文本时提供完成建议的可编辑文本区域。
2. 常见的视图操作
(1)设置可见:显示或隐藏视图;
(2)设置检查状态
(3)设置监听:当具体的事件发生时应该执行的代码;
(4)设置属性:透明度,背景和旋转;
(5)管理输入焦点:允许视图取得焦点和请求焦点。
3. 视图事件资源
(1)用户交互:触摸;键盘/轨迹球/方向键;
(2)系统控制:生命周期的改变。
4. 处理视图事件
经常在监听器中处理事件。由视图类定义大量的监听接口。
(1)视图监听接口
OnClickListener.onClick()——视图被单击;
OnLongClickListener.onLongClick()——视图被按下并保持;
OnFocusChangeListener.onFocuesChange()——视图获得或失去焦点;
OnKeyListener.onKey()——视图接收到硬件的按键按下。
(2)显示视图
视图的组织呈树状结构。显示视图包含多个步骤。
测量——获得每个视图的大小;
布局——定位每个视图;
绘制——绘制每个视图。
定制的视图子类会覆盖不同的视图方法。
onMeasure()——确定视图及其子类的大小;
onLayout()——视图必须对其所有的子视图分配大小和位置;
onDraw()——显示视图的内容;
onFocusChanged()——视图的焦点状态改变;
onKeyUp(),onKeyDown()——硬件按键事件发生;
onWindowVisibilityChanged()——包含视图的窗口的可见状态改变。
5. 视图组
包含其它视图的不可见视图;用于组和组织视图集合;视图的容器(containers)和布局的基类。
预定义的视图组:
(1)单选组
单选组包含一系列单选按钮。每次总是只有一个按钮被选择;
(2)时间选择器
视图组允许用户去选择时间;
(3)日期选择器
视图组允许用户去选择日期;
(4)网络视图
显示网页的视图组;
(5)地图视图
显示地图的视图组;
(6)画廊
显示水平滚动的列表的视图组;由下拉列表适配器管理选项;
a)适配器和适配器视图
适配器视图的子视图由适配器管理。适配器管理数据并向适配器视图提供数据视图;适配器视图显示数据视图。
b)列表视图
适配器视图显示选项的可滚动列表;由列表适配器管理选项;列表视图可以基于文本输入过滤选项列表。
(7)下拉列表
提供选项的可滚动列表的适配器视图;用户可以从列表中选择一个选项;下拉列表适配器管理选项。
6. 布局
为所包含的视图定义结构的通用视图组。
(1)线性布局
子视图以单个水平或垂直的行出现;
(2)相对布局
子视图的位置由其它视图或父视图决定;
(3)桌面布局
子视图以行和列的形式安排。
7. 网格视图
子视图安排在2维可滚动的网格中。
菜单和操作杆
支持菜单的活动;活动可以在菜单中添加选项,处理在菜单选项上的单击事件。
1. 菜单类型
(1)选项
用户按下菜单按钮后显示的菜单;
(2)上下文
当用户触摸并保持视图时具体的视图菜单;
(3)子菜单
当用户触摸可见菜单项时被激活的菜单。
2. 创建菜单
在XML文件中定义菜单资源,保存在res/menu/filename.xml中。
onCreate…Menu()函数中填充菜单资源;在合适的on…ItemSelected()函数中处理选项的选择。
3. 菜单
同时支持许多其他特征:将菜单项打成组;将菜单项与快捷键结合;将菜单项与意图结合。
4. 操作杆
和很多桌面应用的操作杆相似。能够快速执行常见操作。
(1)带操作杆的片段动态布局
显示选择的剧本的引用和剧本的标题;为操作杆提供动作;三个主要对象:
QuoteViewerActivity
TitleFragment
QuoteFragment
(2)actionbar.tab
在Tab和内容区域划分屏幕,允许多个片段共享单个内容区域;每个Tab都与一个片段相关联;同一时刻只有一个Tab被选中;选中的Tab对应的片段将在内容区域可见。
5. 对话
用于与用户交流的活动的独立子窗口。
(1)对话子类
警告对话;过程对话;日期选择器对话;时间选择器对话。
用户接口实验
1. 初始用户接口
(1)填入新视图层
主活动存放在ToDoActivity.java中,本来主活动显示的视图为空白。现在需要将footerView填充进footer_view.xml文件。
TextView footerView = (TextView)getLayoutInflater().inflate(R.layout.footer_view,getListView(), false);
查看footerView.xml发现只有1个TextView,文本的内容为“AddNew ToDo Item”。这个界面在之前的空白界面中并未出现,所以需要用getLayoutInflater()查找res/layout下的xml文件,并且用xml布局实例化后的LayoutInflater对象调用inflate()函数载入footerView视图。正如许多人所说的,getLayoutInflater().inflate()是将Layout的xml布局文件实例化为View类对象。这里用到的函数形式为:
public View inflate (int resource, ViewGrouproot, boolean attachToRoot)
inflate函数:
根据指定的XML资源添加新的视图层。函数发生错误时会返回填入异常(InflateException)。
1)参数
resource:需要加载的XML布局资源的ID号(比如,R.layout.main_page);
root:产生的新视图层的父视图(如果attachToRoot为true),或者只是为返回的视图层的父图层提供一系列布局参数(LayoutParams)值的对象(如果attachToRoot为false)。
attachToRoot:填入的图层是否应与根参数相关联?如果为false,仅用根来为XML根视图创建正确的布局参数子类。
如果提供了根视图并且attachToRoot为true,那么返回的视图为根视图,否则填入的XML文件为根视图。
ListView继承自View,也是一种视图。同时ListView为默认的布局元素。
(2)添加新视图层到列表视图
此时仅仅是得到footer_view.xml对应的视图对象footerview,并且上面也将attachToRoot设置为false,所以与根视图暂时还一点关系扯不上。所以需要添加XML对应的视图对象至列表视图。
getListView().addFooterView(footerView);
这里我理解为如果没有根视图,那么可以选择添加新的视图层到列表视图。
先看看这个函数addFooterView()到底怎么用的:
voidandroid.widget.ListView.addFooterView(View v)
addFooterView函数:
在列表的底部添加一个固定的视图。如果addFooterView被多次调用,视图将会根据它们的添加顺序出现。根据用户需要可以通过调用该函数获取视图的焦点。
第一次使用时,函数调用只能放在用setAdapter(ListAdapter)设置适配器之前。
参数:需添加的视图。
(3)为新视图添加监听器
将新的视图强制转换成TextView后才赋值给了footerView,为footerView添加监听器。当检测到footerView被触摸时进入footerView对象的OnClickListener()函数,在该函数中从当前活动ToDoManagerActivity转换到另一个活动AddToDoActivity。然后启动从ToDoManagerActivity转换到AddToDoActivity的映射并向AddToDoActivity发送请求码ADD_TODO_ITEM_REQUEST。
Intent intent = new Intent(getApplicationContext(),AddToDoActivity.class);
startActivityForResult(intent, ADD_TODO_ITEM_REQUEST);
(4)显示新视图层
到目前为止已经将新视图层添加进列表视图了,最后还需要在界面中显示更新后的列表视图。列表视图显示组件(TextView继承自视图,也是一种基本组件)还需要使用适配器将组件等数据映射到当前活动对应的界面上。
mAdapter);
setListAdapter (ListAdapter adapter)
适配器管理数据并向适配器视图提供数据(这里为组件)更容易理解。
(5)接收目标活动的响应
在当前活动ToDoManagerActivity中启动目标活动AddToDoActivity后,目标活动完成任务后会向当前活动返回结果。在onActivityResult()中处理响应结果:首先判断请求码是否为当前活动发送出去的请求码,然后判断结果码是否为完成任务(后面具体说明任务内容),两个条件同时满足后,根据返回的意图类data创建新的ToDoItem对象,最后添加到当前活动对应的适配器mAdapter中去。add函数添加数据至适配器并通知(Notify)映射数据的列表视图刷新界面。
if (requestCode == ADD_TODO_ITEM_REQUEST) {
if(resultCode == RESULT_OK){
mAdapter.add(new ToDoItem(data));
}
}
2. 适配器添加视图过程总结
(1)填充给定XML的布局文件至视类对象;
(2)视类对象添加进根视图;
(3)为视类对象添加监听函数;
(4)适配器显示添加入视类对象后的根视图。3. AddToDoActivity活动中添加的代码
(1)“取消”事件响应函数
直接结束活动:finish();
(2)“复位”事件响应函数
设置默认的组件数据:设置标题的字符串为为空,设置默认的状态和优先级,设置默认的日期和时间:
mTitleText.setText("");
mStatusRadioGroup.check(mDefaultStatusButton.getId());
mPriorityRadioGroup.check(mDefaultPriorityButton.getId());
setDefaultDateTime();
上面的成员变量在当前活动的视图中有对应关系,其中对我而言比较新的为RadioButton类型和RadioGroup类型的组件。看看check()函数的用法:
check
设置将传入其标识符(ID)的单选按钮选中。选择标识符为-1时表示清空选择,这种操作等价于调用clearCheck()函数。
1)参数
id:组中需要选择的按钮的唯一标识符。
Check中获得标识符的方式(mDefaultStatusButton.getId())等价于getCheckedRadioButtonId()函数。
(3)“提交”事件响应函数
如程序中提示,获得优先级、当前状态和标题,将获得的数据打包进意图类data。这里自定义的packageIntent函数中都是由putExtra组成的,和前面自定义的add函数是成对的。如果将packageIntent相当于打包数据,add相当于解析数据(除此还有显示数据到视图)。至此,活动AddToDoActivity任务完成,最后向活动ToDoManagerActivity返回请求码、结果码和数据。
// TODO - Get the current Priority
Priority priority =getPriority();
// TODO - Get the current Status
Status status= getStatus();
// TODO - Get the current ToDoItem Title
StringtitleString = getToDoTitle();
// Package ToDoItem data into anIntent
Intent data =new Intent();
ToDoItem.packageIntent(data,titleString, priority, status, fullDate);
// TODO- return data Intent and finish
setResult(RESULT_OK,data);
finish();
4. 适配器显示视图
我大概知道在这个函数中,具体看看getView()函数的说明也就清楚了:
View getView (int position, View convertView, ViewGroup
(1)getView函数
inflate(int,android.view.ViewGroup, boolean)来指定根视图并防止与根视图关联。
1)参数
position:期望的视图在适配器数据集中的选项位置;
convertView:重利用的旧视图;
parent:最终关联的俯视图;
返回值:指定位置的数据对应的视图。
(2)get()函数获得列表中指定位置返回的元素,ToDoItem类中包含很多数据;
(3)从todo_item.xml布局文件中填入视图得到相对布局对象itemView;
(4)在itemView中显示数据。
public View getView(intposition, View convertView, ViewGroup parent) {
// TODO - Get the current ToDoItem
final ToDoItem toDoItem = mItems.get(position);
// TODO - Inflate the View for this ToDoItem
//from todo_item.xml
itemView= LayoutInflater.from(mContext).inflate(R.layout.todo_item, parent, false);
// TODO - Fill in specific ToDoItem data
//Remember that the data that goes in this View
//corresponds to the user interface elements defined
//in the layout file
// TODO - Display Title in TextView
final TextView titleView = (TextView) itemView.findViewById(R.id.titleView);
titleView.setText(toDoItem.getTitle());
// TODO - Set up Status CheckBox
final CheckBox statusView = (CheckBox) itemView.findViewById(R.id.statusCheckBox);
setChecked(toDoItem.getStatus().equals(ToDoItem.Status.DONE));
statusView.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
booleanisChecked) {
Log.i(TAG, "Entered onCheckedChanged()");
// TODO - set up an OnCheckedChangeListener, which
// is called when the user toggles the status checkbox
if(isChecked) {
toDoItem.setStatus(Status.DONE);
} else {
toDoItem.setStatus(Status.NOTDONE);
}
}
});
// TODO - Display Priority in a TextView
final TextView priorityView = (TextView) itemView.findViewById(R.id.priorityView);
priorityView.setText(toDoItem.getPriority().toString());
// TODO - Display Time and Date.
//Hint - use ToDoItem.FORMAT.format(toDoItem.getDate()) to get date and
//time String
final TextView dateView = (TextView) itemView.findViewById(R.id.dateView);
ToDoItem.FORMAT.format(toDoItem.getDate()));
//Return the View you just created
return itemView;
}
}
5. 适配器显示视图过程总结
(1)获得视图位置返回的数据; (2)将数据对应的布局文件填入新视图; (3)在新视图中显示数据。
结语
篇幅有限,日期和时间的设置和解析等部分这里暂时不追究了