一、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(); }
/** * 显示单选列表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
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.长时间的工作只能在分线程执行(如果在主线程执行会导致用户的操作无法响应)