首先是重写 ViewHolder,参考了鸿洋大神的博客。
class RViewHolder(private val mContext: Context, val convertView: View) : ViewHolder(convertView) {
private val mViews: SparseArray<View>
init {
mViews = SparseArray()
}
/**
* 通过viewId获取控件
*
* @param viewId
* @return
*/
fun <T : View> getView(viewId: Int): T {
var view = mViews[viewId]
if (view == null) {
view = convertView.findViewById(viewId)
mViews.put(viewId, view)
}
return view as T
}
/****以下为辅助方法 */
/**
* 设置TextView的值
*
* @param viewId
* @param text
* @return
*/
fun setText(viewId: Int, text: String?): RViewHolder {
val tv = getView<TextView>(viewId)
tv.text = text
return this
}
fun setImageResource(viewId: Int, resId: Int): RViewHolder {
val view = getView<ImageView>(viewId)
view.setImageResource(resId)
return this
}
fun setImageBitmap(viewId: Int, bitmap: Bitmap?): RViewHolder {
val view = getView<ImageView>(viewId)
view.setImageBitmap(bitmap)
return this
}
fun setImageDrawable(viewId: Int, drawable: Drawable?): RViewHolder {
val view = getView<ImageView>(viewId)
view.setImageDrawable(drawable)
return this
}
fun setBackgroundColor(viewId: Int, color: Int): RViewHolder {
val view = getView<View>(viewId)
view.setBackgroundColor(color)
return this
}
fun setBackgroundRes(viewId: Int, backgroundRes: Int): RViewHolder {
val view = getView<View>(viewId)
view.setBackgroundResource(backgroundRes)
return this
}
fun setTextColor(viewId: Int, textColor: Int): RViewHolder {
val view = getView<TextView>(viewId)
view.setTextColor(textColor)
return this
}
fun setTextColorRes(viewId: Int, textColorRes: Int): RViewHolder {
val view = getView<TextView>(viewId)
view.setTextColor(mContext.resources.getColor(textColorRes))
return this
}
@SuppressLint("NewApi")
fun setAlpha(viewId: Int, value: Float): RViewHolder {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getView<View>(viewId).alpha = value
} else {
// Pre-honeycomb hack to set Alpha value
val alpha = AlphaAnimation(value, value)
alpha.duration = 0
alpha.fillAfter = true
getView<View>(viewId)!!.startAnimation(alpha)
}
return this
}
fun setVisible(viewId: Int, visible: Boolean): RViewHolder {
val view = getView<View>(viewId)
view.visibility = if (visible) View.VISIBLE else View.GONE
return this
}
fun linkify(viewId: Int): RViewHolder {
val view = getView<TextView>(viewId)
Linkify.addLinks(view, Linkify.ALL)
return this
}
fun setTypeface(typeface: Typeface?, vararg viewIds: Int): RViewHolder {
for (viewId in viewIds) {
val view = getView<TextView>(viewId)
view.typeface = typeface
view.paintFlags = view.paintFlags or Paint.SUBPIXEL_TEXT_FLAG
}
return this
}
fun setProgress(viewId: Int, progress: Int): RViewHolder {
val view = getView<ProgressBar>(viewId)
view.progress = progress
return this
}
fun setProgress(viewId: Int, progress: Int, max: Int): RViewHolder {
val view = getView<ProgressBar>(viewId)
view.max = max
view.progress = progress
return this
}
fun setMax(viewId: Int, max: Int): RViewHolder {
val view = getView<ProgressBar>(viewId)
view.max = max
return this
}
fun setRating(viewId: Int, rating: Float): RViewHolder {
val view = getView<RatingBar>(viewId)
view.rating = rating
return this
}
fun setRating(viewId: Int, rating: Float, max: Int): RViewHolder {
val view = getView<RatingBar>(viewId)
view.max = max
view.rating = rating
return this
}
fun setTag(viewId: Int, tag: Any?): RViewHolder {
val view = getView<View>(viewId)
view.tag = tag
return this
}
fun setTag(viewId: Int, key: Int, tag: Any?): RViewHolder {
val view = getView<View>(viewId)
view.setTag(key, tag)
return this
}
fun setChecked(viewId: Int, checked: Boolean): RViewHolder {
val view = getView<View>(viewId) as Checkable
view.isChecked = checked
return this
}
/**
* 关于事件的
*/
fun setOnClickListener(
viewId: Int,
listener: View.OnClickListener?
): RViewHolder {
val view = getView<View>(viewId)
view.setOnClickListener(listener)
return this
}
fun setOnTouchListener(
viewId: Int,
listener: OnTouchListener?
): RViewHolder {
val view = getView<View>(viewId)
view.setOnTouchListener(listener)
return this
}
fun setOnLongClickListener(
viewId: Int,
listener: OnLongClickListener?
): RViewHolder {
val view = getView<View>(viewId)
view.setOnLongClickListener(listener)
return this
}
companion object {
fun createViewHolder(
context: Context,
itemView: View
): RViewHolder {
return RViewHolder(context, itemView)
}
@JvmStatic
fun createViewHolder(
context: Context,
parent: ViewGroup, layoutId: Int
): RViewHolder {
val itemView = LayoutInflater.from(context).inflate(
layoutId, parent,
false
)
return RViewHolder(context, itemView)
}
}
}
SparseArray对view进行存储,需要的时候可以直接获取进行操作。
继承 RecyclerView.Adapter<RViewHolder>
open class MultiItemTypeAdapter<T>(protected var mContext: Context, var datas: List<T>) : RecyclerView.Adapter<RViewHolder>() {
protected var itemViewDelegate: ItemViewDelegate<T>? = null
protected var mOnItemClickListener: OnItemClickListener? = null
override fun getItemViewType(position: Int): Int {
//根据传入adapter来判断是否有数据
return if (datas.size > 0) NOT_EMPTY_VIEW else EMPTY_VIEW
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RViewHolder {
val layoutId = itemViewDelegate!!.getItemViewLayoutId(viewType)
val holder = createViewHolder(mContext, parent, layoutId)
onViewHolderCreated(holder, holder.convertView, viewType)
setListener(parent, holder, viewType)
return holder
}
fun onViewHolderCreated(
holder: RViewHolder?,
itemView: View?,
viewType: Int
) {
}
fun convert(holder: RViewHolder, t: T) {
itemViewDelegate!!.convert(holder, t, holder.adapterPosition)
}
fun convertEmptyView(holder: RViewHolder?) {}
protected fun isEnabled(viewType: Int): Boolean {
return viewType != EMPTY_VIEW
}
protected fun setListener(
parent: ViewGroup?,
viewHolder: RViewHolder,
viewType: Int
) {
if (!isEnabled(viewType)) return
viewHolder.convertView.setOnClickListener(object : NoDoubleClickListener() {
override fun onNoDoubleClick(v: View) {
val position = viewHolder.adapterPosition
mOnItemClickListener?.onItemClick(v, viewHolder, position)
}
})
viewHolder.convertView.setOnLongClickListener(OnLongClickListener { v ->
mOnItemClickListener?.let {
val position = viewHolder.adapterPosition
return@OnLongClickListener it.onItemLongClick(v, viewHolder, position)
}
false
})
}
override fun onBindViewHolder(holder: RViewHolder, position: Int) {
if (getItemViewType(position) != EMPTY_VIEW) {
convert(holder, datas[position])
} else {
convertEmptyView(holder)
}
}
override fun getItemCount(): Int {
return if (isEmptyViewShowed) {
if (datas.isNotEmpty()) datas.size else 1
} else {
if (datas.isNotEmpty()) datas.size else 0
}
}
fun setItemViewDelegate(delegate: ItemViewDelegate<T>?): MultiItemTypeAdapter<*> {
itemViewDelegate = delegate
return this
}
interface OnItemClickListener {
fun onItemClick(
view: View?,
holder: ViewHolder?,
position: Int
)
fun onItemLongClick(
view: View?,
holder: ViewHolder?,
position: Int
): Boolean
}
fun setOnItemClickListener(onItemClickListener: OnItemClickListener?) {
mOnItemClickListener = onItemClickListener
}
open val isEmptyViewShowed: Boolean
get() = true
companion object {
const val EMPTY_VIEW = 0
const val NOT_EMPTY_VIEW = 1
}
}
RVAdapter类的编写
/**
*
* @fuction 通用Recylerview Adapter
* @date 2019/5/22
* @author zhouruiyong
*/
abstract class RVAdapter<T>(
mContext: Context,
protected var mLayoutId: Int,
mDatas: List<T>
) : MultiItemTypeAdapter<T>(mContext, mDatas) {
private var emptyId = R.layout.item_empty_layout
protected abstract fun convert(holder: RViewHolder, t: T, position: Int)
protected fun getViewLayoutId(viewType: Int): Int {
return if (viewType == EMPTY_VIEW) { emptyId } else mLayoutId
}
fun setEmptyId(emptyId: Int) {
this.emptyId = emptyId
}
init {
//getItemViewLayoutId重写,则此处layoutId可直接写0
setItemViewDelegate(object : ItemViewDelegate<T> {
override fun getItemViewLayoutId(viewType: Int): Int {
return getViewLayoutId(viewType)
}
override fun isForViewType(item: T, position: Int): Boolean {
return true
}
override fun convert(holder: RViewHolder, t: T, position: Int) {
if (isForViewType(t, position)) {
this@RVAdapter.convert(holder, t, position)
}
}
})
}
}
interface ItemViewDelegate<T> {
fun getItemViewLayoutId(viewType: Int): Int
fun isForViewType(item: T, position: Int): Boolean
fun convert(holder: RViewHolder, t: T, position: Int)
}
以上就是adapter封装。现在看使用。
val layoutManager = LinearLayoutManager(this); //线性布局
recyclerview.layoutManager = layoutManager
homeAdapter = object: RVAdapter<String>(this@AdapterActivity,R.layout.item_rv_txt, mDatas){
override fun convert(holder: RViewHolder, t: String, position: Int) {
holder.setText(R.id.txt,mDatas[position])
}
}
recyclerview.adapter = homeAdapter
homeAdapter!!.setOnItemClickListener(object:MultiItemTypeAdapter.OnItemClickListener{
override fun onItemClick(view: View, holder: RecyclerView.ViewHolder, position: Int) {
TODO("Not yet implemented")
}
override fun onItemLongClick(
view: View,
holder: RecyclerView.ViewHolder,
position: Int
): Boolean {
TODO("Not yet implemented")
}
})
注意:可以通过重写isEmptyViewShowed的值,决定数据为空时是否显示空布局的样式。