最近学习kotlin,拿了以前的一个小dome来练手,话不多说,给大家看下效果
左边是一个动态添加的RecyclerView,右边是一个fragment,点击左边的新闻title,可以切换右边的title以及内容
一起来看看用kotlin如何实现吧
首页布局如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"/>
<View
android:background="#999999"
android:layout_width="0.5dp"
android:layout_height="match_parent">
</View>
<FrameLayout
android:id="@+id/right_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3">
</FrameLayout>
</LinearLayout>
布局非常简单,相信不用我多说了,然后是
实体类
package com.example.tiantian_master
data class News(var title:String, var content:String )
大家可以看到 kotlin的代码非常简洁,一个data就实现了toString,get,set等方法,
调用适配器
recycler.layoutManager = LinearLayoutManager(this)
val adapter = NewsAdapter(list)
recycler.adapter = adapter
找到recyclerView并设置layoutManager与他的适配器
使用kotlin无需再使用findViewbyid,可以通过view的id,拿来就能用,kotlin抛弃了new关键字,使代码更加简洁
加上假数据
private fun initDate(){
for (num in 1 ..10)
list.add(News("新闻$num", "震惊$num"))
}
适配器部分
class NewsAdapter(private val list: List<News>) :
RecyclerView.Adapter<NewsAdapter.NewsViewHolder>() {
class NewsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val view = itemView
}
新建NewsAdapter类,注意是Kotlin Class,并继承RecyclerView.Adapter,泛型使用内部类NewsViewHolder
(private val list: List<News>)是一个主构造函数,list值可以在当前类全局使用
重写以下三个方法
onCreateViewHolder
getItemCount
onBindViewHolder
//如有返回值且只有一行代码可省略 :NewsViewHolder{}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = NewsViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_lefyrecyvler,//新闻标题item
parent,
false
)
)
override fun getItemCount()=list.size //: Int可省略
override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {
//kotlin可直接用id获取view组件
holder.view.title.text = list[position].title
}
到此适配器就完成了,运行项目
是不是感觉缺了点什么,没错,点击事件,好吧继续写
interface OnItemClickListener {
fun OnItemClick(view: View, position: Int)
}
在适配器中定义一个接口,接口中定义一个OnItemClick方法,设置两项参数,一个是View,一个是position
private lateinit var onClick: OnItemClickListener
fun setOnItemClick(onItemClickListener: OnItemClickListener) {
this.onClick = onItemClickListener
}
定义全局变量,实现set方法,和java没啥两样
大家可能会疑惑lateinit 有什么用呢
大家应该知道,在kotlin中声明一个可为空的变量的时候,必须在类型后加 ? 标识符,如下
private var onClick: OnItemClickListener?=null
而lateinit关键字,他告诉编译器这个变量会被初始化,并且不会为null,但是在声明这里,并且还不知道什么时候会被初始化。
具体可以去https://www.jianshu.com/p/24fdd70fdbce?utm_source=oschina-app了解
接下来在 onBindViewHold 中实现点击事件
holder.view.setOnClickListener { onClick.OnItemClick(holder.view, position) }
到此为止左边的title就已经完成了
再来看看右边fragment
首先是布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_title"
android:text="title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center">
</TextView>
<TextView
android:text="centent"
android:id="@+id/tv_content"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
</TextView>
</LinearLayout>
很简单,只有标题和内容
再创建一个RightFrgment继承Fragment
package com.example.tiantian_master
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.rightfragment.view.*
class RightFragment(val news: News) : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.rightfragment,container,false)
view.tv_title.text = news.title
view.tv_content.text = news.content
return view
}
}
重新onCreateView方法,加载新闻,返回自定义的layout即可
Activity中点击事件的使用
adapter.setOnItemClick(object : NewsAdapter.OnItemClickListener {
override fun OnItemClick(view: View, position: Int) {
replaceFragment(RightFragment(list[position]))
}
})
private fun replaceFragment( fragment:Fragment){
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.right_layout,fragment)
transaction.commit()//提交
}
replaceFragment用于切换fragment
到此为止,该项目所有功能都已经实现了最后附上完整的activity代码
package com.example.tiantian_master
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.myapplication.adapter.NewsAdapter
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity(){
var list = ArrayList<News>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initDate()
recycler.layoutManager = LinearLayoutManager(this)
val adapter = NewsAdapter(list)
recycler.adapter = adapter
adapter.setOnItemClick(object : NewsAdapter.OnItemClickListener {
override fun OnItemClick(view: View, position: Int) {
replaceFragment(RightFragment(list[position]))
}
})
}
private fun initDate(){
for (num in 1 ..10)
list.add(News("新闻$num", "震惊$num"))
}
private fun replaceFragment( fragment:Fragment){
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.right_layout,fragment)
transaction.commit()
}
}
我的邮箱 2503360639@qq.com
水平有限,如果有错请指出