public interface RvItemViewDelegate<T> {

    /**
     * 设置Item的LayoutId
     */
    public abstract
    @LayoutRes
    int getItemLayoutId();

    /**
     * <P>通过 {@code position} 和 {@code itemData} 判断是否为该位置的Item <br/>
     * 如果返回true 则将依次调用以下接口  <br/>
     * {@link RvItemViewDelegate#onViewHolderCreated(Context, RvHolderHelper)} <br/>
     * {@link RvItemViewDelegate#setItemChildListener(RvHolderHelper, int)}<br/>
     * {@link RvItemViewDelegate#convert(Context, RvHolderHelper, int, Object)}<br/>
     * </P>
     *
     * @param position Item的位置
     * @param itemData Item的内容
     * @return {@code true} - 是该位置的Item <br/>
     * <code> false</code> - 不是该位置的Item
     */
    public abstract boolean isDelegate(int position, T itemData);

    /**
     * Item被创建时调用
     *
     * @param context {@link Context} 上下文
     * @param helper  {@link RvHolderHelper}
     */
    public abstract void onViewHolderCreated(Context context, RvHolderHelper helper);

    /**
     * 设置Item内部ChildView 的监听 在 {@link io.github.anotherme17.commonrvadapter.adapter.RecyclerViewAdapter#onCreateViewHolder(ViewGroup, int)} 中调用
     *
     * @param helper   {@link RvHolderHelper}
     * @param viewType Item 的 layoutId
     */
    public abstract void setItemChildListener(RvHolderHelper helper, int viewType);

    /**
     * 在此为Item里的View 赋值
     *
     * @param context  {@link Context} 上下文
     * @param helper   {@link RvHolderHelper}
     * @param position Item的位置 不包括头和尾
     * @param itemData Item的内容
     */
    public abstract void convert(Context context, RvHolderHelper helper, int position, T itemData);
} public class AlphaInAnimation extends BaseAnimation {

    private static final float DEFAULT_ALPHA_FROM = 0f;
    private final float mFrom;

    public AlphaInAnimation() {
        this(DEFAULT_ALPHA_FROM);
    }

    public AlphaInAnimation(float from) {
        mFrom = from;
    }

    @Override
    public Animator[] getAnimators(View view) {
        return new Animator[]{ObjectAnimator.ofFloat(view, "alpha", mFrom, 1f)};
    }
} public abstract class BaseAnimation {

    /**
     * 动画持续时间,默认为300ms,可通过{{@link BaseAnimation#setDuration(long)}}进行设置
     */
    private long mDuration = 300;

    /**
     * 动画插值器,默认为线性的,可通过{{@link BaseAnimation#setInterpolator(Interpolator)}} 进行设置
     */
    private Interpolator mInterpolator = new LinearInterpolator();

    /**
     * 设置动画
     *
     * @param view 要设置动画的View,即Item的View
     * @return 返回设置完成的动画集合
     */
    public abstract Animator[] getAnimators(View view);

    /**
     * @return 返回动画持续时间
     */
    public long getDuration() {
        return mDuration;
    }

    /**
     * @param duration 设置动画持续时间
     */
    public void setDuration(long duration) {
        mDuration = duration;
    }

    /**
     * @return 返回动画插值器
     */
    public Interpolator getInterpolator() {
        return mInterpolator;
    }

    /**
     * @param interpolator 设置动画插值器
     */
    public void setInterpolator(Interpolator interpolator) {
        mInterpolator = interpolator;
    }
} public class ScaleInAnimation extends BaseAnimation {
    private static final float DEFAULT_SCALE_FROM = .5f;
    private final float mFrom;

    public ScaleInAnimation() {
        this(DEFAULT_SCALE_FROM);
    }

    public ScaleInAnimation(float from) {
        mFrom = from;
    }

    @Override
    public Animator[] getAnimators(View view) {
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", mFrom, 1f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", mFrom, 1f);
        return new ObjectAnimator[]{scaleX, scaleY};
    }
} public class SlideInBottomAnimation extends BaseAnimation {
    @Override
    public Animator[] getAnimators(View view) {
        return new Animator[]{
                ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0)
        };
    }
} public class SlideInLeftAnimation extends BaseAnimation {
    @Override
    public Animator[] getAnimators(View view) {
        return new Animator[] {
                ObjectAnimator.ofFloat(view, "translationX", -view.getRootView().getWidth(), 0)
        };
    }
} public class SlideInRightAnimation extends BaseAnimation {
    @Override
    public Animator[] getAnimators(View view) {
        return new Animator[]{
                ObjectAnimator.ofFloat(view, "translationX", view.getRootView().getWidth(), 0)
        };
    }
} public class BaseItemTouchHelper extends ItemTouchHelper.Callback {
    /*================ final 参数================*/

    /**
     * 允许拖动
     */
    public static final int DRAG_ENABLE = 0x01;
    /**
     * 允许滑动删除
     */
    public static final int SWIP_ENABLE = 0x02;
    /**
     * 当Item的类型相同时才允许互换位置
     */
    public static final int SAME_MOVE = 0x04;

    /**
     * 默认的ItemTouch模式
     */
    public static final int DEFAULT_MODEL = SWIP_ENABLE | DRAG_ENABLE;

    @IntDef({DRAG_ENABLE, SWIP_ENABLE, SAME_MOVE, DEFAULT_MODEL})
    @Retention(RetentionPolicy.SOURCE)
    public @interface ItemTouchModel {

    }

    /*================ 默认的拖动和滑动的参数 ================*/
    protected int defaultDragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
    protected int defaultSwipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;

    /*================ 参数 ================*/

    /**
     * 是否允许长按拖动
     */
    private boolean isLongPressDragEnabled = false;
    /**
     * 是否允许滑动
     */
    private boolean isItemViewSwipeEnabled = false;
    /**
     * 是否在相同Item时才允许互换位置
     */
    private boolean isSameMove = false;

    /*================ 移动和滑动的监听 ================*/
    protected OnItemDragListener mOnItemDragListener;
    protected OnItemSwipedListener mOnItemSwipedListener;

    /*================ 在create时需要赋值和初始化的对象 ================*/
    protected ItemTouchHelper mItemTouchHelper;
    protected RecyclerViewAdapter mAdapter;

    /*================================ 分界线 ================================*/

    public BaseItemTouchHelper() {
        mItemTouchHelper = new ItemTouchHelper(this);
    }

    public void setRvAdapter(RecyclerViewAdapter adapter) {
        this.mAdapter = adapter;
    }

    public void setItemTouchMode(int model) {
        isLongPressDragEnabled = (model & DRAG_ENABLE) != 0;
        isItemViewSwipeEnabled = (model & SWIP_ENABLE) != 0;
        isSameMove = (model & SAME_MOVE) != 0;
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return isLongPressDragEnabled;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return isItemViewSwipeEnabled;
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setSelected(true);
        }
        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = defaultDragFlags;
        int swipeFlags = defaultSwipeFlags;

        // 当加了 HeaderAndFooterAdapter 时需要加上下面的判断
        if (mAdapter.isHeaderOrFooter(viewHolder)) {
            dragFlags = swipeFlags = ItemTouchHelper.ACTION_STATE_IDLE;
        }

        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        if (isSameMove) {
            if (viewHolder.getItemViewType() != target.getItemViewType()) {
                return false;
            }
        }

        if (mAdapter.isHeaderOrFooter(viewHolder) || mAdapter.isHeaderOrFooter(target))
            return false;
        return true;
    }

    @Override
    public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, int fromPos, RecyclerView.ViewHolder target, int toPos, int x, int y) {
        super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);

        mAdapter.itemMoved(target, viewHolder);

        if (mOnItemDragListener != null)
            mOnItemDragListener.onItemMoved(recyclerView, target, viewHolder);
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        mAdapter.removeItem(viewHolder);

        if (mOnItemSwipedListener != null)
            mOnItemSwipedListener.onItemSwiped(viewHolder, direction);
    }

    public void attacth2RecycleView(RecyclerView recyclerView) {
        mItemTouchHelper.attachToRecyclerView(recyclerView);
    }

    public void startDrag(RecyclerView.ViewHolder holder) {
        mItemTouchHelper.startDrag(holder);
    }

    public void startSwiped(RecyclerView.ViewHolder holder) {
        mItemTouchHelper.startSwipe(holder);
    }

    public void setDragFlag(int flag) {
        defaultDragFlags = flag;
    }

    public void setSwipedFlag(int flag) {
        defaultSwipeFlags = flag;
    }

    /*========== listener ==========*/

    public void setOnItemDragListener(OnItemDragListener onItemDragListener) {
        mOnItemDragListener = onItemDragListener;
    }

    public void setOnItemSwipedListener(OnItemSwipedListener onItemSwipedListener) {
        mOnItemSwipedListener = onItemSwipedListener;
    }

    public interface OnItemDragListener {
        void onItemMoved(RecyclerView recyclerView, RecyclerView.ViewHolder from, RecyclerView.ViewHolder to);
    }

    public interface OnItemSwipedListener {
        void onItemSwiped(RecyclerView.ViewHolder viewHolder, int direction);
    }
} public class RecyclerViewHolder extends RecyclerView.ViewHolder {

    private RecyclerView mRecyclerView;

    private RecyclerViewAdapter mAdapter;

    private RvHolderHelper mHelper;

    /*=== listener ===*/
    private OnRvItemClickListener mOnRvItemClickListener;
    private OnRvItemLongClickListener mOnRvItemLongClickListener;

    public RecyclerViewHolder(View emptyView) {
        super(emptyView);
    }

    public RecyclerViewHolder(View itemView, RecyclerView recyclerView,
                              RecyclerViewAdapter recyclerViewAdapter,
                              OnRvItemClickListener onRvItemClickListener,
                              OnRvItemLongClickListener onRvItemLongClickListener) {
        super(itemView);

        this.mRecyclerView = recyclerView;
        this.mAdapter = recyclerViewAdapter;
        this.mOnRvItemClickListener = onRvItemClickListener;
        this.mOnRvItemLongClickListener = onRvItemLongClickListener;

        /*=== init helper ===*/
        mHelper = new RvHolderHelper(mRecyclerView, this);

        /*=== set listener ===*/
        itemView.setOnClickListener(new OnNoDoubleClickListener() {
            @Override
            public void onNoDoubleClick(View v) {
                if (v.getId() == RecyclerViewHolder.this.itemView.getId() && mOnRvItemClickListener != null) {
                    mOnRvItemClickListener.onRvItemClick(mRecyclerView, v, getAdapterPositionWapper());
                }
            }
        });

        itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (v.getId() == RecyclerViewHolder.this.itemView.getId() && mOnRvItemLongClickListener != null) {
                    return mOnRvItemLongClickListener.onRvItemLongClick(mRecyclerView, v, getAdapterPositionWapper());
                }
                return false;
            }
        });
    }

    public RvHolderHelper getRvHolderHelper() {
        return mHelper;
    }

    public int getAdapterPositionWapper() {
        if (mAdapter.getHeadersCount() > 0) {
            return getAdapterPosition() - mAdapter.getHeadersCount();
        } else {
            return getAdapterPosition();
        }
    }
} public interface OnItemDragCallback {

    /**
     * 在对holder中的某一个View绑定监听后{@link io.github.anotherme17.commonrvadapter.helper.RvHolderHelper#attachItemDrag(int)}
     * 在该View被触发Touch事件后返回该Item的{@link RecyclerViewHolder},可使用{@link io.github.anotherme17.commonrvadapter.helper.RvItemTouchHelper} 设置拖动
     *
     * @param holder 被Touch的View所在的Item的holder
     */
    void setDragView(RecyclerViewHolder holder);

} public interface OnRvItemChildCheckedChangeListener {

    /**
     * Item子控件状态改变时返回
     *
     * @param parent    状态发生改变的View的ParentView
     * @param childView 状态发生改变的View
     * @param position  Item所在的位置
     * @param isChecked 选中状态
     */
    void onRvItemChildCheckedChanged(ViewGroup parent, CompoundButton childView, int position, boolean isChecked);
} public interface OnRvItemChildClickListener {

    /**
     * Item中的ChildView的点击事件
     *
     * @param parent    parentView
     * @param childView 被点击的View
     * @param position  Item所在的位置
     */
    void onRvItemChildClick(ViewGroup parent, View childView, int position);
} public interface OnRvItemChildLongClickListener {

    /**
     * Item中的ChildView的长按事件
     *
     * @param parent    parentView
     * @param childView 被长按的View
     * @param position  Item的位置
     * @return
     */
    boolean onRvItemChildLongClick(ViewGroup parent, View childView, int position);
} public interface OnRvItemChildTouchListener {
    /**
     * Item中的ChildView的touch事件
     * @param viewHolder
     * @param childView
     * @param event
     * @return
     */
    boolean onRvItemChilcTouch(RecyclerViewHolder viewHolder, View childView, MotionEvent event);
} public interface OnRvItemClickListener {

    /**
     * Item的Click事件
     *
     * @param parent   ParentView
     * @param itemView 被点击的Item的View
     * @param position item的位置
     */
    void onRvItemClick(ViewGroup parent, View itemView, int position);
} public interface OnRvItemLongClickListener {

    /**
     * Item的长按事件
     *
     * @param parent   ParentView
     * @param itemView 被点击的Item的View
     * @param position item的位置
     * @return
     */
    boolean onRvItemLongClick(ViewGroup parent, View itemView, int position);
} public class RvDelegateManager<T> {

    protected SparseArrayCompat<RvItemViewDelegate<T>> mDelegates = new SparseArrayCompat<>();

    public void addDelegate(RvItemViewDelegate<T> delegate) {
        int viewType = delegate.getItemLayoutId();
        if (mDelegates.get(viewType) != null) {
            throw new DelegateAlreadyExistException(viewType, mDelegates.get(viewType));
        } else {
            mDelegates.put(viewType, delegate);
        }
    }

    public void addDelegate(RvItemViewDelegate<T>... delegates) {
        for (RvItemViewDelegate<T> delegate : delegates) {
            addDelegate(delegate);
        }
    }

    public void removeDelegate(RvItemViewDelegate<T> delegate) {
        int indexToRemove = mDelegates.indexOfValue(delegate);
        if (indexToRemove >= 0) {
            mDelegates.removeAt(indexToRemove);
        } else {
            throw new DelegateNotFoundException(delegate);
        }
    }

    public void removeDelegate(RvItemViewDelegate<T>... delegates) {
        for (RvItemViewDelegate<T> delegate : delegates) {
            removeDelegate(delegate);
        }
    }

    public void removeDelegate(@LayoutRes int layoutId) {
        int indexToRemove = mDelegates.indexOfKey(layoutId);
        if (indexToRemove >= 0) {
            mDelegates.removeAt(indexToRemove);
        } else {
            throw new DelegateNotFoundException(layoutId);
        }
    }

    public void removeAllDelegate() {
        mDelegates.clear();
    }

    public int getItemViewType(int position, T data) {
        if (mDelegates.size() <= 0) {
            throw new DelegateNotFoundException();
        }

        for (int i = 0; i < mDelegates.size(); i++) {
            RvItemViewDelegate<T> delegate = mDelegates.valueAt(i);
            if (delegate.isDelegate(position, data)) {
                return delegate.getItemLayoutId();
            }
        }
        throw new DelegateNotFoundException();
    }

    public RvItemViewDelegate getDelegateByViewType(int viewType) {
        return mDelegates.get(viewType);
    }

}
import android.animation.Animator;
import android.content.Context;
import android.support.annotation.IntDef;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.SparseArrayCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import io.github.anotherme17.commonrvadapter.R;
import io.github.anotherme17.commonrvadapter.RvItemViewDelegate;
import io.github.anotherme17.commonrvadapter.animation.AlphaInAnimation;
import io.github.anotherme17.commonrvadapter.animation.BaseAnimation;
import io.github.anotherme17.commonrvadapter.animation.ScaleInAnimation;
import io.github.anotherme17.commonrvadapter.animation.SlideInBottomAnimation;
import io.github.anotherme17.commonrvadapter.animation.SlideInLeftAnimation;
import io.github.anotherme17.commonrvadapter.animation.SlideInRightAnimation;
import io.github.anotherme17.commonrvadapter.helper.BaseItemTouchHelper;
import io.github.anotherme17.commonrvadapter.holder.RecyclerViewHolder;
import io.github.anotherme17.commonrvadapter.listener.OnItemDragCallback;
import io.github.anotherme17.commonrvadapter.listener.OnRvItemChildCheckedChangeListener;
import io.github.anotherme17.commonrvadapter.listener.OnRvItemChildClickListener;
import io.github.anotherme17.commonrvadapter.listener.OnRvItemChildLongClickListener;
import io.github.anotherme17.commonrvadapter.listener.OnRvItemChildTouchListener;
import io.github.anotherme17.commonrvadapter.listener.OnRvItemClickListener;
import io.github.anotherme17.commonrvadapter.listener.OnRvItemLongClickListener;
import io.github.anotherme17.commonrvadapter.manager.RvDelegateManager;
package io.github.anotherme17.commonrvadapter.adapter;




/**
 * 万能的RecyclerView适配器
 *
 * @author anotherme17
 * @version 1.0.0
 */
public class RecyclerViewAdapter<T> extends RecyclerView.Adapter<RecyclerViewHolder> {

    private static final boolean DEBUG = true;
    private static final String TAG = "RecyclerViewAdapter";

    /*========== Head And Foot ==========*/
    private static final int BASE_ITEM_TYPE_HEADER = 1024;
    private static final int BASE_ITEM_TYPE_FOOTER = 2048;

    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();
    private SparseArrayCompat<View> mFootViews = new SparseArrayCompat<>();


    private int mDefaultItemId = 0;

    protected Context mContext;

    private List<T> mData;

    private RecyclerView mRecyclerView;

    private RvDelegateManager<T> mDelegateManager;

    private boolean mIsIgnoreCheckedChanged = true;

    protected boolean enableDragAndSwip = false;

    /*=== animation ===*/
    public static final int ALPHAIN = 0x00000001;
    public static final int SCALEIN = 0x00000002;
    public static final int SLIDEIN_BOTTOM = 0x00000003;
    public static final int SLIDEIN_LEFT = 0x00000004;
    public static final int SLIDEIN_RIGHT = 0x00000005;

    protected BaseAnimation mShowAnimation = new AlphaInAnimation();
    private boolean mLoadAnimationEnable = false;
    private boolean mFirstShowEnable = true;
    private int mLastShowPosition = -1;
    private int mLastDismissPosition = -1;

    @IntDef({ALPHAIN, SCALEIN, SLIDEIN_BOTTOM, SLIDEIN_LEFT, SLIDEIN_RIGHT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface AnimationType {
    }

    /*=== empty ===*/
    private boolean ifShowEmptyView = false;
    private FrameLayout mEmptyLayout;

    /*=== helper ===*/
    private BaseItemTouchHelper mTouchHelper = null;

    /*=== listener ===*/
    private OnRvItemChildCheckedChangeListener mOnRvItemChildCheckedChangeListener;
    private OnRvItemChildClickListener mOnRvItemChildClickListener;
    private OnRvItemChildLongClickListener mOnRvItemChildLongClickListener;
    private OnRvItemChildTouchListener mOnRvItemChildTouchListener;
    private OnRvItemClickListener mOnRvItemClickListener;