63. (android開發(fā))RecyclerView動態(tài)加載內(nèi)容

android開發(fā)中RecyclerView現(xiàn)在已經(jīng)是很常用的一個組件了??梢造`活的布局,運(yùn)行效率也比ListView要好很多。只不過,它不是天然支持的,需要在app/build.gradle文件中添加包的引用
RecyclerView包引用

在項目的主界面需要增加RecyclerView組件。由于這個組件是通過引用加入的,所以在添加的時候要寫全路徑

    <android.support.v7.widget.RecyclerView
        android:id="@+id/articleRecycleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>

這是組件的外層,而內(nèi)部動態(tài)顯示內(nèi)容還需要再建一個xml來實(shí)現(xiàn)。當(dāng)然,每一個顯示塊也就是item的界面結(jié)構(gòu),就要在這個新建的xml文件里布局了。本demo就做的簡單點(diǎn)。新建一個article_item.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="wrap_content"
    android:orientation="vertical"
    android:background="#98623c">
    <TextView
        android:id="@+id/article_item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/article_item_publish_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="5dp"
        android:background="#e6cde3"/>
</LinearLayout>

在ide中,現(xiàn)在是看不到效果的。


article_item.xml編輯器預(yù)覽結(jié)果

只能是先寫代碼了。
在activity中添加代碼
先建立一個模擬數(shù)據(jù)

    /**模擬數(shù)據(jù)*/
    private val data:Array<String> = arrayOf("蘋果", "香蕉", "桔子", "橙子", "核桃", "西瓜", "水蜜桃", "獼猴桃", "羅漢果", "梨", "菠蘿", "殷桃", "葡萄", "草莓", "橄欖", "火龍果", "蛇果", "藍(lán)莓", "牛油果", "山楂", "芒果", "杏", "桃", "哈密瓜", "山竹", "桂圓", "荔枝")

再建立一個界面動態(tài)顯示數(shù)據(jù)的保存數(shù)組

    /**數(shù)據(jù)顯示數(shù)組*/
    private val articleList = ArrayList<Article>()

針對item里的顯示元素,需要一個數(shù)據(jù)類來構(gòu)建。

/**文章數(shù)據(jù)類*/
data class Article(        val indexPic: String,    //引導(dǎo)圖
                           val title: String,   //標(biāo)題
                           val subhead: String, //副標(biāo)題
                           val author: String,  //作者
                           val publishTime: String  //發(fā)布時間
 )

當(dāng)activity運(yùn)行起來的時候,我們首先要做內(nèi)容的初始化,就是把所有要顯示的數(shù)據(jù)都加載進(jìn)來。步驟是先把所有數(shù)據(jù)都放進(jìn)數(shù)據(jù)顯示數(shù)組articleList,然后再把數(shù)據(jù)都一條條綁定到界面article_item。
數(shù)據(jù)初始化使用一個initArticles()方法來實(shí)現(xiàn)

    /**數(shù)據(jù)初始化,獲得要展示的數(shù)據(jù),并加載到數(shù)據(jù)顯示數(shù)組*/
    private fun initArticles() {
        articleList.clear()     //清理原有數(shù)據(jù)
        for (i in data.indices){
            val article = Article("",data[i],"","", getNow())
            articleList.add(article)
        }
    }

然后在onCreate中調(diào)用。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_articles)

        title = "recyclerview"

        initArticles()  //初始化文章列表數(shù)據(jù)
        val linearLayoutManager = LinearLayoutManager(this)
        articleRecycleView.layoutManager = linearLayoutManager
        val articleAdapter = ArticleAdapter(this, articleList)
        articleRecycleView.adapter = articleAdapter
    }

可以看到,在“初始化文章列表數(shù)據(jù)”之后,就是對界面的管理和數(shù)據(jù)的綁定了。界面采用了LinearLayoutManager實(shí)現(xiàn)管理,而數(shù)據(jù)采用了Adapter。這里需要我們實(shí)現(xiàn)一個ArticleAdapter類。它繼承自RecyclerView.Adapter

class ArticleAdapter : RecyclerView.Adapter<ArticleAdapter.ViewHolder>{
    private var context:Context? = null
    private var articleList:ArrayList<Article>? = null
    constructor(context: Context, articleList: ArrayList<Article>){
        this.context = context
        this.articleList = articleList
    }
    class ViewHolder:RecyclerView.ViewHolder{
        var txtvwTitle: TextView
        var txtvwPublishTime: TextView
        constructor(itemView: View):super(itemView){
            txtvwTitle = itemView.findViewById(R.id.article_item_title)
            txtvwPublishTime = itemView.findViewById(R.id.article_item_publish_time)
        }
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
        if (position < articleList?.size as Int){
            val article = articleList?.get(position)        //取得當(dāng)前文章的數(shù)據(jù)
            //--開始賦值
            holder?.txtvwTitle?.text = article?.title
            holder?.txtvwPublishTime?.text = article?.publishTime
            //--結(jié)束賦值
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent?.context).inflate(R.layout.article_item, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return articleList?.size as Int
    }
}

在類中,需要傳入上下文和數(shù)據(jù),所以在類的構(gòu)造器上以這兩個為參數(shù)。
constructor(context: Context, articleList: ArrayList<Article>)
在 ViewHolder 類中,是對界面組件的實(shí)例化。以便在類中給指定的組件綁定數(shù)據(jù)。而綁定數(shù)據(jù)是在 onBindViewHolder 中實(shí)現(xiàn)。

完整代碼展示
package com.cofox.functions.Articles

import android.content.Context
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.cofox.mykt.function.getNow
import com.cofox.mykt.myweather.R
import kotlinx.android.synthetic.main.activity_articles.*

class ArticlesActivity : AppCompatActivity() {

    /**模擬數(shù)據(jù)*/
    private val data:Array<String> = arrayOf("蘋果", "香蕉", "桔子", "橙子", "核桃", "西瓜", "水蜜桃", "獼猴桃", "羅漢果", "梨", "菠蘿", "殷桃", "葡萄", "草莓", "橄欖", "火龍果", "蛇果", "藍(lán)莓", "牛油果", "山楂", "芒果", "杏", "桃", "哈密瓜", "山竹", "桂圓", "荔枝")
    /**數(shù)據(jù)顯示數(shù)組*/
    private val articleList = ArrayList<Article>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_articles)

        title = "recyclerview"

        initArticles()  //初始化文章列表數(shù)據(jù)
        val linearLayoutManager = LinearLayoutManager(this)
        articleRecycleView.layoutManager = linearLayoutManager

        val articleAdapter = ArticleAdapter(this, articleList)
        articleRecycleView.adapter = articleAdapter
    }

    /**數(shù)據(jù)初始化,獲得要展示的數(shù)據(jù),并加載到數(shù)據(jù)顯示數(shù)組*/
    private fun initArticles() {
        articleList.clear()     //清理原有數(shù)據(jù)
        for (i in data.indices){
            val article = Article("",data[i],"","", getNow())
            articleList.add(article)
        }
    }


}

/**文章數(shù)據(jù)類*/
data class Article(        val indexPic: String,    //引導(dǎo)圖
                           val title: String,   //標(biāo)題
                           val subhead: String, //副標(biāo)題
                           val author: String,  //作者
                           val publishTime: String  //發(fā)布時間
 )

class ArticleAdapter : RecyclerView.Adapter<ArticleAdapter.ViewHolder>{
    private var context:Context? = null
    private var articleList:ArrayList<Article>? = null
    constructor(context: Context, articleList: ArrayList<Article>){
        this.context = context
        this.articleList = articleList
    }
    class ViewHolder:RecyclerView.ViewHolder{
        var txtvwTitle: TextView
        var txtvwPublishTime: TextView
        constructor(itemView: View):super(itemView){
            txtvwTitle = itemView.findViewById(R.id.article_item_title)
            txtvwPublishTime = itemView.findViewById(R.id.article_item_publish_time)
        }
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
        if (position < articleList?.size as Int){
            val article = articleList?.get(position)        //取得當(dāng)前文章的數(shù)據(jù)
            //--開始賦值
            holder?.txtvwTitle?.text = article?.title
            holder?.txtvwPublishTime?.text = article?.publishTime
            //--結(jié)束賦值
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent?.context).inflate(R.layout.article_item, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return articleList?.size as Int
    }
}


getNow() 就是獲取當(dāng)前時間的一個自定義函數(shù)。你可以換成別的東西來實(shí)現(xiàn)。和本文要講的重點(diǎn)無關(guān)。

看一下界面最終效果
RecyclerView動態(tài)加載內(nèi)容效果

關(guān)于數(shù)據(jù)從服務(wù)器上獲取,相信通過前面的幾節(jié)內(nèi)容就可以很容易實(shí)現(xiàn)對本節(jié)中相應(yīng)內(nèi)容做更新了。
點(diǎn)擊和長按操作

如果只是顯示,顯然還缺少另一個最常見的功能——點(diǎn)擊。既然有點(diǎn)擊,作為手機(jī)操作也有另一個類似的操作——長按。這兩個也是要實(shí)現(xiàn)一下的。
當(dāng)然,要點(diǎn)擊一定是有數(shù)據(jù)才有點(diǎn)擊的需要,因為要看詳情嘛。那么點(diǎn)擊監(jiān)聽就在 articleAdapter 聲明之后開始加代碼。修改 onCreate 中的相應(yīng)代碼。

        val articleAdapter = ArticleAdapter(this, articleList)
        articleAdapter.setOnItemClickListener(object : ArticleAdapter.OnItemClickListener {
            override fun onClick(position: Int) {
                Toast.makeText(this@ArticlesActivity, "onClick點(diǎn)擊,第" + position + "個Item被點(diǎn)擊了。"+articleList[position].title, Toast.LENGTH_LONG).show()

            }

            override fun onLongClick(position: Int) {
                Toast.makeText(this@ArticlesActivity, "onLongClick長按,第" + position + "個Item被點(diǎn)擊了。", Toast.LENGTH_LONG).show()
            }
        })
        articleRecycleView.adapter = articleAdapter

現(xiàn)在執(zhí)行是沒有結(jié)果的,還需要在 ArticleAdapter 類中增加相關(guān)接口和操作。
在類內(nèi)部聲明一個Item事件監(jiān)聽接口,并建立一個監(jiān)聽的變量及監(jiān)聽操作動作。

    //Item事件監(jiān)聽
    interface OnItemClickListener {
        fun onClick(position: Int)
        fun onLongClick(position: Int)
    }
    private var mOnItemClickListener: OnItemClickListener? = null
    fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
        this.mOnItemClickListener = onItemClickListener
    }

再把監(jiān)聽綁定到每條記錄上。

            //--開始綁定點(diǎn)擊事件
            if (mOnItemClickListener != null) {

                holder?.itemView?.setOnClickListener { mOnItemClickListener?.onClick(position) }

                holder?.itemView?.setOnLongClickListener {
                    mOnItemClickListener?.onLongClick(position)
                    false
                }
//                holder?.txtvwTitle!!.setOnClickListener { mOnItemClickListener?.onClick(position) }


            }
            //--結(jié)束綁定點(diǎn)擊事件

這個綁定可以綁定到整個 View ,也可以綁定到 View 內(nèi)的任一組件上,比如

holder?.txtvwTitle!!.setOnClickListener { mOnItemClickListener?.onClick(position) }

這樣就把點(diǎn)擊動作綁定到文章標(biāo)題上了。
運(yùn)行效果如下


點(diǎn)擊

長按

修改后的完整代碼

package com.cofox.functions.Articles

import android.content.Context
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import com.cofox.functions.RecyclerViewJava.FruitAdapter
import com.cofox.mykt.function.getNow
import com.cofox.mykt.myweather.R
import kotlinx.android.synthetic.main.activity_articles.*

class ArticlesActivity : AppCompatActivity() {

    /**模擬數(shù)據(jù)*/
    private val data:Array<String> = arrayOf("蘋果", "香蕉", "桔子", "橙子", "核桃", "西瓜", "水蜜桃", "獼猴桃", "羅漢果", "梨", "菠蘿", "殷桃", "葡萄", "草莓", "橄欖", "火龍果", "蛇果", "藍(lán)莓", "牛油果", "山楂", "芒果", "杏", "桃", "哈密瓜", "山竹", "桂圓", "荔枝")
    /**數(shù)據(jù)顯示數(shù)組*/
    private val articleList = ArrayList<Article>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_articles)

        title = "recyclerview"

        initArticles()  //初始化文章列表數(shù)據(jù)
        val linearLayoutManager = LinearLayoutManager(this)
        articleRecycleView.layoutManager = linearLayoutManager

        val articleAdapter = ArticleAdapter(this, articleList)
        articleAdapter.setOnItemClickListener(object : ArticleAdapter.OnItemClickListener {
            override fun onClick(position: Int) {
                Toast.makeText(this@ArticlesActivity, "onClick點(diǎn)擊,第" + position + "個Item被點(diǎn)擊了。"+articleList[position].title, Toast.LENGTH_LONG).show()

            }

            override fun onLongClick(position: Int) {
                Toast.makeText(this@ArticlesActivity, "onLongClick長按,第" + position + "個Item被點(diǎn)擊了。", Toast.LENGTH_LONG).show()
            }
        })
        articleRecycleView.adapter = articleAdapter
    }

    /**數(shù)據(jù)初始化,獲得要展示的數(shù)據(jù),并加載到數(shù)據(jù)顯示數(shù)組*/
    private fun initArticles() {
        articleList.clear()     //清理原有數(shù)據(jù)
        for (i in data.indices){
            val article = Article("",data[i],"","", getNow())
            articleList.add(article)
        }
    }


}

/**文章數(shù)據(jù)類*/
data class Article(        val indexPic: String,    //引導(dǎo)圖
                           val title: String,   //標(biāo)題
                           val subhead: String, //副標(biāo)題
                           val author: String,  //作者
                           val publishTime: String  //發(fā)布時間
 )

class ArticleAdapter : RecyclerView.Adapter<ArticleAdapter.ViewHolder>{
    private var context:Context? = null
    private var articleList:ArrayList<Article>? = null
    constructor(context: Context, articleList: ArrayList<Article>){
        this.context = context
        this.articleList = articleList
    }
    class ViewHolder:RecyclerView.ViewHolder{
        var txtvwTitle: TextView
        var txtvwPublishTime: TextView
        constructor(itemView: View):super(itemView){
            txtvwTitle = itemView.findViewById(R.id.article_item_title)
            txtvwPublishTime = itemView.findViewById(R.id.article_item_publish_time)

        }
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
        if (position < articleList?.size as Int){
            val article = articleList?.get(position)        //取得當(dāng)前文章的數(shù)據(jù)
            //--開始賦值
            holder?.txtvwTitle?.text = article?.title
            holder?.txtvwPublishTime?.text = article?.publishTime
            //--結(jié)束賦值

            //--開始綁定點(diǎn)擊事件
            if (mOnItemClickListener != null) {

                holder?.itemView?.setOnClickListener { mOnItemClickListener?.onClick(position) }

                holder?.itemView?.setOnLongClickListener {
                    mOnItemClickListener?.onLongClick(position)
                    false
                }
//                holder?.txtvwTitle!!.setOnClickListener { mOnItemClickListener?.onClick(position) }


            }
            //--結(jié)束綁定點(diǎn)擊事件
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent?.context).inflate(R.layout.article_item, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return articleList?.size as Int
    }

    //Item事件監(jiān)聽
    interface OnItemClickListener {
        fun onClick(position: Int)
        fun onLongClick(position: Int)
    }
    private var mOnItemClickListener: OnItemClickListener? = null
    fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
        this.mOnItemClickListener = onItemClickListener
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容