安卓学习-第四章-UI view

261 阅读5分钟

第一行代码第四章主要介绍了常用控件和常用布局的使用方式。

思考:既然打算尝试写博客,作为开发小白一开始的内容只能是搬运的书本,而这些基础琐碎的知识点在官方文档和其他的书本都比比皆是,那我记录这些东西的意义有多大呢?如何才能不只是书本的搬运工,这是我作为一个开发和博客新手面临的问题。

基础控件

对于基础控件,只记录他的名称和其较为特有的设置。

控件共有属性

  • android.layout_width
  • android.layout_height
  • android.id
  • android.visibility: 可设置为 VISIBLE/INVISIBLE/GONE

TextView

  • android.text 设置文本内容
  • android.gravity 文本对齐方式(默认为左上角对齐)
  • android.textColor 字体颜色
  • android.textSize 字体大小

Button

  • android.textAllCaps 设置按钮上英文是否全部大写
  • 添加onClickListener: 对Button设置setOnClickListener或者继承View.onClickListener接口并实现函数onClick

EditText

  • android.hint 设置提示性文字
  • android.maxLine 设置最大显示行数
  • 获取text中内容:editTextView.text.toString(),利用Kotlin语法糖简化getText()函数

在实践中发现无法通过实现onClick()函数实现监听了,因为没有了对应注解

ImageView

  • android.src 指定展示的图片
  • 通过代码动态更改ImageView中的图片:imageView.setImageResource(newResource)

ProcessBar

  • android.style 调整进度条形态
  • 设置进度显示:android.max 设置总进度+通过progressBarView.progress设置当前进度

AlertDialog

AlterDialog可在当前界面上弹出对话框并屏蔽其他交互控件,一般用于警告或提示。另外,这种View是要在Activity的代码中设置的,一般用于响应某种情况下的交互。

三种基本布局

布局layout是一种用于放置各种空间的容器,其继承自UI类ViewViewGroup,且布局的内部也可放置布局形成嵌套。

LinearLayout

将所有控件在线性方向上排列

  • android.orientation 设置排列的方向,要注意内部控件的width和height的设置 内部控件的设置
  • android.layout_gravity 设置内部控件在布局中的对齐方式
  • android.layout_weight 通过比例的形式这只内部控件的黛奥

RelativeLayout

通过相对定位的方式让控件出现在布局的任何位置。

内部控件的设置:

  1. 相对上层View
  • android.alignParentTop
  • android.alignParentBottom
  • android.alignParentLeft
  • android.alignParentRight
  • android.centerInParent

2,相对内部其他控件

  • android.layout_above
  • android.layout_below
  • android.layout_toLeftOf
  • android.layout_toRightOf
  • android.layout_alignLeft
  • android.layout_alignRight
  • android.layout_alignTop
  • android.layout_alignBottom

FrameLayout

控件默认摆放在左上角,可通过android.layout_gravity摆放控件

自定义控件

  • 通过引入布局的方式引入常用的空间布局,从而减少重复代码。(include)
  1. 创建布局,例如标题栏布局title.xml。在布局中放置一组控件。
  2. 在主layout中引入该布局。即添加代码<include layout="@layout/title" />
  • 创建自定义控件,单独编写事件注册代码,减少逻辑代码的重复。
  1. 新建布局类TitleLayout并继承LinearLayout
  2. 在TitleLayout类中通过init{LayoutInflater}的方式在初始化阶段动态加载布局R.layout.title,即方法一中的没有设置监听的标题栏布局
  3. 在主Layout中加入TitleLayout控件(布局)。
  4. 在TitleLayout类中添加对控件的监听。(通过context as Activity的方式获取对Activity的控制)

Screen Shot 2021-03-18 at 10.19.37 PM.png

复杂控件

接下来介绍两种用于滚动展示的复杂控件,控件内部会包含子项控件。

ListView

ListView是一种用来滑动展示数据的控件,但集合中的数据无法直接传递给它,需要借助适配器完成,下面以ArrayAdapter为例展示定制ListView的流程。

  1. 定义展示的实体类: Fruit
  2. 自定义ListView的子项item布局:fruit_item.xml
  3. 创建自定义适配器FruitAdapter并继承父类ArrayAdapter,重写getView()方法,通过LayoutInflater获取fruit_item布局的控制,并使用FruitList,position绑定布局中的控件与资源。
  4. 在Activity代码中初始化FruitList与FruitAdapter,随后将ListView的adapter设置为FruitAdapter。

Screen Shot 2021-03-19 at 10.32.28 AM.png

ListView的效率优化

  1. 使用convertView在函数getView()中复用之前加载好的缓存布局,从而避免多次使用LayoutInflater
  2. 自定义内部类inner class ViewHolder用于缓存内部控件实例,将viewHolder存储在view.tag中并使用viewHolder对内部控件进行操作,从而减少findViewById()的调用。

ListView的点击事件

  • 使用ListView.setOnItemClickListener()方法和四大参数{parent, view, position, id}进行操作。

RecyclerView

相较于ListView,RecyclerView可以实现更灵活的多方向的滑动展示,并且通过内置viewHolder提高了运行效率,同时使控制逻辑更加清晰。

RecyclerView的基本使用流程

  1. 在项目的build.gradle中添加dependency
  2. 在主layout中加入控件<androidx.recyclerview.widget.RecyclerView>
  3. 为RecyclerView准备适配器,新建类FruitAdapter并继承自RecyclerView.Adapter
  4. 在MainActivity中初始化数据,为recyclerView指定layoutManager从而确定滑动方式,为recyclerView创建并指定adapter。

Adapter

我认为Adapter就是为滑动控件RecyclerView指定子控件或布局item,并对item中的控件添加配置,例如监听器,随后通过ViewHolder等方式提高运行效率。

  1. 在适配器类FruitAdapter中自定义内部类inner class viewHolder并继承RecyclerView.ViewHolder,用于存放item中的控件
  2. onCreateViewHolder中通过LayoutInlfater加载子布局item,随后通过itemView初始化ViewHolder
  3. onBindViewHolder中根据holder和position将List中的数据加载入item的子控件中。

LayoutManager

在RecyclerView中,通过指定Layoutmanager指定布局的排列方式。常用的内置布局方式有LinearLayoutManagerGridLayoutManagerStaggeredGridLayoutManager

RecyclerView的点击事件

在RecyclerView中需要自定义View的点击注册事件,也就是在Adapter的onCreateViewHolder()中,在完成初始化viewHolder后,通过viewHolder子控件设置Listenre。

The priority of listener

from StackOverFlow: Only one listener work at a time, the deeptest child get the priority over it's parents.

对比ListView与RecyclerView的不同

ListViewRecyclerView
前置依赖需要
布局管理自身管理LayoutManager
加载布局方式重写getView()重写onCreateViewHolder()
控件获取findViewById()viewHolder.targetView
点击事件listView.setItemListener()viewHolder.button.setOnClickListener

对最佳实战的分析

实战中创建了类似微信聊天的对话框,那么如何在一个RecyclerView中动态加载两种item布局就成了主要问题。 解决步骤:

  1. 在基础类Msg中设置常量TYPE用于指定消息的类型RECEIVED/SENT。
  2. 在RecyclerView的适配器MsgAdapter中创建两种ViewHolder分别用于缓存left_item.xml和right_item.xml布局中的控件。
  3. 重写getItemViewType(position: Int)函数,返回msgList[positon]中Msg的TYPE
  4. onCreateViewHolder()函数中根据viewType创建对应的ViewHolder
  5. onBindViewHolder中根据holder的类型(LeftViewHolder/RightViewHolder)和Msg设置内部控件。