GridView如何实现拖拽排序及数据交互
发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,这篇文章主要介绍了GridView如何实现拖拽排序及数据交互,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在研究项目中的一个效果的时候
千家信息网最后更新 2025年01月25日GridView如何实现拖拽排序及数据交互
这篇文章主要介绍了GridView如何实现拖拽排序及数据交互,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
在研究项目中的一个效果的时候,查找资料过程中发现有人有这么一种需求,就是GridView在实现拖拽排序的基础上,如果是两个GridView之间实现拖拽效果,并要实现数据交互。
一、效果图:
实现这个效果需要考虑的事情:
① 这个UI整体的构建以及事件的传递
② 如何实现View的共享,穿过边界
二、实现思路:
对于单个GridView的拖拽效果实现是参考网上的一篇文章,很抱歉没能及时保存地址,所以这里就不贴了。
整体实现: 一个容器(DragChessView)里放置两个DragView(可拖拽排序Item的View),事件全部交给DragChessView去处理,然后由他去控制事件的分配和处理。在这个容器中还在这两个DragView上面覆盖一层FrameLayout,来放置要移动的那个View,然后根据手势去移动View。DragView里面进行View的动态交换以及数据交换。
三、实现代码:
1. DragChessView代码
public class DragChessView extends FrameLayout { private GestureDetector detector; /** * 点击拖动 */ public static final int DRAG_WHEN_TOUCH = 0; /** * 长按拖动 */ public static final int DRAG_BY_LONG_CLICK = 1; private int mDragMode = DRAG_WHEN_TOUCH; private boolean hasSendDragMsg = false; private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 0x123: // 启动拖拽模式 isDragable = true; // 根据点击的位置生成该位置上的view镜像 if (isTouchInTop(msg.arg2)) { mDragTop.setCurrentDragPosition(msg.arg1); copyView(mDragTop); } else { mDragBottom.setCurrentDragPosition(msg.arg1); copyView(mDragBottom); } hasSendDragMsg = false; break; default: break; } return false; } }); private boolean isDragable = true; private float[] lastLocation = null; private View mCopyView; private OnTouchListener l; // 转交给GridView一些常用监听器 private AdapterView.OnItemLongClickListener itemLongClickListener; private int mTouchArea = 0; private View dragSlider; private Point mMovePoint; // 记录移动走向,上到下,还是下到上 /** * @param itemClickListener * @描述:item 转交给gridview一些常用监听器 */ public void setOnItemClickListener(AdapterView.OnItemClickListener itemClickListener) { mDragBottom.setOnItemClickListener(itemClickListener); } /** * 长按监听器自己触发,点击拖动模式不存在长按 * * @param */ public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener itemLongClickListener) { this.itemLongClickListener = itemLongClickListener; } private boolean canAddViewWhenDragChange = true; private int mStartPoint; private int START_DRAG_TOP = 0; private int START_DRAG_BOTTOM = 1; /** * 手势监听器,滚动和单击 */ private GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (hasSendDragMsg) { hasSendDragMsg = false; handler.removeMessages(0x123); } if (isDragable && mCopyView != null) { if (lastLocation == null && e1 != null) { lastLocation = new float[]{e1.getRawX(), e1.getRawY()}; } if (lastLocation == null) lastLocation = new float[]{0, 0}; distanceX = lastLocation[0] - e2.getRawX(); distanceY = lastLocation[1] - e2.getRawY(); lastLocation[0] = e2.getRawX(); lastLocation[1] = e2.getRawY(); mCopyView.setX(mCopyView.getX() - distanceX); mCopyView.setY(mCopyView.getY() - distanceY); int to = eventToPosition(e2); mCopyView.invalidate(); if (isDragInTop()) { if (isDragFromBottom()) { if (isDragBack(isDragInTop())) { //针对已经进入bottom区域,但是又返回来的情况 mStartPoint = START_DRAG_BOTTOM; //切换,保证移动过程中只执行一次 canAddViewWhenDragChange = true; } if (canAddViewWhenDragChange) {// 保证移动过程中,数据只有一次的添加 mDragTop.addSwapView(mDragBottom.getSwapData()); mDragBottom.removeSwapView(); canAddViewWhenDragChange = false; if (hideView != null) hideView.setVisibility(VISIBLE); } if (mDragTop.isViewInitDone()) { mDragTop.setCurrentDragPosition(mDragTop.getGridChildCount() - 1); hideView = mDragTop.getGridChildAt(mDragTop.getCurrentDragPosition()); if (hideView != null) hideView.setVisibility(INVISIBLE); mMovePoint = getDragViewCenterPoint(mDragTop); } } if (mDragTop.isViewInitDone()) dragChangePosition(mDragTop, to); } else { if (isDragFromTop()) { if (isDragBack(isDragInTop())) { mStartPoint = START_DRAG_TOP; canAddViewWhenDragChange = true; } if (canAddViewWhenDragChange) { mDragBottom.addSwapView(mDragTop.getSwapData()); mDragTop.removeSwapView(); canAddViewWhenDragChange = false; if (hideView != null) hideView.setVisibility(VISIBLE); } if (mDragBottom.isViewInitDone()) { mDragBottom.setCurrentDragPosition(mDragBottom.getGridChildCount() - 1); hideView = mDragBottom.getGridChildAt(mDragBottom.getCurrentDragPosition()); if (hideView != null) hideView.setVisibility(INVISIBLE); Log.e("mMovePoint", mMovePoint.x + "-----------" + mMovePoint.y); mMovePoint = getDragViewCenterPoint(mDragBottom); } } if (mDragBottom.isViewInitDone()) dragChangePosition(mDragBottom, to); } } return true; } @Override public void onShowPress(MotionEvent e) { /** 响应长按拖拽 */ if (mDragMode == DRAG_BY_LONG_CLICK) { // 启动拖拽模式 // isDragable = true; // 通知父控件不拦截我的事件 getParent().requestDisallowInterceptTouchEvent(true); // 根据点击的位置生成该位置上的view镜像 int position = eventToPosition(e); if (isCanDragMove(isTouchInTop(e) ? mDragTop : mDragBottom, position)) { // copyView(currentDragPosition = position); Message msg = handler.obtainMessage(0x123, position, (int) e.getY()); // showpress本身大概需要170毫秒 handler.sendMessageDelayed(msg, dragLongPressTime - 170); mMovePoint = new Point((int) e.getX(), (int) e.getY()); mStartPoint = isTouchInTop(e) ? START_DRAG_TOP : START_DRAG_BOTTOM; hasSendDragMsg = true; } } } }; private boolean isDragBack(boolean dragInTop) { return (dragInTop && mStartPoint == START_DRAG_TOP) || (!dragInTop && mStartPoint == START_DRAG_BOTTOM); } private boolean isDragFromTop() { if (mMovePoint != null && mDragTop != null) { if ((mMovePoint.x > mDragTop.getX() && mMovePoint.x < (mDragTop.getX() + mDragTop.getWidth())) && (mMovePoint.y > mDragTop.getY() && mMovePoint.y < (mDragTop.getY() + mDragTop.getHeight()))) { return true; } } return false; } private Point getDragViewCenterPoint(DragView dragView) { Point result = new Point(); if (dragView != null) { int height = dragView.getHeight(); int width = dragView.getWidth(); float x = dragView.getX(); float y = dragView.getY(); result.set((int) (x + width / 2), (int) (y + height / 2)); } return result; } private boolean isDragFromBottom() { if (mMovePoint != null && mDragBottom != null) { if ((mMovePoint.x > mDragBottom.getX() && mMovePoint.x < (mDragBottom.getX() + mDragBottom.getWidth())) && (mMovePoint.y > mDragBottom.getY() && mMovePoint.y < (mDragBottom.getY() + mDragBottom.getHeight()))) { return true; } } return false; } private boolean isTouchInTop(MotionEvent event) { float y = event.getY(); return isTouchInTop(y); } private boolean isTouchInTop(float y) { return y > mDragTop.getY() && y < (mDragTop.getY() + mDragTop.getHeight()); }private void dragChangePosition(DragView dragView, int to) { if (to != dragView.getCurrentDragPosition() && isCanDragMove(dragView, to)) { dragView.onDragPositionChange(dragView.getCurrentDragPosition(), to); } } private boolean isCanDragMove(DragView dragView, int position) { return position >= dragView.getHeadDragPosition() && position < dragView.getGridChildCount() - dragView.getFootDragPosition(); } private FrameLayout mDragFrame; private DragView mDragBottom; private DragView mDragTop; private View hideView; private long dragLongPressTime = 600; public DragChessView(@NonNull Context context) { this(context, null); } public DragChessView(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, -1); } public DragChessView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } private void init(AttributeSet attrs) { Context context = getContext(); detector = new GestureDetector(context, simpleOnGestureListener); detector.setIsLongpressEnabled(false); mDragFrame = new FrameLayout(context); dragSlider = LayoutInflater.from(context).inflate(R.layout.layout_drag_chess, this, false); mDragTop = dragSlider.findViewById(R.id.drag_top); mDragBottom = dragSlider.findViewById(R.id.drag_bottom); addView(dragSlider, -1, -1); addView(mDragFrame, -1, -1); } @Override public boolean onTouchEvent(MotionEvent ev) { if (l != null) { l.onTouch(this, ev); } if (!isViewInitDone()) { return false; } if (isDragable) { handleScrollAndCreMirror(ev); } else { // 交给子控件自己处理 dispatchEvent(isTouchInTop(ev) ? mDragTop : mDragBottom, ev); } // 处理拖动 detector.onTouchEvent(ev); if (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP) { lastLocation = null; if (hasSendDragMsg) { hasSendDragMsg = false; handler.removeMessages(0x123); } } return true; } private void dispatchEvent(DragView dragView, MotionEvent ev) { dragView.dispatchEvent(ev); } private boolean isDragInTop() { if (mCopyView == null) return false; return (mCopyView.getY() + mCopyView.getHeight()) < (mDragTop.getY() + mDragTop.getBottom()); } /** * Description :拦截所有事件 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; } /** * 处理自动滚屏,和单击生成镜像 */ private void handleScrollAndCreMirror(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: // 通知父控件不拦截我的事件 getParent().requestDisallowInterceptTouchEvent(true); // 根据点击的位置生成该位置上的view镜像 int position = eventToPosition(ev); makeCopyView(isTouchInTop(ev) ? mDragTop : mDragBottom, position); break; case MotionEvent.ACTION_MOVE: getParent().requestDisallowInterceptTouchEvent(true);// 通知父控件不拦截我的事件 // 内容太多时,移动到边缘会自动滚动 decodeScrollArea(isDragInTop() ? mDragTop : mDragBottom, ev); break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (hideView != null) { hideView.setVisibility(View.VISIBLE); if (onDragSelectListener != null) { onDragSelectListener.onPutDown(hideView); } } mDragFrame.removeAllViews(); // mDragFrame.scrollTo(0, 0); // isNotifyByDragSort = true; updateUI(isDragInTop() ? mDragTop : mDragBottom, ev); mCopyView = null; canAddViewWhenDragChange = true; // 放手时取消拖动排序模式 if (mDragMode == DRAG_BY_LONG_CLICK) { isDragable = false; } break; default: break; } } private void updateUI(DragView dragView, MotionEvent ev) { if (dragView.isHasPositionChange()) { dragView.setHasPositionChange(false); dragView.getAdapter().notifyDataSetChanged(); } else if (mDragMode == DRAG_BY_LONG_CLICK && itemLongClickListener != null) { dragView.onItemLongClick(itemLongClickListener); } // 停止滚动 if (dragView.isCanScroll()) { int scrollStates2 = dragView.decodeTouchArea(ev); if (scrollStates2 != 0) { dragView.onTouchAreaChange(0); mTouchArea = 0; } } } private void decodeScrollArea(DragView dragView, MotionEvent ev) { if (dragView.isCanScroll()) { int touchArea = dragView.decodeTouchArea(ev); if (touchArea != mTouchArea) { dragView.onTouchAreaChange(touchArea); mTouchArea = touchArea; } } } private void makeCopyView(DragView dragView, int position) { if (position >= dragView.getHeadDragPosition() && position < dragView.getGridChildCount() - dragView.getFootDragPosition()) { dragView.setCurrentDragPosition(position); copyView(dragView); } } /** * 得到事件触发点, 摸到的是哪一个item */ public int eventToPosition(MotionEvent ev) { if (ev != null) { if (isTouchInTop(ev)) return mDragTop.eventToPosition(ev); return mDragBottom.eventToPosition(ev); } return 0; } /** * 复制一个镜像,并添加到透明层 */ private void copyView(DragView dragView) { // TODO: 2018/4/2 创建可移动的 item hideView = dragView.getGridChildAt(dragView.getCurrentDragPosition()); int realPosition = dragView.getGridChildPos(hideView); DragAdapter adapter = dragView.getAdapter(); if (!adapter.isUseCopyView()) { mCopyView = adapter.getView(realPosition, mCopyView, mDragFrame); } else { mCopyView = adapter.copyView(realPosition, mCopyView, mDragFrame); } hideView.setVisibility(View.INVISIBLE); if (mCopyView.getParent() == null) mDragFrame.addView(mCopyView, dragView.getmColWidth(), dragView.getmColHeight()); int[] l1 = new int[2]; int[] l2 = new int[2]; hideView.getLocationOnScreen(l1); mDragFrame.getLocationOnScreen(l2); // mCopyView.setX(hideView.getLeft()); // mCopyView.setY(hideView.getTop() - mCurrentY); mCopyView.setX(l1[0] - l2[0]); mCopyView.setY(l1[1] - l2[1]); if (onDragSelectListener == null) { mCopyView.setScaleX(1.2f); mCopyView.setScaleY(1.2f); } else { onDragSelectListener.onDragSelect(mCopyView); } } private DragSortGridView.OnDragSelectListener onDragSelectListener; /** * @描述:一个item view刚被拖拽和放下时起来生成镜像时调用. */ public void setOnDragSelectListener(DragSortGridView.OnDragSelectListener onDragSelectListener) { this.onDragSelectListener = onDragSelectListener; } /** * @param mode int类型 * @描述:设置拖动的策略是点击还是长按 */ public void setDragModel(int mode) { this.mDragMode = mode; isDragable = mode == DRAG_WHEN_TOUCH; } public void setAnimFrame(ListenFrameLayout mDragFrame) { this.mDragFrame = mDragFrame; } /** * 设置长按需要用时 * * @param time */ public void setDragLongPressTime(long time) { dragLongPressTime = time; } public void setBottomAdapter(@NotNull DragAdapter adapter) { mDragBottom.setAdapter(adapter); } public boolean isViewInitDone() { boolean result = mDragBottom.isViewInitDone(); if (mDragTop.getVisibility() == VISIBLE) result &= mDragTop.isViewInitDone(); return result; } public void setTopAdapter(@NotNull DragAdapter adapter) { mDragTop.setAdapter(adapter); }}
2. DragView的实现:
public class DragViewextends FrameLayout { private static final int TAG_KEY = R.id.first; private NoScrollGridView mGridView; private List mChilds = new ArrayList (); protected int mNumColumns = 3; protected int mColHeight = 0; protected int mColWidth = 0; protected int mChildCount = 0; protected int mMaxHeight = 0; private boolean isViewInitDone = false; private ListenScrollView mScrollView; private int mCurrentY = 0; /** * 自动滚屏的动画 */ private ValueAnimator animator; private DragAdapter adapter; private int headDragPosition = 0; private int footDragPosition = 0; private int currentDragPosition = -1; /** * 是否有位置发生改变,否则不用重绘 */ private boolean hasPositionChange = false; /** * gridview能否滚动,是否内容太多 */ private boolean canScroll = true; /** * 动画时间 */ private static final long ANIM_DURING = 250; private Object swapeData; public DragView(@NonNull Context context) { this(context, null); } public DragView(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, -1); } public DragView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { Context context = getContext(); mGridView = new NoScrollGridView(context); mGridView.setVerticalScrollBarEnabled(false); mGridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); mGridView.setSelector(new ColorDrawable()); // View的宽高之类必须在测量,布局,绘制一系列过程之后才能获取到 mGridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mChilds.isEmpty()) { for (int i = 0; i < mGridView.getChildCount(); i++) { View view = mGridView.getChildAt(i); view.setTag(TAG_KEY, new int[]{0, 0}); view.clearAnimation(); mChilds.add(view); } } if (!mChilds.isEmpty()) { mColHeight = mChilds.get(0).getHeight(); } mColWidth = mGridView.getColumnWidth(); if (mChildCount % mNumColumns == 0) { mMaxHeight = mColHeight * mChildCount / mNumColumns; } else { mMaxHeight = mColHeight * (mChildCount / mNumColumns + 1); } canScroll = mMaxHeight - getHeight() > 0; // 告知事件处理,完成View加载,许多属性也已经初始化了 isViewInitDone = true; } }); mScrollView = new ListenScrollView(context); mGridView.setNumColumns(mNumColumns); mScrollView.addView(mGridView, -1, -1); addView(mScrollView, -1, -1); } private DataSetObserver observer = new DataSetObserver() { @Override public void onChanged() { mChildCount = adapter.getCount(); // 下列属性状态清除,才会在被调用notifyDataSetChange时,在gridview测量布局完成后重新获取 mChilds.clear(); mColHeight = mColWidth = mMaxHeight = 0; isViewInitDone = false; } @Override public void onInvalidated() { mChildCount = adapter.getCount(); } }; /** * 控制自动滚屏的动画监听器. */ private ValueAnimator.AnimatorUpdateListener animUpdateListener = new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int targetY = Math.round((Float) animation.getAnimatedValue()); if (targetY < 0) { targetY = 0; } else if (targetY > mMaxHeight - getHeight()) { targetY = mMaxHeight - getHeight(); } // mGridView.scrollTo(0, targetY); mScrollView.smoothScrollTo(0, targetY); // mCurrentY = targetY; } }; public void setAdapter(DragAdapter adapter) { if (this.adapter != null && observer != null) { this.adapter.unregisterDataSetObserver(observer); } this.adapter = adapter; mGridView.setAdapter(adapter); adapter.registerDataSetObserver(observer); mChildCount = adapter.getCount(); } /** * @param from * @param to * @描述:动画效果移动View */ public void translateView(int from, int to) { View view = mChilds.get(from); int fromXValue = ((int[]) view.getTag(TAG_KEY))[0]; int fromYValue = ((int[]) view.getTag(TAG_KEY))[1]; int toXValue = to % mNumColumns - from % mNumColumns + fromXValue; int toYValue = to / mNumColumns - from / mNumColumns + fromYValue; Animation animation = new TranslateAnimation(1, fromXValue, 1, toXValue, 1, fromYValue, 1, toYValue); animation.setDuration(ANIM_DURING); animation.setFillAfter(true); view.setTag(TAG_KEY, new int[]{toXValue, toYValue}); view.startAnimation(animation); } /** * @param from * @param to * @描述:拖动View使位置发生改变时 */ public void onDragPositionChange(int from, int to) { if (from > to) { for (int i = to; i < from; i++) { translateView(i, i + 1); } } else { for (int i = to; i > from; i--) { translateView(i, i - 1); } } if (!hasPositionChange) { hasPositionChange = true; } if ((from >= mChilds.size() || from < 0) || (to >= mChilds.size() || to < 0)) return; adapter.onDataModelMove(from, to); View view = mChilds.remove(from); mChilds.add(to, view); currentDragPosition = to; } /** * @param scrollStates * @描述:触摸区域改变,做相应处理,开始滚动或停止滚动 */ public void onTouchAreaChange(int scrollStates) { if (!canScroll) { return; } if (animator != null) { animator.removeUpdateListener(animUpdateListener); } if (scrollStates == 1) {// 从普通区域进入触发向上滚动的区域 int instance = mMaxHeight - getHeight() - mCurrentY; animator = ValueAnimator.ofFloat(mCurrentY, mMaxHeight - getHeight()); animator.setDuration((long) (instance / 0.5f)); animator.setTarget(mGridView); animator.addUpdateListener(animUpdateListener); animator.start(); } else if (scrollStates == -1) {// 进入触发向下滚动的区域 animator = ValueAnimator.ofFloat(mCurrentY, 0); animator.setDuration((long) (mCurrentY / 0.5f)); animator.setTarget(mGridView); animator.addUpdateListener(animUpdateListener); animator.start(); } } /** * @param ev 事件 * @return 0中间区域, 1底部,-1顶部 * @描述: 检查当前触摸事件位于哪个区域, 顶部1/5可能触发下滚,底部1/5可能触发上滚 */ public int decodeTouchArea(MotionEvent ev) { if (ev.getY() > (getHeight() + getY()) * 4 / (double) 5) { return 1; } else if (ev.getY() < (getHeight() + getY()) / (double) 5) { return -1; } else { return 0; } } public boolean isViewInitDone() { return isViewInitDone; } /** * 设置前几个item不可以改变位置 */ public void setNoPositionChangeItemCount(int count) { headDragPosition = count; } /** * 设置后几个item不可以改变位置 */ public void setFootNoPositionChangeItemCount(int count) { footDragPosition = count; } public int getHeadDragPosition() { return headDragPosition; } public int getFootDragPosition() { return footDragPosition; } public int getGridChildCount() { return mChilds.size(); } public View getGridChildAt(int position) { if (position < 0 || position >= mChilds.size()) return null; return mChilds.get(position); } public int getGridChildPos(View view) { return mGridView.indexOfChild(view); } public void setCurrentDragPosition(int currentDragPosition) { this.currentDragPosition = currentDragPosition; } public int getCurrentDragPosition() { return currentDragPosition; } public int getmColHeight() { return mColHeight; } public int getmColWidth() { return mColWidth; } public DragAdapter getAdapter() { return adapter; } public boolean isHasPositionChange() { return hasPositionChange; } public void setHasPositionChange(boolean hasPositionChange) { this.hasPositionChange = hasPositionChange; } public boolean isCanScroll() { return canScroll; } public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) { mGridView.setOnItemClickListener(onItemClickListener); } public void onItemLongClick(AdapterView.OnItemLongClickListener itemLongClickListener) { itemLongClickListener.onItemLongClick(mGridView, childAt(currentDragPosition), currentDragPosition, 0); } public View childAt(int index) { return mGridView.getChildAt(index); } public void dispatchEvent(MotionEvent ev) { if (canScroll) mScrollView.dispatchTouchEvent(ev); else mGridView.dispatchTouchEvent(ev); } public int eventToPosition(MotionEvent ev) { if (ev != null) { int m = (int) ev.getX() / mColWidth; int n = (int) (ev.getY() - getY() + mCurrentY) / mColHeight; int position = n * mNumColumns + m; if (position >= mChildCount) { return mChildCount - 1; } else { return position; } } return 0; } public void addSwapView(Object data) { adapter.addNewData(data); } public Object getSwapData() { return adapter.getSwapData(currentDragPosition); } public void removeSwapView() { if (adapter != null) { adapter.removeData(currentDragPosition); adapter.notifyDataSetChanged(); } } class ListenScrollView extends ScrollView { public ListenScrollView(Context context) { super(context); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); mCurrentY = getScrollY(); } } class NoScrollGridView extends GridView { public NoScrollGridView(Context context) { super(context); } /** * @return * @描述:兼容老版本的getColumWidth * @作者 [pWX273343] 2015年7月1日 */ public int getColumnWidth() { return getWidth() / getNumColumns(); } public NoScrollGridView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, mExpandSpec); } }}
3. DragAdapter的代码:
public abstract class DragAdapter extends BaseAdapter { /** * @param from * @param to * @描述:当从from排序被拖到to排序时的处理方式,请对相应的数据做处理。 */ public abstract void onDataModelMove(int from, int to); /** * 复制View使用的方法,默认直接使用getView方法获取 * * @param position * @param convertView * @param parent * @return */ public View copyView(int position, View convertView, ViewGroup parent) { return null; } /** * 是否启用copyView方法 * * @return true 使用copyView复制 false 使用getView直接获取镜像 */ public boolean isUseCopyView() { return false; } public abstract Object getSwapData(int position); public abstract void removeData(int position); public void addNewData(Object data) { }}
4.使用MainActivity:
class GridDragShortActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.attributes.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION setContentView(R.layout.activity_grid_drag_short) //长按item响应该item的拖动排序,默认是触摸就开始拖动 drag_main.setDragModel(DragSortGridView.DRAG_BY_LONG_CLICK) //设置每行个数// drag_main.numColumns = 3 var arrayList = ArrayList() var list = ArrayList () for (i in 0..29) { arrayList.add("" + i) } for (i in 0..29) { list.add(('A' + i).toString()) } drag_main.setBottomAdapter(CustomAdapter(list, this)) drag_main.setTopAdapter(CustomAdapter(arrayList, this)) }}
布局:activity_main.xml
布局 layout_drag_chess.xml:
在实际使用中,可以更据需要再去拓展使用,代码演变过程中的另一个效果,来看看,以它结束这篇:
感谢你能够认真阅读完这篇文章,希望小编分享的"GridView如何实现拖拽排序及数据交互"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!
位置
排序
效果
处理
移动
数据
事件
监听器
篇文章
过程
镜像
监听
代码
动画
布局
两个
方法
模式
生成
容器
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
软件开发专业限制日语吗
什么数据库提供企业案例
希沃软件开发过程
未来5年网络安全性
不加群 群qq号 数据库
网络安全保障演练
云网络安全中心
布乔网络技术工作
在数据库中建立三个表格
珠海互联网科技有限公司
湖南软件开发服务标准
深圳热播网络技术有限公司
微信服务器api
单词数据库
英语不好可以搞软件开发吗
糖豆服务器
石嘴山网络安全意识形态责任制
米合网络技术有限公司怎么样
万方数据库手机号验证不了
联想r630服务器管理口
域名的服务器位置
全球最大手机软件开发公司
同方知网数据库登录
河南大学网络技术中心
去中心化数据库 英文翻译
软件开发支出资本化条件
天津服务器虚拟化多少钱
数据库液冷
英国软件开发工资
移动技术是通信技术网络技术