GridView Cell拖曳

1 篇文章 / 0 new
author
GridView Cell拖曳
網路上看了一些文章, 發現寫得感覺複雜化且動作不盡理想, 就自己來了, 實現拖曳功能幾個主要的重點都以在程式內說明, 但目前仍存在一個問題需要克服, 若要搭配 HorizontalScrollView 作橫移時, 會卡住
► 使用
DragGridView.useDragMode(true);
DragGridView.setOnDragCellEvent(new OnDragCellEvent()    {
    public void onEvent(AdapterView<?> view, Adapter adapter, int srcPosition, int tarPosition)
    {   //拖曳  處理    }           
});
DragGridView
public class DragGridView extends GridView {    
    public DragGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    //啟用拖曳功能
    private boolean dragMode = false;//是否使用拖曳
    private int dragPosition; // 開始拖曳位置
    private int dropPosition; // 結訴拖拽位置
    private ImageView dragImage; // 拖曳時圖示
    private WindowManager windowManager;
    private WindowManager.LayoutParams windowLayout;
    public void useDragMode(boolean mode) {
        dragMode = mode;
        if (!dragMode) return;
        //
        windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
        //拖曳視窗樣式設定
        windowLayout = new WindowManager.LayoutParams();
        windowLayout.gravity = Gravity.TOP | Gravity.LEFT;
        windowLayout.height = WindowManager.LayoutParams.WRAP_CONTENT;
        windowLayout.width = WindowManager.LayoutParams.WRAP_CONTENT;
        windowLayout.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;                
        windowLayout.format = PixelFormat.TRANSLUCENT;
        windowLayout.alpha = 0.8f;// 透明度
        //長按事件處理
        this.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                if (!dragMode) return true;
 
                dragPosition = dropPosition = pointToPosition(mouseX, mouseY);
                if (dragPosition == AdapterView.INVALID_POSITION)
                    return false;
 
                columnCount = getNumColumnsCompat();
                ViewGroup itemView = (ViewGroup) getChildAt(dragPosition - getFirstVisiblePosition());
                // 清除cache,生成圖示
                itemView.destroyDrawingCache();
                itemView.setDrawingCacheEnabled(true);
                startDrag( Bitmap.createBitmap(itemView.getDrawingCache()) );                
                return false;
            };
        });
    }    
    int mouseX = 0, mouseY = 0; // GridView 座標系
    int displayX = 0, displayY = 0; // 螢幕座標系
    @Override
    public boolean onTouchEvent(MotionEvent ev) {// ev 的座標系是以 該元件 GridView 為基準
        //Log.d("dd","onTouchEvent");
        if (!dragMode) return super.onTouchEvent(ev);
 
        mouseX = (int) ev.getX();
        mouseY = (int) ev.getY();
        displayX = (int) ev.getRawX();
        displayY = (int) ev.getRawY();
        if ( (dragImage != null) && (dragPosition != AdapterView.INVALID_POSITION) ) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE: onDrag(mouseX, mouseY); break;
                case MotionEvent.ACTION_UP: onDrop(mouseX, mouseY); break;
            }
        }
        if (dragImage != null)//拖曳過程需 false 否則不在預計的滾動區域內時仍會觸發畫面滾動
            return false;
        else
            return super.onTouchEvent(ev);
    }
    int adjX = 0, adjY = 0; //調整圖像位置
    private void startDrag(Bitmap bm) {
        stopDrag();
        adjX = bm.getWidth() / 2;//視窗中心對準滑鼠
        adjY = bm.getHeight() / 2;
        setDragWindowPos();// 設定顯示座標
        dragImage = new ImageView(getContext());
        dragImage.setImageBitmap(bm);        
        windowManager.addView(dragImage, windowLayout);        
    }
    private void setDragWindowPos() {
        windowLayout.x = displayX - adjX;
        windowLayout.y = displayY - adjY;
        if (dragImage != null)            
            windowManager.updateViewLayout(dragImage, windowLayout);
    }
    private void onDrag(int x, int y) {
        setDragWindowPos();
        int pos = this.pointToPosition(x, y);
        if (pos == AdapterView.INVALID_POSITION) return;
 
        int fs = this.getFirstVisiblePosition();//畫面上第一個cell位置
        int ls = this.getLastVisiblePosition();//畫面上最後一個cell位置
        if ( pos <= (fs + columnCount) ) {//上移
            fs -= columnCount;
            this.smoothScrollToPosition(fs);
        } else if ( pos >= (ls - columnCount) ) {//下移
            ls += columnCount;
            this.smoothScrollToPosition(ls);
        }
    }
    private void onDrop(int x, int y) {//拖曳放開
        stopDrag();
        if (mOnDragCellEvent==null) return;
        //
        dropPosition = pointToPosition(x, y);
        if ( (dropPosition!=AdapterView.INVALID_POSITION)&&(dropPosition != dragPosition) )
            mOnDragCellEvent.onEvent(this, this.getAdapter(), dragPosition, dropPosition);
    }
    private void stopDrag() {
        adjX = adjY = 0;
        if (dragImage != null) {
            windowManager.removeView(dragImage);
            dragImage = null;
        }
    }
    //拖曳事件
    OnDragCellEvent mOnDragCellEvent = null;
    public interface OnDragCellEvent {
        /**
         * @param view GridView.
         * @param adapter GridView Cell list.
         * @param srcPosition 拖曳開始cell位置.
         * @param tarPosition 拖曳結束cell位置.
         */
        void onEvent(AdapterView<?> view, Adapter adapter, int srcPosition, int tarPosition);
    }
    public void setOnDragCellEvent(OnDragCellEvent event) {
        mOnDragCellEvent = event;
    }
    public final OnDragCellEvent getOnDragCellEvent() {
        return mOnDragCellEvent;
    }
    //自行計算欄位數
      //this.getNumColumns(); API11以上才支援
      private int columnCount = 1;
      private int getNumColumnsCompat() {
          int columns = 0;
          int children = getChildCount();//畫面上的cell數
 
          if (children > 0) {
              int width = getChildAt(0).getMeasuredWidth();//每個 cell寬度
              if (width > 0) {
                  columns = getWidth() / width;
              }
          }
          return columns > 0 ? columns : AUTO_FIT;
      }
}
Free Web Hosting