03_用户界面

03_用户界面

常见的异常

  1. NullPointException

    原因:调用对象的方法/属性,但对象为null

  2. ClassCastException

    原因:类型转换异常

  3. ActivityNotFoundException

    原因:没有注册Activity,或注册不正确

基本常见异常的一般分析步骤

  1. 在logcat中从下向上找,尽量找到causeBy(会显示哪种异常导致的)
  2. 找到出异常的类及行号,点击进入对应的行

1. 理论概述

1.1 理解UI

UI的定义

  • 全称User Interface,意为:用户界面
  • UI由ViewViewGroup组成
  • 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
  1. 如何触发Menu的显示? 点击menu键

  2. 如何向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);
        }
  3. 选择某个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
  1. 如何触发Menu的显示? 长按某个视图 view.setOnCreateMenuListener(this)
  2. 如何向Menu中添加MenuItem?重写onCreateContextMenu(),menu.add()
  3. 选择某个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)

优化

  1. 内存中最多存在n+1个convertView对象
  2. 只有当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之间在垂直方向的间距

猜你喜欢

转载自www.cnblogs.com/zhaye/p/10837946.html