Kotlin开发第三天,UI开发
Posted peacejay
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin开发第三天,UI开发相关的知识,希望对你有一定的参考价值。
完整代码Gitee地址:kotlin-demo: 15天Kotlin学习计划
第三天学习内容代码:Chapter3
目录
知识点1:公共标题栏
市场上应用的界面顶部有一个标题栏,标题栏上会有一到两个按钮可用于返回或其他操作(iPhone没有专门的返回键)。虽然android系统已经给每个Activity提供了标题栏功能,但样式有很大局限性,我们自定义一个标题栏,新建item_title布局。
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns: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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="56dp">
<LinearLayout
android:id="@+id/lly_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="15dp"
android:orientation="horizontal">
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:src="@mipmap/img_return_withe"/>
</LinearLayout>
<TextView
android: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="标题"/>
<TextView
android: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 Activity
activity.finish()
}
}
}
现在自定义控件已经创建好了,接下来我们需要在布局文件中添加这个自定义控件,修改activity_learn3.xml中的代码,如下所示:
<LinearLayout
xmlns: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.TitleLayout
android: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">
<ImageView
android: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" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:orientation="vertical">
<TextView
android: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="姓名:" />
<TextView
android: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.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.recyclerview.widget.RecyclerView
android: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].name
holder.phoneText.text = userList[position].phone
holder.ivHerd.setImageResource(userList[position].herd)
}
}
虽然看上去好像多了好几个方法,但其实它比ListView的适配器要更容易理解。适配器准备好了之后,我们就可以开始使用RecyclerView了,修改Learn3Activity中的代码,如下所示:
class Learn3Activity : BaseActivity() {
private val userList = ArrayList<UserBean>()
private lateinit var mAdapter: UserNewAdapter
override 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) {
//获取控件ID
val 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)
//②使用框架,BaseRecyclerViewAdapterHelper
mAdapter = UserNewAdapter()
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = mAdapter
mAdapter.addData(userList)//添加数据
}
总体来看框架写法更简单,运行效果和写法①一样就不再赘述。
未完待续......
以上是关于Kotlin开发第三天,UI开发的主要内容,如果未能解决你的问题,请参考以下文章