完整代码Gitee地址:kotlin-demo: 15天Kotlin学习计划

第三天学习内容代码:Chapter3

目录

知识点1:公共标题栏

知识点2:自定义标题栏控件

知识点3:RecyclerView

①标准写法

②使用框架

知识点4:编写精美的聊天对话界面

①标准写法-多布局

②使用框架-多布局


知识点1:公共标题栏

市场上应用的界面顶部有一个标题栏,标题栏上会有一到两个按钮可用于返回或其他操作(iPhone没有专门的返回键)。虽然Android系统已经给每个Activity提供了标题栏功能,但样式有很大局限性,我们自定义一个标题栏,新建item_title布局。

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="wrap_content"app:cardBackgroundColor="@color/purple_500"app:cardElevation="2dp"app:cardMaxElevation="0dp"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="56dp"><LinearLayoutandroid:id="@+id/lly_back"android:layout_width="wrap_content"android:layout_height="match_parent"android:padding="15dp"android:orientation="horizontal"><ImageViewandroid:layout_width="25dp"android:layout_height="25dp"android:src="@mipmap/img_return_withe"/></LinearLayout><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/white"android:layout_centerVertical="true"android:layout_centerHorizontal="true"android:textSize="18sp"android:textStyle="bold"android:text="标题"/><TextViewandroid:visibility="invisible"android:id="@+id/tv_right_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/white"android:layout_centerVertical="true"android:layout_alignParentRight="true"android:textSize="16sp"android:padding="12dp"android:text="确定"/></RelativeLayout>
</androidx.cardview.widget.CardView>

在activity_learn3布局中引用:

<include layout="@layout/item_title"/>

运行效果如下:

可以看到,我们在LinearLayout中分别加入了两个TextView和一个LinearLayout包裹ImageView,左边的LinearLayout可用于返回,右边的TextView可用于编辑,中间的TextView则可以显示一段标题文本。

知识点2:自定义标题栏控件

引入布局的技巧确实解决了重复编写布局代码的问题,但是如果布局中有一些控件要求能够响应事件,我们还是需要在每个Activity中为这些控件单独编写一次事件注册的代码。比如标题栏中的返回按钮,其实不管是在哪一个Activity中,这个按钮的功能都是相同的,即销毁当前Activity。而如果在每一个Activity中都需要重新注册一遍返回按钮的点击事件,无疑会增加很多重复代码,这种情况最好是使用自定义控件的方式来解决。

新建TitleLayout继承自LinearLayout,代码如下:

class TitleLayout(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {//init结构体中需要对标题栏布局进行动态加载init {val view = LayoutInflater.from(context).inflate(R.layout.item_title, this)//为标题栏中的按钮注册点击事件val llyBack: LinearLayout = view.findViewById(R.id.lly_back)llyBack.setOnClickListener {val activity = context as Activityactivity.finish()}}
}

现在自定义控件已经创建好了,接下来我们需要在布局文件中添加这个自定义控件,修改activity_learn3.xml中的代码,如下所示:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!-- <include layout="@layout/item_title"/> --><com.example.kotlin_demo.TitleLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout>

重新运行程序,和使用引入布局方式的效果是一样的。

知识点3:RecyclerView

ListView由于强大的功能,在过去的Android开发当中可以说是贡献卓越,直到今天仍然还有不计其数的程序在使用ListView。不过ListView并不是完美无缺的,比如如果不使用一些技巧来提升它的运行效率,那么ListView的性能就会非常差。还有,ListView的扩展性也不够好,它只能实现数据纵向滚动的效果,如果我们想实现横向滚动的话,ListView是做不到的。

它可以说是一个增强版的ListView,不仅可以轻松实现和ListView同样的效果,还优化了ListView存在的各种不足之处。目前Android官方更加推荐使用RecyclerView:

新建item_rcy_cont作为RecyclerView每项Item局部:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp"><ImageViewandroid:id="@+id/iv_herd"android:layout_width="70dp"android:layout_height="70dp"android:layout_marginStart="5dp"android:layout_marginLeft="5dp"tools:srcCompat="@tools:sample/avatars" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:orientation="vertical"><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="0dp"android:layout_weight="1"android:gravity="center"android:textSize="15sp"android:text="姓名:" /><TextViewandroid:id="@+id/tv_phone"android:layout_width="wrap_content"android:layout_height="0dp"android:layout_weight="1"android:gravity="center"android:textSize="15sp"android:text="电话:" /></LinearLayout></LinearLayout>

新建实体类UserBean,作为数据存储映射实体:

class UserBean(val herd: Int, val name: String, val phone: String)

修改activity_learn3.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:tools="http://schemas.android.com/tools"android:orientation="vertical"><com.example.kotlin_demo.TitleLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"/><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"tools:listitem="@layout/item_rcy_cont"/>
</LinearLayout>

预览效果如下:

①标准写法

接下来需要为RecyclerView准备一个适配器,新建UserAdapter类,让这个适配器继承自RecyclerView.Adapter,并将泛型指定为UserAdapter.ViewHolder。其中,ViewHolder是我们在UserAdapter中定义的一个内部类,代码如下所示:

//让这个适配器继承自RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder。
class UserAdapter(private val userList: List<UserBean>) :RecyclerView.Adapter<UserAdapter.ViewHolder>() {//内部类绑定控件inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {val nameText: TextView = view.findViewById(R.id.tv_name)val phoneText: TextView = view.findViewById(R.id.tv_phone)val ivHerd: ImageView = view.findViewById(R.id.iv_herd)}//创建布局override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {val view =LayoutInflater.from(parent.context).inflate(R.layout.item_rcy_cont, parent, false)return ViewHolder(view)}//展示布局数量override fun getItemCount(): Int {return userList.size}//给控件赋值与样式override fun onBindViewHolder(holder: ViewHolder, position: Int) {holder.nameText.text = userList[position].nameholder.phoneText.text = userList[position].phoneholder.ivHerd.setImageResource(userList[position].herd)}
}

虽然看上去好像多了好几个方法,但其实它比ListView的适配器要更容易理解。适配器准备好了之后,我们就可以开始使用RecyclerView了,修改Learn3Activity中的代码,如下所示:

class Learn3Activity : BaseActivity() {private val userList = ArrayList<UserBean>()private lateinit var mAdapter: UserNewAdapteroverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_learn3)//3、RecyclerView控件recyclerView()}private fun recyclerView() {//初始化用户数据initUser()val recyclerView: RecyclerView = findViewById(R.id.recyclerView)//①标准写法,使用适配器recyclerView.layoutManager = LinearLayoutManager(this)recyclerView.adapter = UserAdapter(userList)}private fun initUser() {repeat(2) {userList.add(UserBean(R.mipmap.image_nv,"迪丽不热", "17321341289"))userList.add(UserBean(R.mipmap.image_nan,"杀手不冷", "17377621412"))userList.add(UserBean(R.mipmap.image_nv,"赵思露", "19987878221"))userList.add(UserBean(R.mipmap.image_nv,"井川里予", "13612344637"))userList.add(UserBean(R.mipmap.image_nan,"阿斯顿", "13635465678"))userList.add(UserBean(R.mipmap.image_nan,"没啥用科技", "13801940921"))userList.add(UserBean(R.mipmap.image_nv,"阿瑟东", "16622348923"))}}
}

这里使用了initUser()方法,用于初始化所有的用户数据。接着在onCreate()方法中先创建了一个LinearLayoutManager对象,并将它设置到RecyclerView当中。LayoutManager用于指定RecyclerView的布局方式,这里使用的LinearLayoutManager是线性布局的意思,可以实现和ListView类似的效果。接下来我们创建了UserAdapter的实例,并将水果数据传入UserAdapter的构造函数中,最后调用RecyclerView的setAdapter()方法来完成适配器设置,这样RecyclerView和数据之间的关联就建立完成了。现在运行一下程序,如下所示。

当然这只是RecyclerView的基本用法而已,还有更多用法,比如实现横向滚动和瀑布流布局,这个也并不复杂,与Java写法类似。

②使用框架

BaseRecyclerViewAdapterHelper是一个比较成熟的框架,代码书写简洁很大提升开发效率,接下来我们用Kotlin写法使用它,在app目录下的build.gradle添加依赖:

/* 灵活的RecyclerView框架 */
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'

创建适配器UserNewAdapter:

class UserNewAdapter :BaseQuickAdapter<UserBean, BaseViewHolder>(R.layout.item_rcy_cont) {override fun convert(holder: BaseViewHolder, item: UserBean) {//获取控件IDval icon = holder.getView<ImageView>(R.id.iv_herd)//展示图片icon.setImageResource(item.herd)//直接设置文本内容holder.setText(R.id.tv_name, item.name)holder.setText(R.id.tv_phone, item.phone)}
}

适配器准备好了之后,我们就可以开始使用RecyclerView了,修改Learn3Activity中的代码,如下所示:

private fun recyclerView() {//初始化用户数据initUser()val recyclerView: RecyclerView = findViewById(R.id.recyclerView)//②使用框架,BaseRecyclerViewAdapterHelpermAdapter = UserNewAdapter()recyclerView.layoutManager = LinearLayoutManager(this)recyclerView.adapter = mAdaptermAdapter.addData(userList)//添加数据
}

总体来看框架写法更简单,运行效果与标准写法一样。

知识点4:编写精美的聊天对话界面

下面我们来编写一个聊天界面,需要用到.9图片,如何制作这里不做讲解,图片资源可去顶部gitee获取。我们在主界面中放置了一个RecyclerView用于显示聊天的消息内容,定义消息的实体类,新建MsgBean,代码如下所示:

//content表示消息的内容,type表示消息的类型
class MsgBean(val content: String, val itemType: Int) {companion object {//定义常量的关键字是const//表示这是一条收到的消息const val TYPE_LEFT = 0//表示这是一条发出的消息const val TYPE_RIGHT = 1}
}

MsgBean类中只有两个字段:content表示消息的内容,type表示消息的类型。其中消息类型有两个值可选:TYPE_LEFT 表示这是一条收到的消息,TYPE_RIGHT表示这是一条发出的消息。定义常量的关键字是const,注意只有在单例类、companion object或顶层方法中才可以使用const关键字。

新建子项布局,左边显示item_msg_left.xml,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp"android:background="#e8e8e8"><ImageViewandroid:layout_width="40dp"android:layout_height="40dp"android:layout_marginLeft="5dp"android:layout_marginStart="5dp"android:src="@mipmap/image_nv"/><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginStart="5dp"android:gravity="center"android:background="@drawable/item_msg_left_selector"><TextViewandroid:id="@+id/tv_left"android:layout_width="wrap_content"android:layout_height="wrap_content"android:maxWidth="240dp"android:layout_marginLeft="12dp"android:layout_marginRight="10dp"android:text="您好!"android:textSize="15sp"/></LinearLayout></LinearLayout>

预览效果:

新建子项布局,右边显示item_msg_right.xml,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp"android:background="#e8e8e8"><LinearLayoutandroid:layout_toLeftOf="@+id/iv_right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="5dp"android:gravity="center"android:background="@drawable/item_msg_right_selector"><TextViewandroid:id="@+id/tv_right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:maxWidth="240dp"android:layout_marginLeft="12dp"android:layout_marginRight="12dp"android:text="您好!"android:textSize="15sp"/></LinearLayout><ImageViewandroid:id="@+id/iv_right"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginRight="5dp"android:layout_alignParentRight="true"android:src="@mipmap/image_nan" /></RelativeLayout>

预览效果:

①标准写法-多布局

接下来需要创建RecyclerView的适配器类,新建类MsgAdapter,代码如下所示:

class MsgAdapter(private val msgList: List<MsgBean>) :RecyclerView.Adapter<RecyclerView.ViewHolder>() {inner class LeftViewHolder(view: View) : RecyclerView.ViewHolder(view) {val leftMsg: TextView = view.findViewById(R.id.tv_left)}inner class RightViewHolder(view: View) : RecyclerView.ViewHolder(view) {val rightMsg: TextView = view.findViewById(R.id.tv_right)}override fun getItemViewType(position: Int): Int {return msgList[position].itemType}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):     RecyclerView.ViewHolder {return when (viewType) {MsgBean.TYPE_LEFT ->LeftViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_msg_left, parent, false))MsgBean.TYPE_RIGHT ->RightViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_msg_right, parent, false))else -> throw IllegalArgumentException()}}override fun getItemCount(): Int {return msgList.size}override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {val msg = msgList[position]when (holder) {is LeftViewHolder -> holder.leftMsg.text = msg.contentis RightViewHolder -> holder.rightMsg.text = msg.contentelse -> throw IllegalArgumentException()}}}

上述代码中用到了一个新的知识点:根据不同的viewType创建不同的界面。首先我们定义了LeftViewHolder和RightViewHolder这两个ViewHolder,分别用于缓存msg_left_item.xml和msg_right_item.xml布局中的控件。然后要重写getItemViewType()方法,并在这个方法中返回当前position对应的消息类型。

最后修改Learn3Activity中的代码:

class Learn3Activity : BaseActivity() {private val msgList = ArrayList<MsgBean>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_learn3)//4、编写精美的聊天对话界面val tvTitle: TextView = findViewById(R.id.tv_title)tvTitle.text = "聊天室"recyclerNewView()}private fun initMsg() {repeat(1) {msgList.add(MsgBean("在吗?还记得我吗?",0))msgList.add(MsgBean("当然,初中坐我前排的班花,那时候我还扯过你的肩带",1))msgList.add(MsgBean("有啥事吗?",1))msgList.add(MsgBean("能借我200块钱吗",0))msgList.add(MsgBean("其实从初中开始我就一直暗恋你,没好意思跟你说,我们在一起吧",1))msgList.add(MsgBean("别吧												

Kotlin开发第三天,UI开发相关推荐

  1. 电商生鲜网站开发(三)——后台开发:商品分类模块-Redis/Swagger/统一身份校验/IDEA技巧

    电商生鲜网站开发(三)--后台开发:商品分类模块-Redis/Swagger/统一身份校验/IDEA技巧 分类层级 在商品分类上需要继续做归类操作 分类设置成三级 层级太深的弊端:对用户不友好,不利于 ...

  2. php三种web开发技术,三种WEB开发主流技术ASP-PHP-JSP的评价

    三种Web开发主流技术ASP-PHP-JSP的评价 [摘要]本文从程序开发者的角度,对现今社会盛行的WEB开发技术进行了分析,旨在让WEB 开发人员.使用者.准备学习的人对WEB开发技术有更加深入的了 ...

  3. 【Android -- UI开发】一份 UI 开发学习指南

    思维导图 推荐资料:官方文档 六大布局 网上有人比喻的很好:布局好比是建筑里的框架,组件按照布局的要求依次排列,就组成了用于看见的漂亮界面了. 请看文章:[Android – UI 开发]六大布局 U ...

  4. 第一行代码学习笔记第三章——UI开发的点点滴滴

    知识点目录 3.1 如何编写程序界面 3.2 常用控件的使用方法 * 3.2.1 TextView * 3.2.2 Button * 3.2.3 EditText * 3.2.4 ImageView ...

  5. STM32开发 -- LIS3DH三轴加速度计开发详解

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/87096085 这次要讲一下LIS3DH三轴加速度计的开发使用,之前是有讲过 ...

  6. ionic开发笔记三:ionic开发时候需要用到的网址

    首先最主要,最常用的onic官方网站: http://ionicframework.com/docs/v2/api/ ionic中文社区: http://ionichina.com/ github官网 ...

  7. 农村信息综合展示平台(微信网页)项目开发笔记三——朋友圈开发遇到的问题

    本篇记录在朋友圈功能页面中实现图片点击放大查看的功能,遇到了的问题 本系统是使用Vux库因此,为实现查看图片的功能就使用了Vux自带的Previewer,如何使用在这里就不多说,之间查看Vux文档. ...

  8. python django开发api_基于Django框架开发Restful api

    在上篇文章中,我们讲解了restful api的主要概念,让大家有初步的了解.这一篇中,我们将通过python的Django框架,来学习开发restful 架构的接口. 一. 开发环境 开发语言:Py ...

  9. Android UI开发第三十九篇——Tab界面实现汇总及比较

    Tab布局是iOS的经典布局,Android应用中也有大量应用,前面也写过Android中TAb的实现,<Android UI开发第十八篇--ActivityGroup实现tab功能>.这 ...

  10. Android UI开发第三十篇——使用Fragment构建灵活的桌面

    http://www.lupaworld.com/article-222973-1.html 当我们设计应用程序时,希望能够尽最大限度的适配各种设备,包括4寸屏.7寸屏. 10寸屏等等,Android ...

最新文章

  1. TinyXml高速入门(一)
  2. python进行对应分析_机器学习算法---对应分析
  3. vue动态加载静态资源
  4. 以太坊扩容项目 Arbitrum 放弃专利,即将上线主网
  5. 大学java怎么算学得好_为什么现在大学里很多计算机系的大学生,学编程的时候总学不好...
  6. django中admin路由系统工作原理
  7. 抽象代数的人间烟火——北航李尚志
  8. Qcom平台添加一款新的sensor (msm8953)
  9. mac系统Airtest环境安装教程
  10. 恋爱测试题测男生软件,男友求生欲测试题大全
  11. 学习编程到底用不用记笔记?
  12. CVPR 2022 部分行人重识别
  13. 基于SONY ICX694的4通道成像组件设计与调试
  14. Vue-3-单文件组件
  15. Ubuntu18.04 中的文件管理器
  16. 机器学习7 - 算法进阶2
  17. 写在回家前的最后一夜
  18. MNS(非极大值抑制)python实现
  19. 创业失败身无分文,还欠债累累,靠父母的工资来生活,心情烦乱,我该何去何从?...
  20. linux防火墙关闭指定端口外界可访问命令

热门文章

  1. GRBL v1.1版本的介绍
  2. LiveGBS GB28181流媒体服务-产品介绍及相关资源
  3. [电源系列]一、BUCK与BOOST电路的占空比计算
  4. 利用计算机技术执行去自动化,电力调度运行中计算机技术的应用价值与效果
  5. 如何用企业微信、飞书等扫码登录 Office 365
  6. 杜比全景声深受好莱坞青睐
  7. Linux与Shell学习1--Linux简介
  8. 阿里云ECS训练营第三天——微信公众号管理系统
  9. Mac 卸载应用程序(AppCleaner)
  10. APIStore-一招学会,秒变幽默风趣小王子!