Android 初步实现item可拖拽RecyclerView (Grid模式下)
来源:互联网 发布:网络平台运营方案 编辑:程序博客网 时间:2024/06/16 16:25
Android 初步实现item可拖拽RecyclerView (Grid模式下)
0.首先先给一张效果图。部分功能么有实现,好吧我承认我不太会。仅仅给自己留个记录。供参考。
1.先说下思路 用到的类:DragParent (继承RelativeLayout) 、DragGridView (继承RecyclerView)、Bean item数据项、DragAdapter (DragGridView适配器)
外加2个接口PreDragListener(即将进入拖拽状态)、DraggingListener(拖拽中,拖拽结束)。
2.当长按 DragGridView 的item时,该Item View设置不可见状态,通过接口方法告知 DragParent 即将进入拖拽状态。
3.DragParent 进入拖拽状态 马上获取被拖拽item View 对应的Bitmap,并把该Bitmap放入ImageView中,添加到DragParent 内部 item view的位置。
4.重写DragParent dispatchTouchEvent() ,在拖拽状态下 Move 计算当前event x、y坐标位于DragGridView 的那个位置。
5.如果被拖拽的item的位置与当前拖拽点x、y坐标所属item位置不一致,说明需要DragGridView remove掉被拖拽item ,并且在当前拖拽点位置insert。
6.首先自定义一个ID。遇到不要忘记,主要是实现 DragGridView 的itemView与 Bean进行绑定用的。
<?xml version="1.0" encoding="utf-8"?><resources> <item name="id_bean_" type="id"/></resources>7.先看看 Bean 和接口类 简写了。
public class Bean { String str;//item+i boolean isDragged;//是否处于拖拽状态 int rid;//该Bean对应的 图片资源id boolean isLongClicked; public Bean(String str, int rid) { this.str = str; this.rid = rid; }}
public interface PreDragListener { /** * 某个DragGridView 的ItemView 进入拖拽状态回调 */ void preDrag(View view);}
public interface DraggingListener { /** * 拖拽中时,返回的当前拖拽的坐标 */ void dragging(float x, float y); void dragEnd();}
8.DragParent 实现了PreDragListener,当DragAdapter 内部触发长按回调时 需要调用该接口告知 DragParent那个itemView 进入拖拽状态。
9.DragGridView 实现了DraggingListener,当DragParent 内部添加的imageview移动时,不断检测拖拽点在DragGridView 的位置并做remove和insert。
10.先看下DragAdapter ,内部调用PreDragListener。
public class DragAdapter extends RecyclerView.Adapter<DragAdapter.ViewH> implements View.OnLongClickListener, View.OnClickListener { Context mContext; public List<Bean> mBeans = new ArrayList<>(); PreDragListener mListener; public Bean draggedBean; public void setListener(PreDragListener listener) { mListener = listener; } public DragAdapter(Context context) { mContext = context; int[] rids = new int[]{R.mipmap.a1, R.mipmap.a2, R.mipmap.a3, R.mipmap.a4, R.mipmap.a5, R.mipmap.a6 , R.mipmap.a7, R.mipmap.a8, R.mipmap.a9, R.mipmap.a10, R.mipmap.a11, R.mipmap.a12}; for (int i = 0; i < 12; i++) { mBeans.add(new Bean("item+" + i, rids[i % rids.length])); } } @Override public ViewH onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false); ViewH tag = new ViewH(view); view.setTag(tag); return tag; } @Override public void onBindViewHolder(ViewH holder, int position) { Bean bean = mBeans.get(position); if (bean.isLongClicked()) { holder.icon.setVisibility(View.VISIBLE); } else { holder.icon.setVisibility(View.GONE); } if (bean.isDragged()) { holder.itemView.setVisibility(View.INVISIBLE); } else { holder.itemView.setVisibility(View.VISIBLE); } holder.img.setImageResource(bean.getRid()); holder.tv.setText(bean.getStr()); //***需要每个显示的itemView 与其所显示的数据Bean进行绑定 holder.itemView.setTag(R.id.id_bean_, mBeans.get(position)); holder.itemView.setOnLongClickListener(this);//长按 holder.itemView.setOnClickListener(this);//短按 } @Override public int getItemCount() { return mBeans.size(); } @Override public boolean onLongClick(View v) { //**长按时 获取该itemView 所绑定的Bean draggedBean = (Bean) v.getTag(R.id.id_bean_); draggedBean.setIsDragged(true); //**通知 该Bean所在mBeans位置发生变化 notifyItemChanged(mBeans.indexOf(draggedBean)); //**回调 DragParent 对DragGridView事件进行拦截 if (mListener != null) { mListener.preDrag(v); } return true; } /** * 对外提供 拖拽结束时方法,对应呗拖拽数据重置拖拽状态 并刷新 */ public void dragEnd() { int index = mBeans.indexOf(draggedBean); draggedBean.setIsDragged(false); notifyItemChanged(index); draggedBean = null; } /** * 对外方法 获取当前拖拽Bean位于 mBeans的位置 */ public int dragBeanIndex() { if (draggedBean != null) { return mBeans.indexOf(draggedBean); } return -1; } @Override public void onClick(View v) { String str = ((Bean) v.getTag(R.id.id_bean_)).getStr(); Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show(); } public static class ViewH extends RecyclerView.ViewHolder { private View icon; private ImageView img; private TextView tv; public ViewH(View itemView) { super(itemView); icon = itemView.findViewById(R.id.item_icon); img = ((ImageView) itemView.findViewById(R.id.item_img)); tv = ((TextView) itemView.findViewById(R.id.item_tv)); } }}
11.分别给出 DragParent 和 DragGridView 代码。
public class DragParent extends RelativeLayout implements PreDragListener { private ImageView mImg;//在DragParent 跟随拖拽的img DraggingListener mListener; private Bitmap mDrawingCache;//mImg 使用的从item获取到的图像 public void setListener(DraggingListener listener) { mListener = listener; } public DragParent(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { float x = ev.getX(); float y = ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: if (isDragged) { //当处于拖拽状态下 Move时 int width = mImg.getWidth(); int height = mImg.getHeight(); //设置 mImg位置 mImg.setX(x - width / 2); mImg.setY(y - height / 2); //把位置信息回调给 DragGridView 完成计算 if (mListener != null) { mListener.dragging(x, y); } return true; } break; case MotionEvent.ACTION_UP: if (isDragged) { //把拖拽结束 告知 DragGridView if (mListener != null) { mListener.dragEnd(); } //移除 拖拽的img removeView(mImg); //释放Bitmap mDrawingCache.recycle(); //重置拖拽状态 isDragged = false; return true; } break; } return super.dispatchTouchEvent(ev); } /** * 是否处于拖拽状态 */ boolean isDragged; @Override public void preDrag(View view) { isDragged = true; float x = view.getX(); float y = view.getY(); view.buildDrawingCache(); mDrawingCache = view.getDrawingCache(); mImg = new ImageView(getContext()); mImg.setImageBitmap(mDrawingCache); mImg.setBackgroundColor(Color.BLUE); mImg.setPadding(1, 1, 1, 1); mImg.setX(x); mImg.setY(y); addView(mImg); }}
public class DragGridView extends RecyclerView implements DraggingListener { public DragGridView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthSpec, int heightSpec) { int msHeight = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthSpec, msHeight); } /** * 计算当前拖拽点 位于 DragGridView 那个item上 */ public int nearToPosition(float x, float y) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View view = getChildAt(i); if (x >= view.getX() && x <= view.getX() + view.getWidth() && y >= view.getY() && y <= view.getY() + view.getHeight()) { return ((DragAdapter) getAdapter()).mBeans.indexOf(view.getTag(R.id.id_bean_)); } } return -1; } //***接口回调 DragParent 处于拖拽中,把其拖拽点 传给DragGridView @Override public void dragging(float x, float y) { //获取拖拽点所在的item位置 int position = nearToPosition(x, y); DragAdapter adapter = (DragAdapter) getAdapter(); //或者当前被拖拽数据Bean所在mBeans的位置 int dragBeanIndex = adapter.dragBeanIndex(); //如果 二个位置不一致,则说明原来的数据Bean需要被remove后从新insert到指定位置 if (position != dragBeanIndex && position != -1) { adapter.mBeans.remove(dragBeanIndex); adapter.notifyItemRemoved(dragBeanIndex); adapter.mBeans.add(position, adapter.draggedBean); adapter.notifyItemInserted(position); } } /** * 拖拽结束 调用 DragAdapter 的dragEnd(). */ @Override public void dragEnd() { DragAdapter adapter = (DragAdapter) getAdapter(); adapter.dragEnd(); }}
12.Activity 设置一下。
public class MainActivity extends AppCompatActivity { private DragParent parent; private DragGridView drag; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); parent = (DragParent) findViewById(R.id.parent); drag = (DragGridView) findViewById(R.id.drag); drag.setLayoutManager(new GridLayoutManager(this, 3)); DragAdapter dragAdapter = new DragAdapter(this); dragAdapter.setListener(parent); parent.setListener(drag); drag.setAdapter(dragAdapter); }}
13.如果DragGridView数据过多 ,这里并没有实现拖拽到最上部或最下边是自动上拉、下拉DragGridView的功能。
14. 所以只实现了拖拽,从新排序的功能~~供参考,完~~
- Android 初步实现item可拖拽RecyclerView (Grid模式下)
- Android RecyclerView item高度WRAP_CONTENT实现
- Android-RecyclerView实现Item添加和删除
- 巧用设计模式实现Recyclerview各种复杂Item类型
- Android学习笔记之RecyclerView(二)-异布局Item实现
- Android使用ItemTouchHelper实现RecyclerView的item拖动位置交换
- android中用RecyclerView实现滑动删除与切换item
- Android RecyclerView (四)初学,实现长按删除一个Item.
- Android中RecyclerView的item实现动画的效果
- Android实现RecyclerView自动点击Item中的控件
- Android RecyclerView+StaggerLayoutManager实现瀑布流单选item乱跳
- RecyclerView实现多种item布局
- Android RecyclerView设置item间距
- Android recyclerview加载不同item
- Android RecyclerView Item点击事件
- Android中RecyclerView的item运用覆盖view的方法实现item的动画效果
- Android如何实现RecyclerView的item的展开及显示并让item位于头部
- RecyclerView实现带header的grid
- 2016年安全好用微信开通检测软件
- NodeJs洗牌算法
- spi的时序图
- MySQL 5.6 for Windows 解压缩版配置安装
- IOS 基于ffmpeg VR播放器
- Android 初步实现item可拖拽RecyclerView (Grid模式下)
- HTML、XML 等 Dom 结点类解析库的使用
- 【Android UI设计与开发】8.顶部标题栏(一)ActionBar 奥义·详解
- Latex 表格过大(或过小)的调整方法
- SVN使用教程总结
- Revit开发之外部事件IExternalEventHandler
- [HackerRank]Week Of Code 23
- Dining
- 全面总结Java泛型