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子条目的点击事件。
注意:
- 如果你加载的是图片,并且使用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的分割线