RecyclerView之簡(jiǎn)單使用

1,添加依賴

在Project的build.gradle中添加

buildscript {
    ext.kotlin_version = '1.1.2-4'

    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

在app->build.gradle最上面添加

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

在app->build.gradle->dependencies中添加

compile 'com.android.support:design:25.3.1'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

因?yàn)槲沂褂玫氖荎otlin來進(jìn)行代碼編寫,因此在這里要進(jìn)行Kotlin配置。如果不使用Kotlin那么只需要配置design就可以了。

2,RecyclerView的初步使用

2.1,首先我們用RecyclerView來實(shí)現(xiàn)一下ListView加載數(shù)據(jù)列表的頁面效果,如圖所示:

2.1.1,整體XML布局文件:
<android.support.design.widget.CoordinatorLayout    
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto" 
      android:id="@+id/activity_kotlin1st" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:orientation="vertical"> 

      <android.support.v7.widget.RecyclerView 
            android:layout_width="match_parent" 
            android:layout_height="match_parent" 
            android:id="@+id/rc"/>
</android.support.design.widget.CoordinatorLayout>
2.1.2,RecyclerView的Adapter實(shí)現(xiàn):
class Kotlin1stAdapter(var context: Context, var items: List<String>):RecyclerView.Adapter<Kotlin1stAdapter.ViewHolder>(){
      override fun onBindViewHolder(holder: ViewHolder, position: Int) { 
          holder.tv.text = items[position] 
          holder.itemView.tag= position
     } 

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

      override fun getItemCount(): Int=items.size 

      class ViewHolder(itemTv: TextView):RecyclerView.ViewHolder(itemTv){ 
            var tv: TextView = itemTv.findViewById(R.id.tv)as TextView 
      }
}
2.1.3,Activity中代碼實(shí)現(xiàn):
class Kotlin1stActivity : AppCompatActivity() {
        private val itemList= listOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o") 
        private val rcAdapter=Kotlin1stAdapter(this, itemList) 

        override fun  onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_kotlin1st) 
                initDatas()
        }
 
        fun initDatas(){
                 /** 
                    * LinearLayoutManager(Context context, int orientation, boolean reverseLayout) 
                    * orientation:方向 
                    * reverseLayout:ture 表示數(shù)據(jù)從底部開始一直向上 
                    */ 
                rc.layoutManager=LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false)
                rc.adapter = rcAdapter  
        }
}

這樣就簡(jiǎn)單的實(shí)現(xiàn)了上圖的效果,可以看出子條目間沒有分割線,那么分割線該怎么添加呢,通過下面這句代碼:
rc.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))

效果圖如下:


2.2,LayoutManager的使用

LayoutManager是RecyclerView下的一個(gè)抽象類,用來設(shè)置RecyclerView的顯示方式,它有三種實(shí)現(xiàn)類:

  • LinearLayoutManager 線性管理器,支持橫向、縱向
  • GridLayoutManager 網(wǎng)格布局管理器
  • StaggeredGridLayoutManager 瀑布流式布局管理器

上面我們用LinearLayoutManager 來顯示數(shù)據(jù),那么下面我們換另外兩種來看看效果

2.2.1,使用GridLayoutManager 來顯示:
        // rc.layoutManager=LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        /** 
          * GridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) 
          * orientation:方向 
          * spanCount:列數(shù) 
          * reverseLayout:ture 表示數(shù)據(jù)從底部開始一直向上 
          */
        rc.layoutManager= GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false) as RecyclerView.LayoutManager?

效果圖如下:


將顯示方向設(shè)置為HORIZONTAL,將第四個(gè)參數(shù)設(shè)置為true時(shí):

        rc.layoutManager= GridLayoutManager(this, 3, GridLayoutManager.HORIZONTAL, true) as RecyclerView.LayoutManager?

效果如下:


2.2.2,使用StaggeredGridLayoutManager 來顯示:
          /** 
            * StaggeredGridLayoutManager(int spanCount, int orientation) 
            * orientation:方向 
            * spanCount:列數(shù) 
            */
           rc.layoutManager= StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL) as RecyclerView.LayoutManager?

效果圖如下(因?yàn)殚L(zhǎng)寬設(shè)置一樣的,因此看起來和GridLayoutManagerx效果一樣):


設(shè)置高度為隨機(jī)高度,在Adapter中進(jìn)行,代碼:

        var heights = ArrayList<Int>()
        init { 
                for (i in 0..items.size){ 
                        heights.add((100 + 300 * Math.random()).toInt()) 
                }
        }
        override fun onBindViewHolder(holder: ViewHolder, position: Int) { 
                val lp = holder.tv.layoutParams lp.height = heights[position] 
                holder.tv.layoutParams = lp 

                holder.tv.text = items[position] 
                holder.itemView.tag= position
        }

效果圖為:


2.3,RecyclerView的子條目點(diǎn)擊事件

RecyclerView并沒有給我們提供子條目的點(diǎn)擊事件,那么我們只有自己動(dòng)手來實(shí)現(xiàn)點(diǎn)擊事件,還是在Adapter中進(jìn)行處理,代碼為:

class Kotlin1stAdapter(var context: Context, var items: List<String>):RecyclerView.Adapter<Kotlin1stAdapter.ViewHolder>(){ 
        var heights = ArrayList<Int>() 
        init { 
                for (i in 0..items.size){ 
                      heights.add((100 + 300 * Math.random()).toInt()) 
                }
         } 

        override fun onBindViewHolder(holder: ViewHolder, position: Int) { 
                val lp = holder.tv.layoutParams 
                lp.height = heights[position] 
                holder.tv.layoutParams = lp 
                holder.tv.text = items[position] 
                holder.itemView.tag= position 
        } 

        override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
                val view = LayoutInflater.from(context).inflate(R.layout.item_rc_1st, parent, false)
                view.setOnClickListener { view -> listener?.onItemClick(view, view.tag as Int)}
                return ViewHolder(view as TextView)
         } 

        override fun getItemCount(): Int=items.size 

        class ViewHolder(itemTv: TextView):RecyclerView.ViewHolder(itemTv){ 
                var tv: TextView = itemTv.findViewById(R.id.tv)as TextView
        }

        private var listener: OnItemClickListener?=null 

        fun setOnItemClickListener(l: OnItemClickListener): Unit{ this.listener = l } 

        interface OnItemClickListener{ 
                fun onItemClick(view: View, pos: Int)
         }
}

在2.1.3代碼中添加:

               rcAdapter.setOnItemClickListener(object :Kotlin1stAdapter.OnItemClickListener{
                       override fun onItemClick(view: View, pos: Int) { 
                              Log.e("OnItemClickListener", "pos--> "+ pos)
                       }
               })

這樣就實(shí)現(xiàn)了RecyclerView子條目的點(diǎn)擊事件。

注意:

  1. 如果你加載的是圖片,并且使用Glide來進(jìn)行圖片顯示,那么上面的代碼會(huì)出現(xiàn)
    錯(cuò)誤提示:You must not call setTag() on a view Glide is targeting
    錯(cuò)誤原因:View使用setTag后導(dǎo)致Glide之前請(qǐng)求的標(biāo)記被清除,強(qiáng)制轉(zhuǎn)換過程中不能將你給定的類型判斷為Request類型所致。
    Glide源碼中報(bào)錯(cuò)代碼為:
public Request getRequest() {
    Object tag = getTag();
    Request request = null;
    if (tag != null) {
        if (tag instanceof Request) {
            request = (Request) tag;
        } else {
            throw new IllegalArgumentException("You must not call setTag() on a view Glide is targeting");
        }
    }
    return request;
}
 使用`holder.itemView.tag=position `后,在源碼中`Object tag = getTag() ` 得到tag并不是`Request`類型
 解決辦法:新建`ids.xml`文件,代碼:
<resources>
    <item name="glide_id" type="id"/>
</resources>

在Adapter中的onBindViewHolder方法中,將設(shè)置tag語句:
holder.itemView.tag= position改為holder.itemView.setTag(R.id.glide_id, position)
在Adapter中的onCreateViewHolder方法中,將獲取tag語句:
view.tag改為 view.getTag(R.id.glide_id)
在此運(yùn)行程序,問題解決

關(guān)于RecyclerView第一篇先寫到這里,第二篇寫RecyclerView的分割線

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

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

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