03_用户界面
常见的异常:
NullPointException
原因:调用对象的方法/属性,但对象为null
ClassCastException
原因:类型转换异常
ActivityNotFoundException
原因:没有注册Activity,或注册不正确
基本常见异常的一般分析步骤:
- 在logcat中从下向上找,尽量找到causeBy(会显示哪种异常导致的)
- 找到出异常的类及行号,点击进入对应的行
1. 理论概述
1.1 理解UI
UI的定义
- 全称User Interface,意为:用户界面
- UI由View和ViewGroup组成
- View 类是所有视图(包括ViewGroup)的根基类
- View在屏幕上占据一片矩形区域,并会在上面进行内容绘制
- ViewGroup包含一些View或ViewGroup,用于控制子View的布局
View的API结构
- 标红色的是最重要的
- 标蓝色的是次要的
UI的组成
界面的整体布局(layout)
扫描二维码关注公众号,回复: 6266379 查看本文章组成可视图面的各个UI组件(Component)
1.2 UI事件
理解UI事件
- 当用户通过手指触摸UI时,系统会自动创建对应的Event对象
- Android中提供了多种方式拦截处理不同类型的事件
- 视图本身就可以处理发生在该视图上的事件
使用UI事件
Android提供了很多不同类型的事件监听器接口
View.OnClickListener:onClick()
View.OnLongClickListener:onLongClick()
View.OnTouchListener:onTouch()
View.OnCreateContextMenuListener:onCreate()ContextMenu()
View.OnFocusChangeListener:onFocusChange()
View.OnKeyListener:onKey()
给视图添加事件监听的方式
view.seton…Listener(listener)
2. UI开发
2.1 常用UI组件
测试用例
常用的简单Component
TextView:文本视图
<TextView
android:id="@+id/tv_test1_message" //指定id
android:layout_width="match_parent" //宽度
android:layout_height="wrap_content" //高度
android:text="这是TextView的内容" //文本
android:textColor="#ff0000" //文本颜色
android:textSize="20sp" /> //字体大小
EditText:文本输入框
<EditText
android:id="@+id/et_test1_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入手机号" //默认提示文本
android:inputType="phone"> //输入数据类型限定
</EditText>
Button:按钮
<Button
android:id="@+id/btn_test1_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交" />
ImageView:图片视图
<ImageView
android:id="@+id/iv_test1_play"
android:layout_width="70dp"
android:layout_height="70dp"
android:backgroud="@drawable/ic_launcher" //背景图片
android:src="@android:drawable/ic_media_play"/> //前景图片
// 设置前景图片
public void setImageResource(int resId)
imageView.setImageResource(android.R.drawable.ic_media_pause)
// 设置背景图片
public void setBackgroundResource(int resId)
imageView.setBackgroundResource(android.R.drawable.alert_light_frame)
CheckBox:多选框
<CheckBox
android:id="@+id/cb_test1_basket"
android:layout_width="wrap_parent"
android:layout_height="wrap_content"
android:text="篮球"
android:checked="true" /> //标识默认是否勾选
// 判断当前是否勾选
boolean isChecked()
// 设置CheckBox是否勾选
void setChecked(boolean checked)
// 设置选中状态改变的监听
void setOnCheckedChangeListener(OnCheckedChangeListener listener)
RadioGroup/RadioButton:单选框
<RadioGroup
android:id="@+id/rg_test1_sex"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_test1_male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男" />
<RadioButton
android:id="@+id/rb_test1_female"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="女" />
</RadioGroup>
- 给RadioGroup设置改变的监听同CheckBox
菜单Component
OptionMenu
OptionMenu在点击手机的menu键触发
Activity:onCreateOptionsMenu(Menu menu)
- 显示OptionMenu的回调方法,在此方法中向Menu中添加MenuItem
添加MenuItem的两种方式:
纯编码方式:menu.add(...)
加载menu文件的方式:
Menulnflater menulnflater = getMenulnflater();
menulnflater.inflate(R.menu.main_option,menu);
Activity:onOptionsItemSelected(MenuItem item)
- 当选择某个菜单项的回调方法
ContextMenu:上下文菜单
- View:setOnCreateContextMenuListener(listener)
- 为某个视图添加创建ContextMenu的监听(需要长按触发)
- Activity:onCreateContextMenu(menu,view, menuInfo)
- 显示菜单的回调方法
- Activity:onCreateItemSelected(MenuItem item)
- 当选择某个菜单项的回调方法
关于Menu的3个问题
OptionMenu
如何触发Menu的显示? 点击menu键
如何向Menu中添加MenuItem? 重写onCreateOptionsMenu
a. menu.add()
/** * 用来显示optionmenu的方法:向menu中添加Item */ @override public boolean onCreateOptionsMenu(Menu menu){ //纯编码方式 menu.add(0,2,0,"添加"); menu.add(0,3,0,"删除"); return super.onCreateOptionsMenu(menu); }
b. 菜单文件
@override public boolean onCreateOptionsMenu(Menu menu){ // 菜单文件方式 // 1. 得到菜单加载器对象 MenuInflater menuInflater = getMenuInflate(); // 2. 加载菜单文件 menuInflater.inflate(R.menu.option_menu,menu); return super.onCreateOptionsMenu(menu); }
选择某个MenuItem时如何响应? 重写onOptionsItemSelected
@override public boolean onOptionsItemSelected(MenuItem item){ switch(item.getItemId()){ //case R.id.add: case 2: Toast.makeText(this,"添加",0).show(); break; //case R.id.delete: case 3: Toast.makeText(this,"删除",0).show(); break; default: break; } }
- 区别Menu和MenuItem
ContextMenu
- 如何触发Menu的显示? 长按某个视图 view.setOnCreateMenuListener(this)
- 如何向Menu中添加MenuItem?重写onCreateContextMenu(),menu.add()
- 选择某个MenuItem时如何响应? 重写onContextItemSelected(),根据itemId做响应
进度条 Component
Progressbar:进度条
<ProgressBar //默认为圆形进度条
android:id="@+id/pb_test3_loading1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/pb_test3_loading2"
sytle="?android:attr/progressBarStyleHorizontal" //水平进度条
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="2" //当前进度,默认为0
android:max="10" /> //最大进度,默认为100
ProgressBar
void setProgress(int Progress):设置当前进度 int getProgress():得到当前进度 void setMax(int max):设置最大进度 int getMax():设置或得到最大进度
View
void setVisibility(int visibility):设置视图的可见性 View.VISIBLE:标识可见 View.INVISIBLE:标识不可见,但占屏幕空间 View.GONE:标识不可见,也不占屏幕空间
SeekBar:可手动滑动的进度条
<SeekBar
android:id="@+id/sb_test3_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
SeekBar:
setOnSeekBarChangeListener(OnSeekBarChangeListener I):设置改变的监听
OnSeekBarChangeListener:
onProgressChanged(SeekBar seekBar,int progress,boolean fromUser):进度改变
onStartTrackingTouch(SeekBar seekBar):按下滑杆
onStopTrackingTouch(SeekBar seekBar):从滑杆离开
AlertDialog:警告框
AlertDialog:
show():显示警告框
AlertDialog.Builder:
create():创建AlertDialog对象
show():创建AlertDialog对象,同时将其显示出来
setTitle(CharSequence title):设置标题
setMessage(CharSequence message):设置内容
setPositiveButton(String text,OnClickListener listener):设置正面按钮
setNegativeButton(String text,OnClickListener listener):设置负面按钮
dismiss():移除dialog
setSingleChoiceItems(...):设置单选项列表
自定义AlertDialog
DialogBuilder:
setView(View view):设置Dialog中的视图
View:
View inflate(Context context,int resource,ViewGroup root):动态加载布局得到View
ProgressDialog:带进度Dialog
ProgressDialog:
static show(Context context,CharSequence title,CharSequence message):显示dialog
ProgressDialog(Context context):构造方法
setProgressStyle(int style):设置样式
ProgressDialog.STYLE_HORIZONTAL:水平进度条样式
DateDialog:日期Dialog
public DatePickerDialog(Context,context,
OnDateSetListener callBack, //点击确定的回调监听
int year, //显示年份
int monthOfYear, //显示月份
int dayOfMonth) //显示日
2.2 常用UI布局
概述
- 布局本身是不能显示出任何数据,它可以包含一些子视图,并控制子视图的布局
- 常用的Layout
- LinearLayout
- RelativeLayout
- FrameLayout
- ListView
- GridView
- 其它
LinearLayout
- 线性布局:用来控制其子View以水平或垂直方式展开显示
- 重要属性:
- orientation(方向)
- layout_weight(权重)
理解LinearLayout权重
- layout_weight(权重)的值
- =0(默认值):指定多大空间就占据多大的空间
- >0:将父视图中的可用空间进行分割,值越大权重就越大,占据的比例就越大
- Layout_weight的使用场景
- 将布局的宽度或高度平均分成几个等份
- 垂直方向上占用中间所有空间或水平方向上占用中间所有空间
RelativeLayout
- 相对布局:用来控制其子View以相对定位的方式进行布局显示
- 相对布局是最灵活,最强大,也是学习难度最大的布局
- 相对布局相关属性比较多:
- 兄弟视图之间:同方向对齐,反方向对齐
- 与父视图之间:同方向对齐,居中
FrameLayout
- 帧布局中的每一个子View都代表一个画面,默认以屏幕左上角作为(0,0)坐标,按定义的先后顺序依次逐屏显示,后面出现的会覆盖前面的画面
- 可以通过android:layout_gravity等属性来指定子视图的位置
2.3 常用视图标签属性
属性的划分
- 针对任何View的属性
- 常见的最基本属性
- 内边距属性 padding
- 外边距属性 margin
- 只针对RelativeLayout的属性
- 反方向对齐属性 to/above/below
- 同方向对齐属性 align
- 相对父视图的属性 alignparent/center
- 只针对LinearLayout的属性
- 权重属性 weight
- 方向属性 oritation
常用基本属性
属性名 | 作用 |
---|---|
id | 为控件指定相应的ID @+id/idname |
Layout_width | 指定当前视图的宽度 |
layout_height | 指定当前视图的高度 |
text | 指定控件当中显示的文字 |
textSize | 指定控制当中字体的大小 |
background | 指定该控件所使用的背景(图片|颜色) |
layout_gravity | 控件本身相对于父视图的位置 |
grivity | 指定控制中的内容的基本位置 |
内边距与外边距
- 内边距属性
- android:padding
- android:paddingLeft
- android:paddingTop
- android:paddingRight
- android:paddingBotton
- 外边距属性
- android:layout_margin
- android:layout_marginLeft
- android:layout_marginTop
- android:layout_marginRight
- android:layout_marginBottom
同方向对齐与反方向对齐
- 同方向对齐属性
- Android:layout_alignLeft
- Android:layout_alignTop
- Android:layout_alignRight
- Android:layout_alignBottom
- 反方向对齐属性
- Android:layout_toLeftOf
- Android:layout_toRightOf
- Android:layout_above
- Android:layout_below
相对父视图定位
- 与父视图同方向对齐属性
- android:layout_alignParentLeft
- android:layout_alignParentTop
- android:layout_alignParentRight
- android:layout_alignParentBottom
- 相对父视图居中属性
- android:layout_centerInParent
- android:layout_centerVertical
- android:layout_centerHorizontal
2.4 ListView
ListView理解
- ListView是一种用来显示多个可滑动项(Item)列表的VIewGroup
- 需要使用Apadater将集合数据和每一个Item所对应的布局动态适配到LisetView 中显示
- 显示列表:listView.set
Adapter
ArrayAdapter:显示最简单的列表(文本),数据集合为List
或String[] ArrayAdapter(Context context,int resource,T[] objects) ArrayAdapter(Context context,int resource,List<T> objects)
Context:上下文件对象,一般为Activity对象
resource:Item的布局文件标识
objects:需要显示的数据集合(Array或List)
SimpleAdapter:显示复杂的列表,数据集合为List<Map<String,Object>>类型
SimpleAdapter(Context context,List<? extends Map<String,?>> data,int resource,String[] from,int[] to)
- BaseAdapter:显示复杂的列表,数据集合可以是任意类型的集合<List
> - int getCount():得到集合数据的个数,决定了能显示多少行
- Object getItem(int position):根据position得到对应的数据对象
- View getView(int position, View convertView, ViewGroup parent)
//根据position返回对应的带数据的Item视图对象- position:下标
- convertView:可复用的Item视图对象
- 为null:没有可复用的,我们必须加载一个Item的布局文件,并赋值给convertView
- 不为null:直接使用此视图对象
- 后面:找到子View,找到对应的数据,设置数据
- parent:ListView
- SimpleCurosrAdapter:显示复杂的列表,数据集合是数据库查询结果集
- 给ListView的Item设置监听
- item的点击监听 :
listView.setOnItemClickListener(listener)
- item的长按监听:
listView.setOnItemLongClickListener(listener)
- item的点击监听 :
优化
- 内存中最多存在n+1个convertView对象
- 只有当convertView为null时才去加载Item的布局文件
2.5 样式和主题
样式(Style)
- 理解:
- 多个视图属性的集合,在写布局时,当多个视图有不少相同的属性时,可以把这些相同的属性放在一起在 styles.xml 中定义成一个Style,而在布局文件中使用@style/style_name统一引用
- 作用:
- 复用视力标签属性
- 目标:
- 针对的是窗口中的某些视图
- 系统样式:
- Android也定义了些系统样式可以使用
- 使用系统样式:
@android:style/xxx
主题(Theme)
- 理解:
- 主题的本质也是style
- 在styles.xml中定义,在
manifest.xml
中引用
- 作用:
- 复用视图标签属性
- 目标:
- 针对整个应用或某个Activity的界面
- 系统常用主题:
@android:style/Theme.Light.NoTitleBar
:没有标题@android:style/Theme.Light.NoTitleBar.Fullscreen
:全屏@android:style/Theme.Dialog
:对话框
3. 应用练习
3.1 显示所有应用列表
功能描述:
- 此功能是手机卫士程序管理模块的一部分
- 它以列表的形式列出手机中所有应用的信息
- 点击某一项,提示选择的应用的名称
- 长按某一项,删除当前行
主要技术:
- 应用的整体布局与Item的布局
- 获取手机中所有安装的应用信息集合(已定义)
- 使用BaseAdapter显示列表信息
- ListView的item点击响应
scaleType="fitXY" //图片充满View的宽度 minHeight="70dp"//最小高度
3.2 手机卫士主界面
功能描述:
- 此功能是手机卫士主界面功能的一部分
- 以3*3网格的形式显示功能模块列表
- 点击某一项,提示选择的功能模块的名称
主要技术:
- 应用的整体布局与Item的布局
- 利用BaseAdapter在GridView中网格列表信息
- GridView的item点击响应
numColumns="3"//列数 verticalSpacing="10dp" //item之间在垂直方向的间距