代码全部提交到斗鱼弹幕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());
}
}
}
网友评论