Android用户界面

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


posted @ 2016-11-28 20:50  asc  阅读(725)  评论(0编辑  收藏  举报