public class BaseItemAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    private List<Object> dataItems = new ArrayList<>();
    private List<Object> headItems = new ArrayList<>();
    private List<Object> footItems = new ArrayList<>();
    private ItemTypeManager itemTypeManager;
    private LoadMoreManager loadMoreManager;
    private OnItemClickListener onItemClickListener;
    private OnItemLongClickListener onItemLongClickListener;
    private ViewHolderParams params = new ViewHolderParams();
    protected AnimationLoader animationLoader = new AnimationLoader();


    public BaseItemAdapter() {
        itemTypeManager = new ItemTypeManager();
    }


    /**
     * 为数据源注册ViewHolder的管理类{@link ViewHolderManager}<br>
     * ViewHolder的管理类使adapter与view holder的创建绑定解耦<br>
     * 通过{@link ItemTypeManager}管理不同数据源和ViewHolder的关系<br>
     *
     * @param cls     数据源class
     * @param manager 数据源管理类
     * @param <T>     数据源
     * @param <V>     ViewHolder
     * @see #register(Class, ViewHolderManagerGroup)  为相同数据源注册多个ViewHolder的管理类
     */
    public <T, V extends BaseViewHolder> void register(@NonNull Class<T> cls, @NonNull ViewHolderManager<T, V> manager) {
        itemTypeManager.register(cls, manager);
    }

    /**
     * 为相同数据源注册多个ViewHolder的管理类{@link ViewHolderManagerGroup}<br>
     * 主要为相同数据源根据内部属性的值对应多个ViewHolderManager设计，常见的如聊天界面的消息<br>
     *
     * @param cls   数据源class
     * @param group 对应相同数据源的一组数据源管理类
     * @param <T>   数据源
     * @param <V>   ViewHolder
     * @see #register(Class, ViewHolderManager)  为数据源注册ViewHolder的管理类
     */
    public <T, V extends BaseViewHolder> void register(@NonNull Class<T> cls, @NonNull ViewHolderManagerGroup<T> group) {
        itemTypeManager.register(cls, group);
    }

    /**
     * 设置Item view点击监听
     */
    public void setOnItemClickListener(@NonNull OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    /**
     * 设置item view长按监听
     */
    public void setOnItemLongClickListener(@NonNull OnItemLongClickListener onItemLongClickListener) {
        this.onItemLongClickListener = onItemLongClickListener;
    }

    /**
     * 设置Item list
     */
    public void setDataItems(@NonNull List<? extends Object> dataItems) {
        setItem(dataItems);
    }

    /**
     * 添加Item
     */
    public void addDataItem(@NonNull Object item) {
        addDataItem(dataItems.size(), item);
    }

    /**
     * 在指定位置添加Item
     */
    public void addDataItem(int position, @NonNull Object item) {
        addDataItems(position, Collections.singletonList(item));
    }

    /**
     * 添加ItemList
     */
    public void addDataItems(@NonNull List<? extends Object> items) {
        addDataItems(dataItems.size(), items);
    }

    /**
     * 在指定位置添加ItemList
     */
    public void addDataItems(int position, @NonNull List<? extends Object> items) {
        addItem(position, items);
    }

    /**
     * add item的最后调用处
     */
    protected void addItem(int position, @NonNull List<? extends Object> items) {
        dataItems.addAll(position, items);
        notifyItemRangeInserted(position + getHeadCount(), items.size());
    }

    /**
     * 设置item的最后调用处
     */
    protected void setItem(@NonNull List<? extends Object> dataItems) {
        this.dataItems = (List<Object>) dataItems;
        notifyDataSetChanged();
    }

    /**
     * 移动Item的位置 包括数据源和界面的移动
     *
     * @param fromPosition Item之前所在位置
     * @param toPosition   Item新的位置
     */
    public void moveDataItem(int fromPosition, int toPosition) {
        //考虑到跨position(如0->2)移动的时候处理不能Collections.swap
        // if(from<to) to = to + 1 - 1;//+1是因为add的时候应该是to位置后1位，-1是因为先remove了from所以位置往前挪了1位
        dataItems.add(toPosition, dataItems.remove(fromPosition));
        notifyItemMoved(fromPosition + getHeadCount(), toPosition + getHeadCount());
    }


    /**
     * 移除Item 包括数据源和界面的移除
     *
     * @param position 需要被移除Item的position
     */
    public void removeDataItem(int position) {
        removeDataItem(position, 1);
    }

    /**
     * 改变Item 包括数据源和界面的移除
     *
     * @param position 需要被移除第一个Item的position
     * @param position 需要被移除Item的个数
     */
    public void removeDataItem(int position, int itemCount) {
        for (int i = 0; i < itemCount; i++) {
            dataItems.remove(position);
        }
        notifyItemRangeRemoved(position + getHeadCount(), itemCount);
    }

    /**
     * 添加foot View，默认为充满父布局
     * <p>
     * {@link ViewHolderManager#isFullSpan()}
     * {@link ViewHolderManager#getSpanSize(int)}
     *
     * @param footView foot itemView
     * @see HeadFootHolderManager
     * @see UniqueItemManager
     */
    public void addFootView(@NonNull View footView) {
        addFootItem(new UniqueItemManager(new HeadFootHolderManager(footView)));
    }

    /**
     * 添加foot ItemManager ,如是表格不居中需要充满父布局请设置对应属性<br>
     * {@link ViewHolderManager#isFullSpan()}
     * {@link ViewHolderManager#getSpanSize(int)}
     *
     * @param footItem foot item
     * @see HeadFootHolderManager
     */
    public void addFootItem(@NonNull Object footItem) {
        footItems.add(footItem);
    }

    /**
     * 添加head View，默认为充满父布局
     * <p>
     * {@link ViewHolderManager#isFullSpan()}
     * {@link ViewHolderManager#getSpanSize(int)}
     *
     * @param headView head itemView
     * @see HeadFootHolderManager
     * @see UniqueItemManager
     */
    public void addHeadView(@NonNull View headView) {
        addHeadItem(new UniqueItemManager(new HeadFootHolderManager(headView)));
    }

    /**
     * 添加head ItemManager ,如是表格不居中需要充满父布局请设置对应属性<br>
     * {@link ViewHolderManager#isFullSpan()}
     * {@link ViewHolderManager#getSpanSize(int)}
     *
     * @param headItem head item
     * @see HeadFootHolderManager
     */
    public void addHeadItem(@NonNull Object headItem) {
        headItems.add(headItem);
    }

    /**
     * 开启loadMore，使列表支持加载更多<p>
     * 本方法原理是添加{@link #addFootItem(Object)} 并且对添加顺序敏感需要注意在最后调用本方法才可以将加载更多视图放在底部
     *
     * @param loadMoreManager LoadMoreManager
     */
    public void enableLoadMore(@NonNull LoadMoreManager loadMoreManager) {
        this.loadMoreManager = loadMoreManager;
        loadMoreManager.setAdapter(this);
        addFootItem(loadMoreManager);
    }

    /**
     * 加载完成
     *
     * @see LoadMoreManager#loadCompleted(boolean)
     */
    public void setLoadCompleted(boolean isLoadAll) {
        if (loadMoreManager != null) {
            loadMoreManager.loadCompleted(isLoadAll);
        }
    }

    /**
     * 加载失败
     *
     * @see LoadMoreManager#loadFailed()
     */
    public void setLoadFailed() {
        if (loadMoreManager != null) {
            loadMoreManager.loadFailed();
        }
    }

    /**
     * 启动加载动画
     *
     * @param animation BaseAnimation
     */
    public void enableAnimation(BaseAnimation animation) {
        animationLoader.enableLoadAnimation(animation, true);
    }

    /**
     * 启动加载动画
     *
     * @param animation               BaseAnimation
     * @param isShowAnimWhenFirstLoad boolean 是否只有在第一次展示的时候才使用动画
     */
    public void enableAnimation(BaseAnimation animation, boolean isShowAnimWhenFirstLoad) {
        animationLoader.enableLoadAnimation(animation, isShowAnimWhenFirstLoad);
    }

    /**
     * @see AnimationLoader#setInterpolator(Interpolator)
     */
    public void setInterpolator(@NonNull Interpolator interpolator) {
        animationLoader.setInterpolator(interpolator);
    }

    /**
     * @see AnimationLoader#setAnimDuration(long)
     */
    public void setAnimDuration(long animDuration) {
        animationLoader.setAnimDuration(animDuration);
    }

    /**
     * @return 获取当前数据源List，不包含head和foot
     */
    public List<Object> getDataList() {
        return dataItems;
    }


    /**
     * @param position int
     * @return 返回指定位置Item
     */
    public Object getItem(int position) {
        if (position < headItems.size()) {
            return headItems.get(position);
        }

        position -= headItems.size();
        if (position < dataItems.size()) {
            return dataItems.get(position);
        }

        position -= dataItems.size();
        if (position < footItems.size()) {
            return footItems.get(position);
        }

        return null;
    }

    /**
     * 清空数据
     */
    public void clearAllData() {
        clearData();
        headItems.clear();
        footItems.clear();
    }

    /**
     * 清空Item数据不含head 和 foot
     */
    public void clearData() {
        dataItems.clear();
        animationLoader.clear();
    }


    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ViewHolderManager provider = itemTypeManager.getViewHolderManager(viewType);
        BaseViewHolder viewHolder = provider.onCreateViewHolder(parent);
        viewHolder.viewHolderManager = provider;
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        Object item = getItem(position);
        ViewHolderManager manager = holder.viewHolderManager;
        params.setItemCount(getItemCount()).setClickListener(onItemClickListener)
                .setLongClickListener(onItemLongClickListener);
        manager.onBindViewHolder(holder, item, params);
        //赋值 方便以后使用
        holder.itemView.setTag(Const.VIEW_HOLDER_TAG, holder);
        holder.itemData = item;
    }

    @Override
    public int getItemViewType(int position) {
        int type = itemTypeManager.getItemType(getItem(position));
        if (type < 0) {
            throw new RuntimeException("没有为" + getItem(position).getClass() + "找到对应的item itemView manager，是否注册了？");
        }
        return type;
    }

    @Override
    public int getItemCount() {
        return dataItems.size() + getHeadCount() + getFootCount();
    }

    @Override
    public void onViewAttachedToWindow(BaseViewHolder holder) {
        super.onViewAttachedToWindow(holder);
//        System.out.println("onViewAttachedToWindow:::" + holder.getItemPosition() + "==" + holder.getItemData());
        //当StaggeredGridLayoutManager的时候设置充满横屏
        if (holder.getViewHolderManager().isFullSpan() && holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) {
            StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            params.setFullSpan(true);
        }
        animationLoader.startAnimation(holder);
    }

    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
//        System.out.println("onAttachedToRecyclerView:::" + getItemCount());
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            //GridLayoutManager时设置每行的span
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                ViewHolderManager holderManager;

                @Override
                public int getSpanSize(int position) {
                    holderManager = itemTypeManager.getViewHolderManager(getItemViewType(position));
                    return holderManager.getSpanSize(gridManager.getSpanCount());
                }
            });
        }
    }

    /**
     * @return head view个数
     */
    public int getHeadCount() {
        return headItems.size();
    }

    /**
     * @return foot view个数
     */
    public int getFootCount() {
        return footItems.size();
    }

} public class BaseViewHolder extends RecyclerView.ViewHolder {
    public ViewHolderManager viewHolderManager;
    public Object itemData;


    public BaseViewHolder(View itemView) {
        super(itemView);
    }


    public Object getItemData() {
        return itemData;
    }

    /**
     * header和footer的个数也计算在内
     * {@link #getAdapterPosition()}
     */
    public int getItemPosition() {
        return getAdapterPosition();
    }

    public ViewHolderManager getViewHolderManager() {
        return viewHolderManager;
    }

} public abstract class BaseViewHolderManager<T> extends ViewHolderManager<T, BaseViewHolder> {
    @Override
    public abstract void onBindViewHolder(BaseViewHolder holder, T t);

    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent) {
        BaseViewHolder viewHolder = new BaseViewHolder(getItemView(parent));
        onCreateViewHolder(viewHolder);
        return viewHolder;
    }

    /**
     * {@link #onCreateViewHolder}
     */
    protected void onCreateViewHolder(@NonNull BaseViewHolder holder) {
    }

} public class ImageTextBean extends BaseItemData {
    private int img;
    private String imgUrl;
    private String text;

    public ImageTextBean(int img, String text) {
        this.img = img;
        this.text = text;
    }

    public ImageTextBean(String imgUrl, String text) {
        this.imgUrl = imgUrl;
        this.text = text;
    }

    public int getImg() {
        return img;
    }

    public void setImg(int img) {
        this.img = img;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }

    @Override
    public String toString() {
        return text;
    }
} public class TextDragBean extends BaseItemData implements ItemDrag {
    private String text;
    private boolean isCanMove = true;
    private boolean isCanChangeRecycler = true;
    private boolean isCanDrag = true;

    public TextDragBean(String text) {
        this.text = text;
    }

    public TextDragBean(String text, boolean isCanMove) {
        this.text = text;
        this.isCanMove = isCanMove;
    }

    public TextDragBean(String text, boolean isCanMove, boolean isCanChangeRecycler) {
        this.text = text;
        this.isCanMove = isCanMove;
        this.isCanChangeRecycler = isCanChangeRecycler;
    }

    public TextDragBean(String text, boolean isCanMove, boolean isCanChangeRecycler, boolean isCanDrag) {
        this.text = text;
        this.isCanMove = isCanMove;
        this.isCanChangeRecycler = isCanChangeRecycler;
        this.isCanDrag = isCanDrag;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    @Override
    public String toString() {
        return text;
    }

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

    public void setCanMove(boolean canMove) {
        isCanMove = canMove;
    }

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

    public void setCanChangeRecycler(boolean canChangeRecycler) {
        isCanChangeRecycler = canChangeRecycler;
    }

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

    public void setCanDrag(boolean canDrag) {
        isCanDrag = canDrag;
    }
} public class ImageAndTextManager extends BaseViewHolderManager<ImageTextBean> {


    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, @NonNull ImageTextBean data) {
        TextView textView = getView(holder, R.id.text);
        textView.setText(data.getText());
        ImageView imageView = getView(holder, R.id.image);
        imageView.setImageResource(data.getImg());
    }

    @Override
    protected int getItemLayoutId() {
        return R.layout.item_image_text;
    }

} public class TextViewDragManager extends BaseViewHolderManager<TextDragBean> {


    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, @NonNull TextDragBean data) {
        TextView textView = getView(holder, R.id.text);
        textView.setText(data.getText());
    }

    @Override
    protected int getItemLayoutId() {
        return R.layout.item_text;
    }

} public class ItemDragHelper {
    public static final int NONE = -1;

    private OnItemDragListener dragListener = new EmptyDragListener();
    private RecyclerView horizontalRecycler;
    private DragFloatViewHelper floatViewHelper;
    private boolean isDrag;

    private int lastRecyclerPos = NONE;
    private RecyclerView lastRecyclerView;
    private int lastItemPos = NONE;
    private float lastTouchRawX;
    private float lastTouchRawY;
    private int itemViewHeight;

    /**
     * 横向滚动的RecyclerView
     *
     * @param horizontalRecycler
     */
    public ItemDragHelper(@NonNull RecyclerView horizontalRecycler) {
        this.horizontalRecycler = horizontalRecycler;
        floatViewHelper = new DragFloatViewHelper();
    }

    /**
     * 开始拖拽
     *
     * @param viewHolder 选中的Item的ViewHolder
     */
    public void startDrag(@NonNull BaseViewHolder viewHolder) {
        View itemView = viewHolder.itemView;
        int itemPosition = viewHolder.getItemPosition();
        dragListener.setItemViewHolder(viewHolder);
        if (!dragListener.onItemSelected(itemView, itemPosition)) {
            return;
        }

        isDrag = true;

        initParams();
        lastItemPos = itemPosition;
        dragListener.onDragStart();
        floatViewHelper.createView(itemView, lastTouchRawX, lastTouchRawY, dragListener.getScale());
        dragListener.onDrawFloatView(floatViewHelper.getFloatView());


        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) itemView.getLayoutParams();
        itemViewHeight = itemView.getHeight() + params.topMargin + params.bottomMargin;
    }

    private void initParams() {
        lastRecyclerPos = NONE;
        lastRecyclerView = null;
    }

    /**
     * 设置拖拽回调Listener
     *
     * @param onItemDragListener 回调Listener
     */
    public void setOnItemDragListener(@NonNull OnItemDragListener onItemDragListener) {
        this.dragListener = onItemDragListener;
    }

    public RecyclerView getHorizontalRecycler() {
        return horizontalRecycler;
    }

    /**
     * 必须完整处理Touch事件，可以在Activity或者外层的ViewGroup或可以拦截Touch事件的地方回调都可以
     *
     * @param event touch的event
     * @return true表示消耗掉事件
     */
    public boolean onTouch(@NonNull MotionEvent event) {
        lastTouchRawX = event.getRawX();
        lastTouchRawY = event.getRawY();

        if (!isDrag) {
            return false;
        }
        //如果drag过程没有MOVE事件，lastVerticalPos和lastRecyclerView是不能被正确初始化的，这样dragFinish回调就会有问题
//        if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
        floatViewHelper.updateView((int) lastTouchRawX, (int) lastTouchRawY);
        moveIfNecessary(lastTouchRawX, lastTouchRawY);
        scrollRunnableStart();
//        }

        if (event.getActionMasked() == MotionEvent.ACTION_UP ||
                event.getActionMasked() == MotionEvent.ACTION_CANCEL ||
                event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
            stopDrag();
        }

        return true;
    }

    private void scrollRunnableStart() {
        if (lastRecyclerView != null) {
            lastRecyclerView.removeCallbacks(scrollRunnable);
            scrollRunnable.run();
            lastRecyclerView.invalidate();
        }
    }

    private void stopDrag() {
        if (isDrag) {
            dragListener.onDragFinish(lastRecyclerView, lastRecyclerPos, lastItemPos);
            floatViewHelper.removeView();
        }

        isDrag = false;
    }


    /**
     * 当用户拖动的时候，计算是否需要移动Item
     *
     * @param touchRawX float event.getRawX()
     * @param touchRawY float event.getRawY()
     */
    private boolean moveIfNecessary(float touchRawX, float touchRawY) {
        boolean result = true;

        //找到当前触摸点下的recyclerView
        float[] location = getInsideLocation(horizontalRecycler, touchRawX, touchRawY);
        View view = horizontalRecycler.findChildViewUnder(location[0], location[1]);
        int recyclerPos = getPositionByChildView(view);
//        System.out.println("find_parent_out:lastRecPos:" + lastRecyclerPos + "-recPos:" + recyclerPos + "=loc0:" + location[0] + "=loc1:" + location[1]);
        RecyclerView recyclerView = findRecyclerView(view);

        //没有找到所属位置或者目标RecyclerView，则不继续
        if (recyclerPos == NONE || recyclerView == null) {
            return false;
        }

        //找到当前触摸点下的itemView
        location = getInsideLocation(recyclerView, touchRawX, touchRawY);
        float itemX = location[0];
        float itemY = location[1];
        View itemView = recyclerView.findChildViewUnder(itemX, itemY);
        int itemPos = getTargetItemPos(itemView, itemY, lastRecyclerPos, recyclerPos);

//        System.out.println("find_parent_out:lastItemPos:" + lastItemPos + "==itemPos:" + itemPos + "==childX:" + itemX + "===childY:" + itemY);
        if (isSelectedRecyclerView(lastRecyclerPos, recyclerPos)) {
            dragListener.onRecyclerSelected(recyclerView, recyclerPos);
            lastRecyclerPos = recyclerPos;
            lastRecyclerView = recyclerView;
        } else if (isChangeRecyclerView(lastRecyclerPos, recyclerPos)) {
            itemPos = calcItemPositionWhenChangeRecycler(recyclerView, itemView, itemPos, itemX, itemY);
//            System.out.println("find_parent_inside:" + itemPos + "==" + lastRecyclerPos + "-" + recyclerPos + "==" + "childX:" + itemX + "childY:" + itemY);
            if (itemPos != NONE) {
                //当recycler change的时候，返回Recycler Position
                recyclerPos = dragListener.onRecyclerChangedRecyclerPosition(lastRecyclerView, recyclerView,
                        lastItemPos, itemPos, lastRecyclerPos, recyclerPos);
                //当recycler切换的时候，返回Item位置，有的Recycler不管touch在什么位置都要替换指定的item位置
                itemPos = dragListener.onRecyclerChangedItemPosition(lastRecyclerView, recyclerView,
                        lastItemPos, itemPos, lastRecyclerPos, recyclerPos);
                boolean isChanged = dragListener.onRecyclerChanged(lastRecyclerView, recyclerView,
                        lastItemPos, itemPos, lastRecyclerPos, recyclerPos);
                if (!isChanged) {
                    return result;
                }
//                System.out.println("find_parent:" + lastRecyclerPos + "-" + verticalPos);
                //在切换recycle view并且触摸到子recycle view的item的时候才真正去改变值
                lastRecyclerPos = recyclerPos;
                lastRecyclerView = recyclerView;
                //因为切换父控件，所以需要重置为当前itemPos，不然上个的最后位置有可能超过当前的大小抛出错误
                lastItemPos = itemPos;
            }

        }

        if (itemPos == NONE) {
            return result;
        }

        if (isItemNeedChange(itemView, lastItemPos, itemPos, itemY)) {
            itemPos = dragListener.onItemChangedPosition(recyclerView, lastItemPos, itemPos, lastRecyclerPos);

            boolean isChanged = dragListener.onItemChanged(recyclerView, lastItemPos, itemPos, lastRecyclerPos);
            if (!isChanged) {
                return result;
            }
            scrollToRightPositionWhenItemChanged(recyclerView, itemView, itemPos);
//            System.out.println("find:" + lastRecyclerPos + "-" + recyclerPos + "======" + lastItemPos + "-" + itemPos);
            lastItemPos = itemPos;
        }
        return result;
    }

    /**
     * 当item位置变换，滚动recycler到正确的位置
     * TODO: 2017/2/21 0021 整理更优雅的写法  还有scrollToPosition(0)是否必要？
     */
    private void scrollToRightPositionWhenItemChanged(RecyclerView recyclerView, View itemView, int itemPos) {
        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof ItemTouchHelper.ViewDropHandler) {
            OrientationHelper helper = OrientationHelper.createVerticalHelper(layoutManager);
            int start = helper.getDecoratedStart(itemView);
            int end = helper.getDecoratedEnd(itemView);
            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(
                    itemPos, lastItemPos > itemPos ? start : end - itemViewHeight);
//                System.out.println(lastItemPos + "-" + childPos + "OrientationHelperOrientationHelper:"
//                        + height + "==" + itemViewHeight + "=||=" + start + "===" + end + "||||||" + myStart + "===" + itemTargetView.getHeight() );
        }
        if (lastItemPos == 0 || itemPos == 0) {
            recyclerView.scrollToPosition(0);
        }
    }

    /**
     * 获取当前点击的位置在RecyclerView内部的坐标 (Y坐标范围0+padding到height-padding)?
     */
    private float[] getInsideLocation(RecyclerView recyclerView, float touchRawX, float touchRawY) {
        float[] result = new float[2];
        int[] location = new int[2];
        recyclerView.getLocationOnScreen(location);
        result[0] = touchRawX - location[0];
        result[1] = touchRawY - location[1];
//        System.out.println("getInsideLocation:" + result[0] + "-" + result[1] + "==" + "X:" + touchRawX + "Y:" + touchRawY);

        result[0] = result[0] / dragListener.getScale();
        result[1] = result[1] / dragListener.getScale();

        int minY = recyclerView.getPaddingTop();
        int maxY = recyclerView.getHeight() - recyclerView.getPaddingBottom();
        result[1] = Math.min(Math.max(result[1], minY), maxY);


        return result;
    }

    /**
     * 当在两个RecyclerView中切换时，计算目标RecyclerView中Child位置 (若目标RecyclerView为空返回0)
     */
    private int calcItemPositionWhenChangeRecycler(RecyclerView verticalRecycler, View itemView, int itemPos, float childX, float childY) {
        //若目标RecyclerView为空返回0
        if (itemPos == NONE && verticalRecycler.getAdapter().getItemCount() == 0) {
            itemPos = 0;
        } else if (itemView != null) {
            int top = itemView.getTop();
            if ((top + itemView.getHeight() * dragListener.getMoveLimit()) < childY) {
                //证明滑动位置在targetView的下部，所以要插入到当前位置+1
                itemPos++;
            }
        }

        return itemPos;
    }

    /**
     * 从view中获取需要操作的RecyclerView
     *
     * @param view View
     */
    protected RecyclerView findRecyclerView(View view) {
        if (view == null) {
            return null;
        }

        if (view instanceof RecyclerView) {
            return (RecyclerView) view;
        } else if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            RecyclerView recyclerView;
            for (int i = 0, count = viewGroup.getChildCount(); i < count; i++) {
                recyclerView = findRecyclerView(viewGroup.getChildAt(i));
                if (recyclerView != null) {
                    return recyclerView;
                }
            }
        }
        return null;
    }


    /**
     * 滚动Runnable，为了可持续滚动
     */
    private final Runnable scrollRunnable = new Runnable() {

        @Override
        public void run() {
            float[] horLocation = getInsideLocation(horizontalRecycler, lastTouchRawX, lastTouchRawY);
            float[] verLocation = getInsideLocation(lastRecyclerView, lastTouchRawX, lastTouchRawY);
            boolean isHorizontalScroll = scrollIfNecessary(horizontalRecycler, (int) horLocation[0], (int) horLocation[1]);
            boolean isVerticalScroll = scrollIfNecessary(lastRecyclerView, (int) verLocation[0], (int) verLocation[1]);
            if (isDrag && (isHorizontalScroll || isVerticalScroll)) {
                //it might be lost during scrolling
                moveIfNecessary(lastTouchRawX, lastTouchRawY);
                lastRecyclerView.removeCallbacks(scrollRunnable);
                ViewCompat.postOnAnimation(lastRecyclerView, this);
            }
        }
    };

    /**
     * 当用户滚动到边缘的时候,计算是否需要滚动
     */
    private boolean scrollIfNecessary(RecyclerView recyclerView, int curX, int curY) {
        if (!isDrag) {
            return false;
        }

        RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
        int scrollX = 0;
        int scrollY = 0;
        if (lm.canScrollHorizontally()) {
            scrollX = dragListener.calcHorizontalScrollDistance(recyclerView, curX, curY);
        }
        if (lm.canScrollVertically()) {
            scrollY = dragListener.calcVerticalScrollDistance(recyclerView, curX, curY);
        }
//        System.out.println("scroll:::::" + scrollY + "=" + recyclerView.getScrollY() + "curY::" + curY);
//        System.out.println("scroll:::::" + scrollX + "=" + recyclerView.getScrollX() + "curX::" + curX);

        if (scrollX != 0 || scrollY != 0) {
            recyclerView.scrollBy(scrollX, scrollY);
        }
        return scrollX != 0 || scrollY != 0;
    }


    /**
     * 获取需要move的目标Position，即toPosition
     *
     * @return NONE为找不到
     */
    private int getTargetItemPos(View itemTargetView, float childY, int lastRecyclerPos, int currRecyclerPos) {
        int itemPos = getPositionByChildView(itemTargetView);

        if (itemPos == NONE) {
            return itemPos;
        }

        if ((itemPos != lastItemPos || lastRecyclerPos != currRecyclerPos)) {
            return itemPos;
        }

        return NONE;
    }


    /**
     * 两个Item是否需要move
     */
    private boolean isItemNeedChange(View itemView, int lastItemPos, int itemPos, float itemY) {
        if (itemView == null || lastItemPos == NONE || itemPos == NONE || lastItemPos == itemPos) {
            return false;
        }
        int top = itemView.getTop();

        int moveLimit = (int) (top + itemView.getHeight() * dragListener.getMoveLimit());
//        System.out.println("isNeedRemove-top:" + top + "==height:" + itemView.getHeight()
//                + "==touchY:" + itemY + "moveLimit==" + moveLimit + "lastItemPos > itemPos===" + (lastItemPos > itemPos));

        if (lastItemPos > itemPos) {
//            return touchY < moveLimit && top >= 0;
            return itemY < moveLimit;
        } else {
            return itemY > moveLimit;
        }
    }

    /**
     * touch的位置是否为当前view，防止两个item切换时的抖动问题
     */
    private boolean isCurrPosition(float childY, View itemView) {
//        System.out.println("isCurrPosition:" + (childY > itemView.getTop() && childY < itemView.getBottom()));
        return childY >= itemView.getTop() && childY <= itemView.getBottom();
    }


    /**
     * 查找当前view在RecyclerView中的位置 没有返回NONE
     */
    private int getPositionByChildView(View itemView) {
        if (itemView == null) {
            return NONE;
        }
        try {
            return ((RecyclerView.LayoutParams) itemView.getLayoutParams()).getViewAdapterPosition();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return NONE;
    }

    /**
     * 是否真正切换了RecyclerView
     * 需要注意这里把没有切换后没有touch到Item当成不是真正切换
     */
    private boolean isChangeRecyclerView(int lastRecyclerPos, int currRecyclerPos) {
        return lastRecyclerPos != currRecyclerPos && lastRecyclerPos != NONE && currRecyclerPos != NONE;
    }

    /**
     * 是否为初次选中RecycleView
     */
    private boolean isSelectedRecyclerView(int lastRecyclerPos, int currRecyclerPos) {
        return lastRecyclerPos == NONE && currRecyclerPos != NONE;
    }

    /**
     * 是否为第一次选中子ItemView
     */
    private boolean isSelectedChildView(int lastChildPos, int currChildPos) {
        return lastChildPos == NONE && currChildPos != NONE;
    }

    static class EmptyDragListener extends OnItemDragListener {

    }
} public class ViewScaleHelper {
    public static final int VIEW_WIDTH_KEY = -21681;
    public static final int VIEW_HEIGHT_KEY = -21682;

    private List<View> verticalViewList = new ArrayList<>();
    private View contentView;
    private View horizontalView;
    private boolean isInScaleMode;

    private int verticalWidth;
    private float scale = 0.5f;


    public synchronized boolean isInScaleMode() {
        return isInScaleMode;
    }

    public float getScale() {
        return scale;
    }

    /**
     * 开启或关闭缩放模式
     */
    public void toggleScaleModel() {
        if (isInScaleMode) {
            stopScaleModel();
        } else {
            startScaleModel();
        }
    }

    /**
     * 开启缩放
     */
    public synchronized void startScaleModel() {
        if (isInScaleMode) {
            return;
        }
        isInScaleMode = true;

        scaleContentView(contentView);
        scaleContentView(horizontalView);
        horizontalView.setScaleX(scale);
        horizontalView.setScaleY(scale);
        horizontalView.setPivotX(0f);
        horizontalView.setPivotY(0f);


        for (View view : verticalViewList) {
            //当父视图setScaleX的时候此时的宽度即为需要被记住的宽度，这样可以保证缩小后的宽度不再次恢复原来的大小
            verticalWidth = view.getWidth();
            scaleVerticalView(view, verticalWidth);
            view.requestLayout();
        }
    }

    /**
     * 关闭缩放
     */
    public synchronized void stopScaleModel() {
        if (!isInScaleMode) {
            return;
        }
        isInScaleMode = false;
        restoreView(contentView);
        restoreView(horizontalView);
        for (View view : verticalViewList) {
            restoreView(view);
            view.requestLayout();
        }
        horizontalView.setScaleX(1f);
        horizontalView.setScaleY(1f);

    }

    public void addVerticalView(View view) {
        verticalViewList.add(view);

        if (isInScaleMode) {
            scaleVerticalView(view, verticalWidth);
        }

    }

    /**
     * 缩放垂直视图
     * 垂直的视图宽度需要记住当前缩小后的宽度，然后设置到layout param，不然会充满屏幕宽度
     * 高度无需控制，就是需要充满屏幕
     *
     * @param width 需要被保持的宽度
     */
    private void scaleVerticalView(View view, int width) {
        recordViewWidth(view);
        view.getLayoutParams().width = width;
    }

    /**
     * 缩放内容视图
     * 内容视图高宽需要缩放1/scale倍数，后续进行setScaleX and Y的时候才能和原来的视图同等大小
     *
     * @param view
     */
    private void scaleContentView(View view) {
        recordViewWidth(view);
        recordViewHeight(view);
        view.getLayoutParams().width = (int) (view.getWidth() / scale);
        view.getLayoutParams().height = (int) (view.getHeight() / scale);
    }

    private void recordViewWidth(View view) {
        view.setTag(VIEW_WIDTH_KEY, view.getLayoutParams().width);
    }

    private void recordViewHeight(View view) {
        view.setTag(VIEW_HEIGHT_KEY, view.getLayoutParams().height);
    }

    private void restoreView(View view) {
        Object tag = null;
        if ((tag = view.getTag(VIEW_WIDTH_KEY)) != null) {
            view.getLayoutParams().width = (int) tag;
        }
        if ((tag = view.getTag(VIEW_HEIGHT_KEY)) != null) {
            view.getLayoutParams().height = (int) tag;
        }
    }

    public View getContentView() {
        return contentView;
    }

    public void setContentView(View contentView) {
        this.contentView = contentView;
    }

    public View getHorizontalView() {
        return horizontalView;
    }

    public void setHorizontalView(View horizontalView) {
        this.horizontalView = horizontalView;
    }
} public class UniqueItemManager implements ItemManager {
    private ViewHolderManager<? extends UniqueItemManager, ? extends BaseViewHolder> manager;

    public UniqueItemManager(ViewHolderManager<? extends UniqueItemManager, ? extends BaseViewHolder> manager) {
        this.manager = manager;
    }

    @Override
    public String getItemTypeName() {
        return toString();
    }

    @Override
    public ViewHolderManager getViewHolderManager() {
        return manager;
    }
} public abstract class OnItemDragListener {
    protected ItemData dragItemData;
    protected int originalRecyclerPosition;
    protected int originalItemPosition;

    protected int horizontalScrollMaxSpeed = 15;
    protected int verticalScrollMaxSpeed = 10;
    protected float horizontalLimit = 100;
    protected float verticalLimit = 200;


    /**
     * 拖拽结束时回调
     * todo 考虑是否把参数抽成参数对象，其他方法也存在此问题
     *
     * @param recyclerView 所在RecyclerView
     * @param recyclerPos  RecyclerView所在position
     * @param itemPos      item所在position
     */
    public void onDragFinish(RecyclerView recyclerView, int recyclerPos, int itemPos) {
        dragItemData.setVisibility(View.VISIBLE);
        recyclerView.findViewHolderForAdapterPosition(itemPos).itemView.setVisibility(View.VISIBLE);
    }

    /**
     * 拖拽开始时回调
     */
    public void onDragStart() {
    }

    /**
     * 每次拖动时候都要设置Item数据源，方便Recycler切换时候添加到新的Recycler
     *
     * @param viewHolder 当前拖动的Item view holder
     */
    public void setItemViewHolder(@NonNull BaseViewHolder viewHolder) {
        Object itemData = viewHolder.getItemData();
        if (itemData instanceof ItemData) {
            this.dragItemData = (ItemData) itemData;
        } else {
            //用到了Visibility相关方法控制被拖动item的隐藏和展现
            // 可以在继承的时候重写此方法去除此限制，但是必须自己实现被拖动item的隐藏和展现
            throw new IllegalArgumentException("数据源必须实现ItemData接口");
        }

    }

    /**
     * 第一次被选中的时候回调
     *
     * @param selectedView 选中的RecyclerView
     * @param selectedPos  选中的位置
     * @return 是否允许RecyclerView切换，目前返回值无效
     */
    public boolean onRecyclerSelected(RecyclerView selectedView, int selectedPos) {
        originalRecyclerPosition = selectedPos;
        return true;
    }

    /**
     * 触摸切换RecyclerView的时候回调
     *
     * @param fromView            上个RecyclerView
     * @param toView              当前RecyclerView
     * @param itemFromPos         上个item选中的位置
     * @param itemToPos           当前item选中的位置
     * @param recyclerViewFromPos 上个RecyclerView选中的位置
     * @param recyclerViewToPos   当前RecyclerView选中的位置
     * @return 是否允许RecyclerView切换，如果false，则此次切换无效
     */
    public boolean onRecyclerChanged(RecyclerView fromView, RecyclerView toView, int itemFromPos, int itemToPos,
                                     int recyclerViewFromPos, int recyclerViewToPos) {
        if (!isItemCanChangeRecycler(dragItemData)) {
            return false;
        }
        BaseItemAdapter adapter = (BaseItemAdapter) toView.getAdapter();
        Object itemData = adapter.getItem(itemToPos);
        //如果追加到另一个Recycler的末尾则itemData为null，此情况是可以move的
        if (itemData != null && !isItemCanMove(itemData)) {
            return false;
        }
        adapter.addDataItem(itemToPos, dragItemData);

        adapter = (BaseItemAdapter) fromView.getAdapter();
        adapter.removeDataItem(itemFromPos);
        return true;
    }

    /**
     * 第一次被选中的时候回调
     *
     * @param selectedView 选中的RecyclerView
     * @param selectedPos  选中的位置
     * @return 是否允许Item选中拖动，如果false，则此次开启拖动无效
     */
    public boolean onItemSelected(View selectedView, int selectedPos) {
        boolean isItemCanDrag = isItemCanDrag(dragItemData);
        if (isItemCanDrag) {
            originalItemPosition = selectedPos;
            dragItemData.setVisibility(View.INVISIBLE);
            selectedView.setVisibility(View.INVISIBLE);
        }
        return isItemCanDrag(dragItemData);
    }

    /**
     * 触摸时切换Item的时候回调
     *
     * @param recyclerView    包含Item的RecyclerView
     * @param fromPos         上个选中的位置
     * @param toPos           当前选中的位置
     * @param recyclerViewPos 当前包含Item的RecyclerView选中的位置
     * @return 是否允许Item切换 如果false，则此次切换无效
     */
    public boolean onItemChanged(RecyclerView recyclerView, int fromPos, int toPos, int recyclerViewPos) {
        BaseItemAdapter adapter = (BaseItemAdapter) recyclerView.getAdapter();

        if (!isItemCanMove(adapter.getItem(toPos))) {
            return false;
        }

        adapter.moveDataItem(fromPos, toPos);
        return true;
    }

    private boolean isItemCanChangeRecycler(Object itemData) {
        ItemDrag itemDrag = getItemDrag(itemData);
        return itemDrag == null || itemDrag.isCanChangeRecycler();
    }

    private boolean isItemCanMove(Object itemData) {
        ItemDrag itemDrag = getItemDrag(itemData);
        return itemDrag == null || itemDrag.isCanMove();
    }

    private boolean isItemCanDrag(Object itemData) {
        ItemDrag itemDrag = getItemDrag(itemData);
        return itemDrag == null || itemDrag.isCanDrag();
    }

    private ItemDrag getItemDrag(Object itemData) {
        if (itemData instanceof ItemDrag) {
            return (ItemDrag) itemData;
        }
        return null;
    }

    /**
     * 获取缩放比例，主要配合recycler缩放时{@link ViewScaleHelper}使用，需要复写返回正确的缩放比例
     *
     * @return 缩放比例 如0.5
     * @see ViewScaleHelper
     */
    public float getScale() {
        return 1;
    }

    /**
     * Recycler切换前回调此方法获取替换的目标Recycler<br>
     * 如果只是是否允许此Recycler被替换使用{@link #onRecyclerChanged}
     *
     * @param recyclerViewToPos 目标RecyclerViewPosition
     * @param itemToPos         目标ItemPosition
     * @return 默认null[目标RecyclerViewPosition, 目标ItemPosition]
     */
    public int onRecyclerChangedRecyclerPosition(RecyclerView fromView, RecyclerView toView, int itemFromPos, int itemToPos,
                                                 int recyclerViewFromPos, int recyclerViewToPos) {
        return recyclerViewToPos;
    }


    /**
     * Recycler切换前回调此方法获取替换的目标Item<br>
     * 有的Recycler不管touch在什么位置都要替换指定的item位置<br>
     * 如果只是是否允许此Recycler被替换使用{@link #onRecyclerChanged}
     *
     * @param recyclerViewToPos 目标RecyclerViewPosition
     * @param itemToPos         目标ItemPosition
     * @return 默认目标ItemPosition
     */
    public int onRecyclerChangedItemPosition(RecyclerView fromView, RecyclerView toView, int itemFromPos, int itemToPos,
                                             int recyclerViewFromPos, int recyclerViewToPos) {
        return itemToPos;
    }

    /**
     * Item切换前回调此方法获取替换的目标Item<br>
     * 有时需要指定要替换的Item位置，使用此方法<br>
     * 如果只是是否允许此Item被替换使用{@link #onItemChanged}
     *
     * @param toPos 目标ItemPosition
     * @return 默认返回 toPos
     */
    public int onItemChangedPosition(RecyclerView recyclerView, int fromPos, int toPos, int recyclerViewPos) {
        return toPos;
    }

    /**
     * @return 最大水平滚动速度
     */
    public int getHorizontalScrollMaxSpeed() {
        return (int) (horizontalScrollMaxSpeed / getScale());
    }

    /**
     * @return 最大垂直滚动速度
     */
    public int getVerticalScrollMaxSpeed() {
        return (int) (verticalScrollMaxSpeed / getScale());
    }

    /**
     * 在范围内才可以触发滚动
     *
     * @return 水平滚动临界范围
     */
    public float getHorizontalLimit() {
        return horizontalLimit / getScale();
    }

    /**
     * 在范围内才可以触发滚动
     *
     * @return 垂直滚动临界范围
     */
    public float getVerticalLimit() {
        return verticalLimit / getScale();
    }

    /**
     * 计算垂直水平距离
     * <p>
     * todo 可参考ItemTouchHelper改造成加速器形式 还有calcVerticalScrollDistance
     *
     * @return 水平滚动距离
     */
    public int calcHorizontalScrollDistance(View view, int touchX, int touchY) {
        int direct = calcScrollHorizontalDirect(touchX, view.getWidth());
        int scrollDistance = 0;
        if (direct < 0) {
            float level = (getHorizontalLimit() - touchX) / getHorizontalLimit();
            scrollDistance = -calcScrollDistance(level, getHorizontalScrollMaxSpeed());
        } else if (direct > 0) {
            float level = (touchX - view.getWidth() + getHorizontalLimit()) / getHorizontalLimit();
            scrollDistance = calcScrollDistance(level, getHorizontalScrollMaxSpeed());
        }
        return scrollDistance;
    }

    /**
     * 计算垂直滚动距离
     *
     * @return 垂直滚动距离
     */
    public int calcVerticalScrollDistance(View view, int touchX, int touchY) {
        int direct = calcScrollVerticalDirect(touchY, view.getHeight());
        int scrollDistance = 0;
        if (direct < 0) {
            float level = (getVerticalLimit() - touchY) / getVerticalLimit();
            scrollDistance = -calcScrollDistance(level, getVerticalScrollMaxSpeed());
        } else if (direct > 0) {
            float level = (touchY - view.getHeight() + getVerticalLimit()) / getVerticalLimit();
            scrollDistance = calcScrollDistance(level, getVerticalScrollMaxSpeed());
        }
        return scrollDistance;
    }

    /**
     * 计算滚动距离
     *
     * @param touchLevel 触摸滑动速度等级
     * @param maxSpeed   最大速度
     * @return 滚动距离 touchLevel*maxSpeed
     */
    protected int calcScrollDistance(float touchLevel, int maxSpeed) {
        touchLevel = touchLevel > 1 ? 1f : touchLevel;
        return (int) (touchLevel * maxSpeed);
    }

    /**
     * 计算水平滚动指向
     * 可以对touchX的值进行过滤  例:滑动超出view(touchX<0||touchX>viewWidth)
     *
     * @return -1:像左滚动 0:不滚动 1:像右滚动
     */
    protected int calcScrollHorizontalDirect(int touchX, int viewWidth) {
        if (touchX < getHorizontalLimit()) {
            return -1;
        } else if (touchX > viewWidth - getHorizontalLimit()) {
            return 1;
        }
        return 0;
    }

    /**
     * 计算垂直滚动指向
     * 可以对touchY的值进行过滤  例:滑动超出view(touchY<0||touchY>viewHeight)
     *
     * @return -1:像上滑 0:不滑动 1:像下滑
     */
    protected int calcScrollVerticalDirect(int touchY, int viewHeight) {
        if (touchY < getVerticalLimit()) {
            return -1;
        } else if (touchY > viewHeight - getVerticalLimit()) {
            return 1;
        }
        return 0;
    }

    /**
     * 对浮动view进行处理 如：动画的处理
     *
     * @param floatView 浮动的view
     */
    public void onDrawFloatView(View floatView) {
        floatView.setScaleX(0.95f);
        floatView.setScaleY(0.95f);
        floatView.setRotation(0.9f);
        floatView.setAlpha(0.8f);
    }

    /**
     * 当touch位置在目标视图高度的边界值时对两个Item进行move的处理
     * 默认0.5即超过一半高度时允许两个Item move
     *
     * @return 两个Item是否进行move边界值
     */
    public float getMoveLimit() {
        return 0.5f;
    }
} public abstract class OnItemLongClickListener implements View.OnLongClickListener {

    @Override
    public boolean onLongClick(View v) {
        BaseViewHolder viewHolder = ListenerUtil.getViewHolderByItemView(v);
        if (viewHolder == null) {
            return false;
        }

        onItemLongClick(viewHolder);
        return true;
    }

    /**
     * 点击回调 可以通过viewHolder get到需要的数据
     */
    protected abstract void onItemLongClick(BaseViewHolder viewHolder);

}
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.freelib.multiitem.adapter.BaseItemAdapter;
import com.freelib.multiitem.adapter.holder.BaseViewHolder;
import com.freelib.multiitem.adapter.holder.BaseViewHolderManager;
import com.freelib.multiitem.demo.bean.ImageTextBean;
import com.freelib.multiitem.demo.bean.TextDragBean;
import com.freelib.multiitem.demo.viewholder.ImageAndTextManager;
import com.freelib.multiitem.demo.viewholder.TextViewDragManager;
import com.freelib.multiitem.helper.ItemDragHelper;
import com.freelib.multiitem.helper.ViewScaleHelper;
import com.freelib.multiitem.item.UniqueItemManager;
import com.freelib.multiitem.listener.OnItemDragListener;
import com.freelib.multiitem.listener.OnItemLongClickListener;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
package com.freelib.multiitem.demo;





@EActivity(R.layout.activity_panel)
public class PanelActivity extends AppCompatActivity {
    @ViewById(R.id.panel_content)
    protected View contentView;

    public static final int NONE = -1;
    private RecyclerView horizontalRecycler;
    private BaseItemAdapter adapter;
    private ItemDragHelper dragHelper;
    private ViewScaleHelper scaleHelper;

    public static void startActivity(Context context) {
        PanelActivity_.intent(context).start();
    }

    @AfterViews
    protected void initView() {
        setTitle(R.string.panel_title);

        horizontalRecycler = (RecyclerView) findViewById(R.id.recyclerView);

        adapter = new BaseItemAdapter();
        //此处为了简单所以使用不可复用的模式，正式业务视具体情况而定！！！
        adapter.addDataItems(Arrays.asList(new UniqueItemManager(new RecyclerViewManager(15)),
                new UniqueItemManager(new RecyclerViewManager(1)), new UniqueItemManager(new RecyclerViewManager(25)),
                new UniqueItemManager(new RecyclerViewManager(15)), new UniqueItemManager(new RecyclerViewManager(5))));
        //设置横向滚动LinearLayoutManager
        horizontalRecycler.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
        horizontalRecycler.setAdapter(adapter);

        //ItemDragHelper，需要传入外层的横向滚动的RecyclerView
        dragHelper = new ItemDragHelper(horizontalRecycler);
        dragHelper.setOnItemDragListener(new OnBaseDragListener());

        scaleHelper = new ViewScaleHelper();
        //设置最外层的Content视图
        scaleHelper.setContentView(contentView);
        //设置横向的Recycler列表视图
        scaleHelper.setHorizontalView(horizontalRecycler);

        //监听横向滚动RecyclerView双击事件，并开启关闭缩放模式
        doubleTapToggleScale();
    }

    private void doubleTapToggleScale() {
        GestureDetector doubleTapGesture = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                scaleHelper.toggleScaleModel();
                return super.onDoubleTap(e);
            }
        });
        horizontalRecycler.setOnTouchListener((v, event) -> doubleTapGesture.onTouchEvent(event));
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //需要把touch事件传给dragHelper，true表示消耗掉事件
        //需要保证在Activity或者外层的ViewGroup或可以拦截Touch事件的地方回调都可以
        return dragHelper.onTouch(ev) || super.dispatchTouchEvent(ev);
    }

    class OnBaseDragListener extends OnItemDragListener {