美文网首页
简易封装的一个适用于聊天界面的Recyclerview适配器

简易封装的一个适用于聊天界面的Recyclerview适配器

作者: Sunhee21 | 来源:发表于2019-05-26 21:45 被阅读0次

    代码全部提交到斗鱼弹幕Demo里了

    package com.csh.application.common.widget.adapter;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.support.annotation.IdRes;
    import android.support.annotation.LayoutRes;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.support.v7.widget.RecyclerView;
    import android.util.SparseArray;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author sunhee
     * @intro
     * @date 2019/5/26
     */
    public abstract class BaseNestedAdapter<T extends INestedItem> extends RecyclerView.Adapter<BaseNestedHolder> {
    
        protected Context mContext;
        protected List<T> mData;
    
        @SuppressLint("UseSparseArrays")
        private SparseArray<Integer> parentTypeLayouts = new SparseArray<>();
    
    
        private OnItemClickListener mOnItemClickListener;
        private OnItemLongClickListener mOnItemLongClickListener;
    
        public BaseNestedAdapter(@Nullable List<T> data) {
            this.mData = (data == null ? new ArrayList<T>() : data);
            addParentLayoutId(parentTypeLayouts);
            if (parentTypeLayouts.size() == 0)
                throw new IndexOutOfBoundsException("parentTypeLayouts size is 0");
        }
    
        @Override
        public int getItemViewType(int position) {
            INestedItem item = mData.get(position);
            if (item != null) {
                return ViewType.makeViewType(item.getParentType(), item.getChildType());
            }
            return super.getItemViewType(position);
        }
    
        @NonNull
        @Override
        public BaseNestedHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
            this.mContext = viewGroup.getContext();
            int paretType = ViewType.getParent(viewType);
            int childType = ViewType.getChild(viewType);
            int parentLayoutId = parentTypeLayouts.get(paretType);//父子布局
            View parentView = LayoutInflater.from(mContext).inflate(parentLayoutId, viewGroup, false);//父布局
            int containerId = getChildContainerView(paretType);
            ViewGroup innerContainer = null;
            if (containerId != 0)
                innerContainer = parentView.findViewById(containerId);//父布局存放子布局的容易 可以为空 没有子布局
            View childView = null;
            if (innerContainer != null) {
    
                childView = getChildLayoutView(childType, innerContainer);//子View可能为空
    
                if (childView != null)
                    innerContainer.addView(childView);
            }
            return new BaseNestedHolder(parentView, childView);
        }
    
    
        protected abstract void addParentLayoutId(SparseArray<Integer> parentTypeLayouts);
    
    
        @IdRes
        @Nullable
        protected abstract int getChildContainerView(int parentType);
    
        protected abstract View getChildLayoutView(int childType, ViewGroup parentContainer);
    
        @Override
        public void onBindViewHolder(@NonNull BaseNestedHolder parentHolder, int position) {
            INestedItem iNestedItem = mData.get(position);
            iNestedItem.convertParent(parentHolder);
            if (parentHolder.getChildHolder() != null) {
                iNestedItem.convertChild(parentHolder.getChildHolder());
            }
            bindViewClickListener(parentHolder);
        }
    
    
        @Override
        public int getItemCount() {
            return mData.size();
        }
    
    
        private void bindViewClickListener(final BaseNestedHolder baseViewHolder) {
            if (baseViewHolder == null) {
                return;
            }
            final View view = baseViewHolder.itemView;
            if (view == null) {
                return;
            }
            if (getOnItemClickListener() != null) {
                view.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        getOnItemClickListener().onItemClick(BaseNestedAdapter.this, v, baseViewHolder.getAdapterPosition());
                    }
                });
            }
            if (getOnItemLongClickListener() != null) {
                view.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        return getOnItemLongClickListener().onItemLongClick(BaseNestedAdapter.this, v, baseViewHolder.getAdapterPosition());
                    }
                });
            }
        }
    
        /**
         * add one new data
         */
        public void addData(@NonNull T data) {
            mData.add(data);
            notifyItemInserted(mData.size());
            compatibilityDataSizeChanged(1);
        }
    
        /**
         * compatible getLoadMoreViewCount and getEmptyViewCount may change
         *
         * @param size Need compatible data size
         */
        private void compatibilityDataSizeChanged(int size) {
            final int dataSize = mData == null ? 0 : mData.size();
            if (dataSize == size) {
                notifyDataSetChanged();
            }
        }
    
        public interface OnItemLongClickListener {
    
            boolean onItemLongClick(BaseNestedAdapter adapter, View view, int position);
        }
    
    
        public interface OnItemClickListener {
    
            void onItemClick(BaseNestedAdapter adapter, View view, int position);
        }
    
        public OnItemClickListener getOnItemClickListener() {
            return mOnItemClickListener;
        }
    
        public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
            this.mOnItemClickListener = mOnItemClickListener;
        }
    
        public OnItemLongClickListener getOnItemLongClickListener() {
            return mOnItemLongClickListener;
        }
    
        public void setOnItemLongClickListener(OnItemLongClickListener mOnItemLongClickListener) {
            this.mOnItemLongClickListener = mOnItemLongClickListener;
        }
    
    }
    
    package com.csh.application.common.widget.adapter;
    
    import android.support.annotation.IdRes;
    import android.support.v7.widget.RecyclerView;
    import android.util.SparseArray;
    import android.view.View;
    
    /**
     * @author sunhee
     * @intro
     * @date 2019/5/26
     */
    public class BaseNestedHolder extends RecyclerView.ViewHolder {
    
        private final SparseArray<View> views;
    
        public ChildHolder childHolder;
    
        public BaseNestedHolder(View parentView, View childView) {
            super(parentView);
            this.childHolder = childView == null ? null : new ChildHolder(childView);
            this.views = new SparseArray<>();
        }
    
        @SuppressWarnings("unchecked")
        public <T extends View> T getView(@IdRes int viewId) {
            View view = views.get(viewId);
            if (view == null) {
                view = itemView.findViewById(viewId);
                views.put(viewId, view);
            }
            return (T) view;
        }
    
        public ChildHolder getChildHolder() {
            return childHolder;
        }
    
        public static class ChildHolder  {
    
            private final SparseArray<View> views;
    
            public View childView;
    
            public ChildHolder(View childView) {
                this.childView = childView;
                this.views = new SparseArray<>();
            }
    
            @SuppressWarnings("unchecked")
            public <T extends View> T getView(@IdRes int viewId) {
                View view = views.get(viewId);
                if (view == null) {
                    view = childView.findViewById(viewId);
                    views.put(viewId, view);
                }
                return (T) view;
            }
        }
    }
    
    package com.csh.application.common.widget.adapter;
    /**
     * @author sunhee
     * @intro 数据类实现这个接口就好了
     * @date 2019/5/26
     */
    public interface INestedItem {
    
    
        int getParentType();
        int getChildType();
    
    
        void convertParent(BaseNestedHolder parentHolder);
        void convertChild(BaseNestedHolder.ChildHolder childHolder);
    
    
    }
    
    
    
    package com.csh.application.common.widget.adapter;
    
    import android.support.annotation.IntRange;
    
    import timber.log.Timber;
    
    public  class ViewType {
        private static final int MODE_SHIFT = 24;
        private static final int MODE_MASK = 0xff << MODE_SHIFT; //L8 is 1,R24 is 0
        private static final int MODE_ONE = 1 << MODE_SHIFT;
        private static final int MODE_TWO = 2 << MODE_SHIFT;
    
    
    
    
        public static int makeViewType(@IntRange(from = 0, to = 0xff) int paretType, int childType) {
            return (childType & ~MODE_MASK) | (paretType << MODE_SHIFT & MODE_MASK);
        }
    
        public static int getChild(int viewType) {
            return (viewType & ~MODE_MASK);
        }
    
        public static int getParent(int viewType) {
            //noinspection ResourceType
            return (viewType & MODE_MASK)>>MODE_SHIFT;
        }
    
    }
    

    简单使用

    package com.csh.application.home.mvp.adapter.bullet_msg
    
    import android.util.SparseArray
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.TextView
    import com.csh.application.common.widget.adapter.BaseNestedAdapter
    import com.csh.application.common.widget.adapter.INestedItem
    import com.csh.application.home.R
    import com.sunhee.lib_socket.entity.MsgConstants
    
    /**
     * @intro
     * @author sunhee
     * @date 2019/5/26
     */
    
    class FakeChatAdapter(datas:MutableList<INestedItem>):BaseNestedAdapter<INestedItem>(datas){
    
    
        override fun getChildContainerView(parentType: Int): Int {
            val id = when(parentType){
                MsgConstants.MSG_FROM -> R.id.layout_content
                MsgConstants.MSG_TO -> R.id.layout_container
                else -> 0
            }
            return id
        }
    
    
        override fun addParentLayoutId(parentTypeLayouts: SparseArray<Int>) {
            parentTypeLayouts.put(MsgConstants.MSG_FROM, R.layout.layout_msg_from)
            parentTypeLayouts.put(MsgConstants.MSG_TO, R.layout.layout_msg_to)
        }
    
    
    
    
    
    
        override fun getChildLayoutView(childType: Int, parentContainer: ViewGroup): View? {
            return when(childType){
                MsgConstants.GIFT -> TextView(mContext).apply { text = "左边的消息" }
                MsgConstants.NORMAL -> {
                    LayoutInflater.from(mContext).inflate(R.layout.layout_complex,parentContainer,false)
                }
                else->TextView(mContext).apply { text = "奇怪的消息" }
            }
    
        }
    
    
    
    
    }
    
    package com.sunhee.lib_socket.entity;
    
    import android.graphics.Color;
    import android.widget.TextView;
    
    import com.csh.application.common.widget.adapter.BaseNestedHolder;
    import com.google.gson.annotations.SerializedName;
    import com.sunhee.lib_socket.R;
    
    /**
     * 弹幕消息
     * @author chenshanghui
     * @date 2019/5/1
     */
    public class BulletMsg extends BaseMsg {
    
    
    
    
        private int parentType = MsgConstants.MSG_FROM;
    
        @Override
        public int getParentType() {
            return parentType;
        }
    
        @Override
        public int getChildType() {
            return MsgConstants.NORMAL;
        }
    
        @Override
        public void convertParent(BaseNestedHolder parentHolder) {
            parentHolder.itemView.setBackgroundColor(Color.BLUE);
        }
    
        @Override
        public void convertChild(BaseNestedHolder.ChildHolder childHolder) {
            if(childHolder.childView instanceof TextView){
                ((TextView) childHolder.childView).setText(getTxt());
            }
        }
    
    }
    

    相关文章

      网友评论

          本文标题:简易封装的一个适用于聊天界面的Recyclerview适配器

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