RecyclerView之简单使用

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"

因为我使用的是Kotlin来进行代码编写,因此在这里要进行Kotlin配置。如果不使用Kotlin那么只需要配置design就可以了。

2,RecyclerView的初步使用

2.1,首先我们用RecyclerView来实现一下ListView加载数据列表的页面效果,如图所示:

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实现:
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中代码实现:
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 表示数据从底部开始一直向上 
                    */ 
                rc.layoutManager=LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false)
                rc.adapter = rcAdapter  
        }
}

这样就简单的实现了上图的效果,可以看出子条目间没有分割线,那么分割线该怎么添加呢,通过下面这句代码:
rc.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))

效果图如下:


2.2,LayoutManager的使用

LayoutManager是RecyclerView下的一个抽象类,用来设置RecyclerView的显示方式,它有三种实现类:

  • LinearLayoutManager 线性管理器,支持横向、纵向
  • GridLayoutManager 网格布局管理器
  • StaggeredGridLayoutManager 瀑布流式布局管理器

上面我们用LinearLayoutManager 来显示数据,那么下面我们换另外两种来看看效果

2.2.1,使用GridLayoutManager 来显示:
        // rc.layoutManager=LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        /** 
          * GridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) 
          * orientation:方向 
          * spanCount:列数 
          * reverseLayout:ture 表示数据从底部开始一直向上 
          */
        rc.layoutManager= GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false) as RecyclerView.LayoutManager?

效果图如下:


将显示方向设置为HORIZONTAL,将第四个参数设置为true时:

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

效果如下:


2.2.2,使用StaggeredGridLayoutManager 来显示:
          /** 
            * StaggeredGridLayoutManager(int spanCount, int orientation) 
            * orientation:方向 
            * spanCount:列数 
            */
           rc.layoutManager= StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL) as RecyclerView.LayoutManager?

效果图如下(因为长宽设置一样的,因此看起来和GridLayoutManagerx效果一样):


设置高度为随机高度,在Adapter中进行,代码:

        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的子条目点击事件

RecyclerView并没有给我们提供子条目的点击事件,那么我们只有自己动手来实现点击事件,还是在Adapter中进行处理,代码为:

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)
                       }
               })

这样就实现了RecyclerView子条目的点击事件。

注意:

  1. 如果你加载的是图片,并且使用Glide来进行图片显示,那么上面的代码会出现
    错误提示:You must not call setTag() on a view Glide is targeting
    错误原因:View使用setTag后导致Glide之前请求的标记被清除,强制转换过程中不能将你给定的类型判断为Request类型所致。
    Glide源码中报错代码为:
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方法中,将设置tag语句:
holder.itemView.tag= position改为holder.itemView.setTag(R.id.glide_id, position)
在Adapter中的onCreateViewHolder方法中,将获取tag语句:
view.tag改为 view.getTag(R.id.glide_id)
在此运行程序,问题解决

关于RecyclerView第一篇先写到这里,第二篇写RecyclerView的分割线

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容