Recyclerview 实现拖拽

       private List<TopTabBean.CategorysBean> datas = new ArrayList<>();
        // 编辑完成之后的tab 集合
       private List<TopTabBean.CategorysBean> mEditFinishTabList = new ArrayList<>(); 
        mRvTab.setVerticalScrollBarEnabled(false);
        mRvTab.setHorizontalFadingEdgeEnabled(false);

        // 设置RecyclerView 不可滚动
        mRvTab.setNestedScrollingEnabled(false);
        mRvTab.setOverScrollMode(View.OVER_SCROLL_NEVER);
        mRvTab.setHasFixedSize(true);

        mAdapter = new TabAdapter(ShellMoreTabActivity.this);
        NoScrollGridLayoutManager manager = new NoScrollGridLayoutManager(ShellMoreTabActivity.this, 4);   //  设置4列
        manager.setScrollEnabled(false);  //  设置网格布局不可滚动
        mRvTab.setLayoutManager(manager);

        mItemTouchHelper = new ItemTouchHelper(new TabCallback());
        mItemTouchHelper.attachToRecyclerView(mRvTab);
        mAdapter.setData(datas);
        mRvTab.setAdapter(mAdapter);

         // 进入 某一个 频道
        mAdapter.setOnDetailClickListener(new TabAdapter.OnDetailClickLister() {
            @Override
            public void onItemClick(int position, int id) {
                    // todo
            }
        });
        mAdapter.setOnItemDragListener(new TabAdapter.OnDragLister() {
            @Override
            public void onItemDrag(int position, TabAdapter.TabNewsHolder holder) {

                 // 只有 不被锁住的元素才可以拖动
                if (!datas.get(position).getLocked()) {
                    mItemTouchHelper.startDrag(holder);
                }
            }
        });

【不滚动网格布局】

/**
 * @Author Lee
 * @Time 2018/9/17
 * @Theme  自定义 不滚动网格布局
*/

public class NoScrollGridLayoutManager extends GridLayoutManager {

private boolean isScrollEnabled = true;
public NoScrollGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

public NoScrollGridLayoutManager(Context context, int spanCount) {
    super(context, spanCount);
}

public NoScrollGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
    super(context, spanCount, orientation, reverseLayout);
}

public void setScrollEnabled(boolean flag) {
    this.isScrollEnabled = flag;
}

@Override
public boolean canScrollVertically() {
    return isScrollEnabled && super.canScrollVertically() ;
}

@Override
public boolean canScrollHorizontally() {
    return isScrollEnabled && super.canScrollHorizontally();
   }
}

【TabCallback 】 实现拖动的接口类,需要重写很多方法:

  class TabCallback extends ItemTouchHelper.Callback {

    private boolean isFirstDragUnable = false;
    private boolean isSwipeEnable = true;

    /**
     * 这个方法是设置是否滑动时间,以及拖拽的方向,所以在这里需要判断一下是列表布局还是网格布局,
     * 如果是列表布局的话则拖拽方向为DOWN和UP,如果是网格布局的话则是DOWN和UP和LEFT和RIGHT
     *
     * @param recyclerView
     * @param viewHolder
     * @return
     */
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

        if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
            final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
                    ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
            final int swipeFlags = 0;
            return makeMovementFlags(dragFlags, swipeFlags);
        } else {
            final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            final int swipeFlags = 0;
            return makeMovementFlags(dragFlags, swipeFlags);
        }
    }


    /**
     * onMove()方法则是我们在拖动的时候不断回调的方法,在这里我们需要将正在拖拽的item和集合的item进行交换元素,然后在通知适配器更新数据
     *
     * @param recyclerView
     * @param viewHolder
     * @param target
     * @return
     */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

        //得到当拖拽的viewHolder的Position
        int fromPosition = viewHolder.getAdapterPosition();
        //拿到当前拖拽到的item的viewHolder
        int toPosition = target.getAdapterPosition();

        if(datas.get(fromPosition).getLocked() || datas.get(toPosition).getLocked()){
            // 不可拖拽(包括 不可拖拽到其他地方 或者 其他地方拖拽到 这里 )
            return false;
        }else{

            if (fromPosition < toPosition) {
                for (int i = fromPosition; i < toPosition; i++) {
                    Collections.swap(datas, i, i + 1);
                }
            } else {
                for (int i = fromPosition; i > toPosition; i--) {
                    Collections.swap(datas, i, i - 1);
                }
            }
            mAdapter.notifyItemMoved(fromPosition, toPosition);
            return true;

        }

    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int actionState) {
        /*
        ACTION_STATE_IDLE:闲置状态
        ACTION_STATE_SWIPE:滑动状态
        ACTION_STATE_DRAG:拖拽状态*/

        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
        }
        super.onSelectedChanged(viewHolder, actionState);
    }


    /**
     * 手指松开的时候还原
     *
     * @param recyclerView
     * @param viewHolder
     */
    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        viewHolder.itemView.setBackgroundColor(Color.WHITE);
        mEditFinishTabList = datas;  // 得到重新排序后最终的元素集合
        mAdapter.setData(mEditFinishTabList);

        // 监听 结束拖拽:
     /*    mTvTabEdit.setTextColor(getResources().getColor(R.color.colorAccent));
        mTabHint.setText(mChannelHint);
        mTvTabEdit.setText(mEdit);*/

    }

    /**
     * 重写拖拽不可用
     *
     * @return
     */
    @Override
    public boolean isLongPressDragEnabled() {
        return isFirstDragUnable;
    }

     /**
     * 滑动
     * @return
     */
    @Override
    public boolean isItemViewSwipeEnabled() {
        return isSwipeEnable;
    }
}

【元素】TopTabBean

public class TopTabBean{

private ResultBean result;
private List<CategorysBean> categorys;

public List<CategorysBean> getCategorys() {
    return categorys;
}

public void setCategorys(List<CategorysBean> categorys) {
    this.categorys = categorys;
}

public static class CategorysBean{

    private int id;
    private String  categoryCode;
    private String  categoryName;
    private Boolean   locked;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCategoryCode() {
        return categoryCode;
    }

    public void setCategoryCode(String categoryCode) {
        this.categoryCode = categoryCode;
    }

    public String getCategoryName() {
        return categoryName;
    }

    public void setCategoryName(String categoryName) {
        this.categoryName = categoryName;
    }

    public Boolean getLocked() {
        return locked;
    }

    public void setLocked(Boolean locked) {
        this.locked = locked;
    }

    }
}

【设配器】TabAdapter

  /**
 * @Author Lee
 * @Time 2018/8/10
 * @Theme
*/
public class TabAdapter extends XRecyclerView.Adapter<TabAdapter.TabNewsHolder> {

private final Context mContext;
private List<TopTabBean.CategorysBean> mTopBeanList = new ArrayList<>();
private OnDetailClickLister onDetailClickListener;
private OnDragLister onDragLister;

public TabAdapter(Context context) {
    mContext = context;
}

public void setData(List<TopTabBean.CategorysBean> list) {
    this.mTopBeanList.clear();
    this.mTopBeanList.addAll(list);
    notifyDataSetChanged();
}

public void addData(List<TopTabBean.CategorysBean> list) {
    this.mTopBeanList.addAll(list);
    notifyDataSetChanged();
}


@Override
public TabAdapter.TabNewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View mView = LayoutInflater.from(mContext).inflate(R.layout.item_shell_tab, parent, false);
    return new TabNewsHolder(mView);
}

@Override
public void onBindViewHolder(final TabAdapter.TabNewsHolder holder, final int position) {

    if(mTopBeanList.get(position).getLocked()){

        holder.mTvTabCategory.setTextColor(mContext.getResources().getColor(R.color.colorAccent));
        holder.mTvTabCategory.setBackgroundResource(R.drawable.shape_rect_gray_solid_blue_stroke);
    }

    holder.mTvTabCategory.setText(mTopBeanList.get(position).getCategoryName());
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onDetailClickListener.onItemClick(position, mTopBeanList.get(position).getId() );
        }
    });

    // 拖拽
    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            onDragLister.onItemDrag(position, holder);
            return true;
        }
    });

}


@Override
public int getItemCount() {

    return mTopBeanList != null ? mTopBeanList.size() : 0;
}


public class TabNewsHolder extends XRecyclerView.ViewHolder {

    private TextView mTvTabCategory;

    public TabNewsHolder(View itemView) {
        super(itemView);

        mTvTabCategory = itemView.findViewById(R.id.tv_tab_category);
    }
}


public void setOnDetailClickListener(OnDetailClickLister onDetailClickListener) {
    this.onDetailClickListener = onDetailClickListener;
}

public void setOnItemDragListener(OnDragLister onDragLister) {
    this.onDragLister = onDragLister;
}

public interface OnDetailClickLister {
    void onItemClick(int position, int id);
}

public interface OnDragLister {

    void onItemDrag(int position, TabAdapter.TabNewsHolder holder);
       }
   }

【xml 布局】

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="match_parent"
          android:layout_height="wrap_content">

<TextView
    android:id="@+id/tv_tab_category"
    android:text="体育"
    android:layout_margin="7dp"
    android:gravity="center"
    android:textColor="@color/shell_font_black"
    android:background="@drawable/shape_rect_light_gray_solid"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:textSize="15sp"
    android:layout_width="75dp"
    android:layout_height="wrap_content"/>

 </LinearLayout>

【drawable】

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<stroke android:width="1dp"
    android:color="@color/colorAccent" />
<solid android:color="@color/background"/>
<corners android:radius="3dp" />
</shape>

【注意】点击某一个tab,跳转到相对应的Fragment.

  /**
 *  切换到某一个目录分类
 *
 * @param event
 */
@Subscribe(threadMode = ThreadMode.MAIN)
public void switchEvent(JumpToCategoryEvent event) {
    String categoryName = event.getCategoryName();
    for(int i =0; i< mTabList.size(); i++){
        if(categoryName.equals(mTabList.get(i).getCategoryName())){
            mVp.setCurrentItem(i);
            break;
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容