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)擊事件。
注意:
- 如果你加載的是圖片,并且使用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的分割線