美文网首页
RecyclerView之简单使用

RecyclerView之简单使用

作者: 小和尚恋红尘 | 来源:发表于2017-06-17 15:53 被阅读0次

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的分割线

相关文章

网友评论

      本文标题:RecyclerView之简单使用

      本文链接:https://www.haomeiwen.com/subject/cxxbqxtx.html