recyclerview的adapter封装(kotlin)

    技术2022-07-11  93

    首先是重写 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

    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的值,决定数据为空时是否显示空布局的样式。

    github地址:https://gitee.com/stonezry/AndroidDemo

    Processed: 0.011, SQL: 9