仿網易新聞欄目管理(頻道管理)功能
阿新 • • 發佈:2019-01-30
仿網易新聞客戶端欄目的拖拽,刪除,新增效果。在此要感謝vipra,此效果是在這個專案的基礎上修改的
先上效果圖:
簡單說一下實現原理:
首先看一下效果圖,分為上下兩個GridView,上邊的為可以拖拽的GridView,為DragGrid。下邊是不可拖拽的普通的GridView。
主要說一下DragGrid(可以拖拽的GridView):重寫onInterceptTouchEvent方法,然後設定Item的長按事件,拿到當前的item資訊(postion,item的view),並在window層建立item的view的佈局,在onTouchEvent方法,處理move事件獲取到移動,計算item之間的移動和建立動畫。
處理長按事件:
處理移動:setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { int x = (int) ev.getX();// 長按事件的X位置 int y = (int) ev.getY();// 長按事件的y位置 startPosition = position;// 第一次點選的postion dragPosition = position; if (startPosition <= 0) {//TODO 原來是1 return false; } View dragViewGroup = getChildAt(dragPosition - getFirstVisiblePosition()); TextView dragTextView = (TextView) dragViewGroup.findViewById(R.id.text_item); RelativeLayout ri_delete = (RelativeLayout) dragViewGroup.findViewById(R.id.ri_delete); dragTextView.setSelected(true); dragTextView.setEnabled(false); ri_delete.setVisibility(View.INVISIBLE); itemHeight = dragViewGroup.getHeight(); itemWidth = dragViewGroup.getWidth(); itemTotalCount = DragGrid.this.getCount(); int row = itemTotalCount / nColumns;// 算出行數 Remainder = (itemTotalCount % nColumns);// 算出最後一行多餘的數量 if (Remainder != 0) { nRows = row + 1; } else { nRows = row; } // 如果特殊的這個不等於拖動的那個,並且不等於-1 if (dragPosition != AdapterView.INVALID_POSITION) { // 釋放的資源使用的繪圖快取。如果你呼叫buildDrawingCache()手動沒有呼叫setDrawingCacheEnabled(真正的),你應該清理快取使用這種方法。 win_view_x = windowX - dragViewGroup.getLeft();//VIEW相對自己的X,半斤 win_view_y = windowY - dragViewGroup.getTop();//VIEW相對自己的y,半斤 dragOffsetX = (int) (ev.getRawX() - x);//手指在螢幕的上X位置-手指在控制元件中的位置就是距離最左邊的距離 dragOffsetY = (int) (ev.getRawY() - y);//手指在螢幕的上y位置-手指在控制元件中的位置就是距離最上邊的距離 // dragItemView = dragViewGroup; dragViewGroup.destroyDrawingCache(); if (ri_delete.getVisibility() == View.GONE) { ri_delete.setVisibility(View.VISIBLE); } dragViewGroup.setDrawingCacheEnabled(true); //TODO 展示刪除按鈕 showInnerDeleteIcon(); showDeleteIcon(true); Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup.getDrawingCache()); //mVibrator.vibrate(50);//設定震動時間 startDrag(dragBitmap, (int) ev.getRawX(), (int) ev.getRawY()); //隱藏需要移動的item hideDropItem(); dragViewGroup.setVisibility(View.INVISIBLE); isMoving = false; requestDisallowInterceptTouchEvent(true); return true; } return false; } });
// 拖動的VIEW下方的POSTION int dPosition = pointToPosition(x, y); // 判斷下方的POSTION是否是最開始2個不能拖動的 if (dPosition > 0) {//TODO 原來值是1 if ((dPosition == -1) || (dPosition == dragPosition)) { return; } dropPosition = dPosition; if (dragPosition != startPosition) { dragPosition = startPosition; } int movecount; //拖動的=開始拖的,並且 拖動的 不等於放下的 if ((dragPosition == startPosition) || (dragPosition != dropPosition)) { //移需要移動的動ITEM數量 movecount = dropPosition - dragPosition; } else { //移需要移動的動ITEM數量為0 movecount = 0; } if (movecount == 0) { return; } int movecount_abs = Math.abs(movecount); if (dPosition != dragPosition) { //dragGroup設定為不可見 ViewGroup dragGroup = (ViewGroup) getChildAt(dragPosition); dragGroup.setVisibility(View.INVISIBLE); float to_x = 1;// 當前下方positon float to_y;// 當前下方右邊positon //x_vlaue移動的距離百分比(相對於自己長度的百分比) float x_vlaue = ((float) mHorizontalSpacing / (float) itemWidth) + 1.0f; //y_vlaue移動的距離百分比(相對於自己寬度的百分比) float y_vlaue = ((float) mVerticalSpacing / (float) itemHeight) + 1.0f; Log.d("x_vlaue", "x_vlaue = " + x_vlaue); for (int i = 0; i < movecount_abs; i++) { to_x = x_vlaue; to_y = y_vlaue; //像左 if (movecount > 0) { // 判斷是不是同一行的 holdPosition = dragPosition + i + 1; if (dragPosition / nColumns == holdPosition / nColumns) { to_x = -x_vlaue; to_y = 0; } else if (holdPosition % 4 == 0) { to_x = 3 * x_vlaue; to_y = -y_vlaue; System.out.println("=============to_y ="+to_y); } else { to_x = -x_vlaue; to_y = 0; } } else { //向右,下移到上,右移到左 holdPosition = dragPosition - i - 1; if (dragPosition / nColumns == holdPosition / nColumns) { to_x = x_vlaue; to_y = 0; } else if ((holdPosition + 1) % 4 == 0) { to_x = -3 * x_vlaue; to_y = y_vlaue; } else { to_x = x_vlaue; to_y = 0; } } ViewGroup moveViewGroup = (ViewGroup) getChildAt(holdPosition); Animation moveAnimation = getMoveAnimation(to_x, to_y); moveViewGroup.startAnimation(moveAnimation); //如果是最後一個移動的,那麼設定他的最後個動畫ID為LastAnimationID if (holdPosition == dropPosition) { LastAnimationID = moveAnimation.toString(); } moveAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { isMoving = true; } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { // 如果為最後個動畫結束,那執行下面的方法 if (animation.toString().equalsIgnoreCase(LastAnimationID)) { DragAdapter mDragAdapter = (DragAdapter) getAdapter(); mDragAdapter.exchange(startPosition, dropPosition); startPosition = dropPosition; dragPosition = dropPosition; isMoving = false; } } }); } } }
如此,當點選下邊的GridView,獲取到當前item的位置,然後獲取到上傳size+1的位置,建立window層view,設定動畫。
具體程式碼可以去我的github自己去看。