一、UI的理解
全称user interface, 意为: 用户界面
UI由View和ViewGroup组成? ? ? ?
View类是所有视图(包括ViewGroup)的根基类
View在屏幕上占据一片矩形区域, 并会在上面进行内容绘制
ViewGroup包含一些View或ViewGroup, 用于控制子View的布局
ViewGroup与View是父子关系
二、UI事件
当用户通过手指触摸UI时, 系统会自动创建对应的Event对象
Android中提供了多种方式拦截处理不同类型的事件
视图本身就可以处理发生在该视图上的事件
Android提供了很多不同类型的事件监器听接口:
View.OnClickListener: onClick()
View.OnLongClickListener: onLongClick()
View.OnTouchListener: onTouch()
View.OnCreateContextMenuListener: onCreateContextMenu()
View.OnFocusChangeListener: onFocusChange()
View.OnKeyListener: onKey()
设置监听器:view.seton...Listneer(listener)
三、简单的UI组件
常用的UI组件
TextView:文本视图
EditText:可编辑的文本视图
Button:按钮
ImageView:图片视图
android:background="@drawable/ic_launcher"//背景图片 图片和视图一样大
android:src=""//前景图片 原来大小 前景图片如果比背景图片大 会覆盖背景图片
CheckBox:多选框
RadioGroup/RadioButton:单选框 线性布局
Toast 文本小提示
View:视图隐藏/显示的方法
void setVisibility(int visibility) : 设置视图的可见性
View. VISIBLE : 标识可见
View. INVISIBLE : 标识不可见, 但占屏幕空间
View.GONE : 标识不可见, 也不占屏幕空间
四.菜单Menu
a.OptionMenu
1.如何触发Menu的显示?
点击手机的menu键触发
2.如何向Menu中添加MenuItem?
重写onCreateOptionMenu()
纯编码方式:menu.add()
3.加载菜单文件的方法:
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main_option, menu);
4.选择某个MenuItem时如何响应?
重写onOptionsitemSelected(),根据itemid做响应
b、contentMenu
1.如何触发Menu的显示?
长按某个视图
view.setOnCreateContextMenuListener(this)
2. 为某个视图添加创建ContextMenu的监听(需要长按触发)
如何向Menu中添加MenuItem?
重写onCreateContextMenu(menu,view,menuinfo)
3.显示菜单的回调方法
menu.add
4.选择某个MenuItem时如何响应?
重写onContextitemSelected(Menultem item),根据itemid做响应
* 测试Menu * @author Administrator */ /* * OptionMenu *1.如何触发Menu的显示?点击menu建 *2.如何向menu中添加MenuItem?重写onOptionsItemSelected * 1)menu.add() * 2)菜单文件 *3.选择某个MenuItem时如何响应?重写onOptionsItemSelected * *ContextMenu *1.如何触发Menu的显示?长按摸个视图view.setOnCreateContextMenuListener(this) *2.如何向Menu中添加MenuItem? 重写OnCreateContextMenu(),menu.add() *3.选择某个MenuItem时如何响应?重写onContextItemSelected(),根据itemId作响应 */ public class MenuActivity extends Activity { private Button btn_menu; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_menu); btn_menu = (Button)findViewById(R.id.btn_menu); btn_menu.setOnCreateContextMenuListener(this); } @Override //长按触发菜单 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); //添加菜单选项 /** * groupId:分组 * itemId:id * order:排序 * title:标题 */ //menu.add(groupId, itemId, order, title) menu.add(0, 1, 0, "添加"); menu.add(0, 2, 0, "删除"); } @Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()){//获取当前点击的菜单id //case R.id.add: case 1: Toast.makeText(this, "添加", 0).show();//显示 break; //case R.id.delete: case 2: Toast.makeText(this, "删除", 0).show(); break; default: break; } return super.onContextItemSelected(item); } @Override //用来显示optionMenu:向menu中添加item public boolean onCreateOptionsMenu(Menu menu) { //纯编码方式 menu.add(0, 1, 0, "添加"); menu.add(0, 2, 0, "删除"); /*MenuInflater menuinf = getMenuInflater(); menuinf.inflate(R.menu.option_menu, menu);//加载菜单文件*/ return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //case R.id.add: case 1: Toast.makeText(this, "添加", 0).show(); break; //case R.id.delete: case 2: Toast.makeText(this, "删除", 0).show(); break; default: break; } return super.onOptionsItemSelected(item); } }
五、进度条
a.ProgressBar下的方法:
1.void setProgress(int Progress) : 设置当前进度
2.int getProgress() : 得到当前进度
3.void setMax(int max) : 设置最大进度
4.int getMax() : 设置或得到最大进度
5.圆形
6.水平
b.SeekBar
六、对话框
API结构
a.AlertDialog
1一般的
show():显示警告框
没有公开的构造方法,中能通过其内部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 * @param v */ public void showAD1(View v){ new AlertDialog.Builder(this) .setTitle("删除数据")//设置标题 .setMessage("你确定要删除吗")//设置内容 .setPositiveButton("删除",new DialogInterface.OnClickListener() {//设置正面按钮 @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(DialogActivity.this, "删除数据", 0).show(); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() {//设置负面按钮 @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(DialogActivity.this, "取消删除数据", 0).show(); } }) .show();//方法链调用 }
2.自定义布局
动态加载布局文件得到对应的View对象
View inflate(Context context, int resource, ViewGroup root) : 动态加载布局得到View
设置View
setView(View view) : 设置Dialog中的视图
/** * 显示自定义AlertDialog * @param v */ public void showAD3(View v){ //动态加载布局 得到对应的view对象 //问题1: view的真实类型?是布局文件的根标签类型,包含子view对象 //问题2: 如何得到一个独立view的子view? view.findViewId(id) //findViewId(id)是在setContentView()中找 View view = View.inflate(this, R.layout.dialog_view, null); final EditText nameET = (EditText)view.findViewById(R.id.ed_dialog_name); final EditText pwdET = (EditText)view.findViewById(R.id.ed_dialog_pwd); new AlertDialog.Builder(this) .setView(view) .setPositiveButton("确定",new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String name = nameET.getText().toString(); String pwd = pwdET.getText().toString(); Toast.makeText(DialogActivity.this, "用户名:"+name+" ,密码:"+pwd, 0).show(); } }) .setNegativeButton("取消", null) .show(); }
3.带单选列表的
/** * 显示单选列表AlertDialog * @param v */ public void showAD2(View v){ final String[] items = {"红","绿","蓝","黑"};//当局部变量定义了final时,此变量不会随着方法执行完毕而消失 new AlertDialog.Builder(this) .setTitle("指定背景颜色") .setSingleChoiceItems(items, 2, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) {//which为数组下标 Toast.makeText(DialogActivity.this, items[which], 0).show(); dialog.dismiss(); } }) .show(); }
4.圆形进度
static show(Context context, CharSequence title,CharSequence message) : 显示dialog
/** * 显示圆形进度ProgressDialog * @param v */ public void showPD1(View v){//回调方法:在主线程执行 final ProgressDialog dialog = ProgressDialog.show(this, "数据加载", "数据加载中..."); //模拟做一个长时间的工作需要在分线程完成,不能在主线程完成 new Thread(){ public void run() {//分线程 for(int i=0;i<20;i++){ try { Thread.sleep(100);//睡2秒 } catch (InterruptedException e) { e.printStackTrace(); } } //移除dialog dialog.dismiss();//在分线程执行,但内部使用Hander实现主线程移除dialog //不能在分线程更新UI //显示Toast runOnUiThread(new Runnable() { @Override public void run() {//在主线程执行 Toast.makeText(getApplicationContext(), "加载完成!!!", 0).show(); } }); //runOnUiThread()在分线程执行 //Runnable()中的run()方法要在满足以下条件时才会在分线程执行 /*new Thread(new Runnable() { @Override public void run() {//此时的run方法才会在分线程执行 }}).start();*/ } }.start(); }
5.水平进度
ProgressDialog(Context context) : 构造方法
setProgressStyle(int style) 设置样式
ProgressDialog.STYLE_HORIZONTAL :水平进度条样式
/** * * 显示水平进度ProgressDialog * @param v */ public void showPD2(View v){ //1.创建dialog对象 final ProgressDialog pd = new ProgressDialog(this); //2.设置样式 pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //3.显示 pd.show(); //4.启动分线程,加载数据,并显示进度,当加载完成时移除dialog new Thread(new Runnable(){ @Override public void run() { int count =20; pd.setMax(count); for(int i=0;i<count;i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //设置进度 pd.setProgress(pd.getProgress()+1); } //移除dialog pd.dismiss(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "加载完成!!!", 0).show(); } }); } }).start(); }
5.DateDialog
//创建日历对象
Calendar calendar = Calendar.getInstance();
//得到当前的年月日
final int year = calendar.get(Calendar.YEAR);//得到年份
final int monthOfYear = calendar.get(Calendar.MONTH);//月
final int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);//得到日
/** * * 显示DatePickerDialog * @param v */ public void showDPD(View v){ Calendar c = Calendar.getInstance();//获取日历对象 int year = c.get(Calendar.YEAR);//获取年份 int month = c.get(Calendar.MONTH);//获取月份 int day = c.get(Calendar.DAY_OF_MONTH);//获取天数 new DatePickerDialog(this, new OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int month, int day) { Toast.makeText(getApplicationContext(), "当前时间:"+year+"-"+month+"-"+day, 0).show(); } }, year, month, day).show(); }
6.TimeDialog
Calendar c = Calendar.getInstance();
int hourOfDay = c.get(Calendar.HOUR_OF_DAY); //得到小时
int minute = c.get(Calendar.MINUTE); //得到分钟
/** * * 显示TimePickerDialog * @param v */ public void showTPD(View v){ Calendar c = Calendar.getInstance();//获取日历对象 int hour = c.get(Calendar.HOUR_OF_DAY);//获取时间 int minute = c.get(Calendar.MINUTE);//获取分钟 new TimePickerDialog(this, new OnTimeSetListener() { @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) { Toast.makeText(getApplicationContext(), "当前时间"+hourOfDay+":"+minute, 0).show(); } }, hour, minute, true).show(); }
启动分线程
根据id查找View对象
a.查找当前界面中的view对象
this.findViewById(id)
b.查找某个view对象的子view
view.findViewById(id)
更新视图
a.不能在分线程直接更新UI
Toast不能在分线程显示
但ProgressDialog可以在分线程更新(因为它的内部使用了Hander)
b.长时间的工作只能在分线程执行(如果在主线程执行会导致用户的操作无法响应)