美文网首页
recyclerview的adapter封装(kotlin)

recyclerview的adapter封装(kotlin)

作者: 记忆九天 | 来源:发表于2020-07-01 16:01 被阅读0次

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

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

    相关文章

      网友评论

          本文标题:recyclerview的adapter封装(kotlin)

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