完整代碼Gitee地址:kotlin-demo: 15天Kotlin學習計劃
第三天學習內容代碼:Chapter3
目錄
知識點1:公共標題欄
知識點2:自定義標題欄控制元件
知識點3:RecyclerView
知識點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"))
}
}
}
這里使用了一個同樣的initFruits()方法,用于初始化所有的水果資料,接著在onCreate()方法中先創建了一個LinearLayoutManager物件,并將它設定到RecyclerView當中,LayoutManager用于指定RecyclerView的布局方式,這里使用的LinearLayoutManager是線性布局的意思,可以實作和ListView類似的效果,接下來我們創建了FruitAdapter的實體,并將水果資料傳入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)//添加資料
}
總體來看框架寫法更簡單,運行效果和寫法①一樣就不再贅述,
未完待續......
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/344284.html
標籤:其他
