可拖拽 GridView

package com.example.myapp;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.*;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.GridView;
import android.widget.ImageView;

import java.util.LinkedList;
import java.util.List;


/**
 * Created by yp-tc-m-2781 on 16/5/3.
 */
public class MyGridView extends GridView {

    private final String tag = "#myapp.MyGridView";

    private View mStartDragItemView = null;
    private ImageView mDragImageView;
    private Bitmap mDragBitmap;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mWindowLayoutParams;
    private Handler mHandler;
    private long dragResponseMS = 800;
    private boolean isDrag;
    private boolean normalMove;
    private int mDownX;
    private int mDownY;
    private int itemHeight;
    private int mDragPosition;
    private Vibrator mVibrator;
    private int mPoint2ItemLeft;
    private int mPoint2ItemTop;
    private boolean mAnimationEnd = true;
    private int paddingTop;
    private int paddingBottom;
    int mNumColumns;

    public MyGridView(Context context) {
        this(context,null);
    }

    public MyGridView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
        mWindowManager = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
        mHandler = new Handler();
        paddingTop = getPaddingTop();
        paddingBottom = getPaddingBottom();
    }

    @Override
    public void setNumColumns(int numColumns) {
        super.setNumColumns(numColumns);
        this.mNumColumns = numColumns;
    }

    private Runnable mLongClickRunnable = new Runnable() {

        @Override
        public void run() {
            isDrag = true;
            mVibrator.vibrate(50);
            mStartDragItemView.setVisibility(View.INVISIBLE);
            itemHeight = mStartDragItemView.getHeight();
            createDragImage(mDragBitmap, mDownX, mDownY);
        }
    };

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                normalMove = false;
                mDownX = (int)ev.getX();
                mDownY = (int)ev.getY();
                mDragPosition = pointToPosition(mDownX,mDownY);
                if(mDragPosition == INVALID_POSITION)
                {
                    return super.dispatchTouchEvent(ev);
                }
                mHandler.postDelayed(mLongClickRunnable,dragResponseMS);
                mStartDragItemView = getChildAt(mDragPosition - getFirstVisiblePosition());
                mStartDragItemView.setDrawingCacheEnabled(true);
                mDragBitmap = Bitmap.createBitmap(mStartDragItemView.getDrawingCache());
                mStartDragItemView.destroyDrawingCache();
                mPoint2ItemTop = mDownY - mStartDragItemView.getTop();
                mPoint2ItemLeft = mDownX - mStartDragItemView.getLeft();
                break;
            case MotionEvent.ACTION_MOVE:
                int moveX = (int)ev.getX();
                int moveY = (int) ev.getY();
                if(!isTouchInItem( moveX, moveY)){
                    normalMove = true;
                    mHandler.removeCallbacks(mLongClickRunnable);
                }
                break;
            case MotionEvent.ACTION_UP:
                mHandler.removeCallbacks(mLongClickRunnable);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        Log.i(tag,"onTouchEvent");
        if(isDrag && mDragImageView != null){
            switch(ev.getAction()){
                case MotionEvent.ACTION_MOVE:
                    onDragItem((int)ev.getX(),(int)ev.getY());
                    break;
                case MotionEvent.ACTION_UP:
                    onStopDrag();
                    break;
            }
            return true;
        }
        return super.onTouchEvent(ev);
    }

    private void onStopDrag(){
        View view = getChildAt(mDragPosition - getFirstVisiblePosition());
        if(view != null){
            view.setVisibility(View.VISIBLE);
        }
        removeDragImage();
        isDrag = false;
        if(onChangeListener != null)
        {
            onChangeListener.onStop();
        }
    }

    private void createDragImage(Bitmap bitmap, int downX , int downY)
    {
        mWindowLayoutParams = new WindowManager.LayoutParams();
        mWindowLayoutParams.format = PixelFormat.TRANSLUCENT;
        mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
        mWindowLayoutParams.x = downX - mPoint2ItemLeft + getLeft();
        mWindowLayoutParams.y = downY - mPoint2ItemTop + getTop();
        mWindowLayoutParams.alpha = 0.55f;
        mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE ;
        mDragImageView = new ImageView(getContext());
        mDragImageView.setImageBitmap(bitmap);
        mWindowManager.addView(mDragImageView, mWindowLayoutParams);
    }

    private boolean isTouchInItem(int x, int y){
        if(isDrag || normalMove)
        {
            return true;
        }
        int disX = Math.abs(x - mDownX);
        int disY = Math.abs(y - mDownY);
        if(disX > 1 || disY > 1)
        {
            return false;
        }
        return true;
    }

    private void removeDragImage(){
        if(mDragImageView != null){
            mWindowManager.removeView(mDragImageView);
            mDragImageView = null;
        }
    }

    private void onDragItem(int moveX, int moveY){
        mWindowLayoutParams.x = (moveX - mPoint2ItemLeft + getLeft());
        mWindowLayoutParams.y = (moveY - mPoint2ItemTop + getTop());
        int trans = itemHeight/4;
        if((getBottom()-mWindowLayoutParams.y - paddingBottom) <= (itemHeight+trans))
        {
            smoothScrollBy(itemHeight,1500);
        }
        else if((mWindowLayoutParams.y - trans) <= (getTop() + paddingTop))
        {
            smoothScrollBy(-itemHeight,1500);
        }
        else
        {
            smoothScrollBy(0,0);
        }
        mWindowManager.updateViewLayout(mDragImageView, mWindowLayoutParams);
        final int newPosition = pointToPosition(moveX,moveY);
        if(newPosition != mDragPosition && newPosition != INVALID_POSITION && mAnimationEnd)
        {
            if(onChangeListener != null) {
                onChangeListener.onChange(mDragPosition, newPosition);
            }
            final ViewTreeObserver observer = getViewTreeObserver();
            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    observer.removeOnPreDrawListener(this);
                    animateReorder(mDragPosition, newPosition);
                    mDragPosition = newPosition;
                    return true;
                }
            } );
        }
    }

    private void animateReorder(final int oldPosition, final int newPosition) {
        boolean isForward = newPosition > oldPosition;
        List<Animator> resultList = new LinkedList<Animator>();
        if (isForward) {
            for (int pos = oldPosition; pos < newPosition; pos++) {
                View view = getChildAt(pos - getFirstVisiblePosition());
                if ((pos + 1) % mNumColumns == 0) {
                    resultList.add(createTranslationAnimations(view,
                            - (view.getWidth() ) * (mNumColumns - 1), 0,
                            view.getHeight() , 0));
                } else {
                    resultList.add(createTranslationAnimations(view,
                            view.getWidth() , 0, 0, 0));
                }
            }
        } else {
            for (int pos = oldPosition; pos > newPosition; pos--) {
                View view = getChildAt(pos - getFirstVisiblePosition());
                if ((pos) % mNumColumns == 0) {
                    resultList.add(createTranslationAnimations(view,
                            (view.getWidth() ) * (mNumColumns - 1), 0,
                            -view.getHeight() , 0));
                } else {
                    resultList.add(createTranslationAnimations(view,
                            -view.getWidth() , 0, 0, 0));
                }
            }
        }

        AnimatorSet resultSet = new AnimatorSet();
        resultSet.playTogether(resultList);
        resultSet.setDuration(300);
        resultSet.setInterpolator(new AccelerateDecelerateInterpolator());
        resultSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                mAnimationEnd = false;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimationEnd = true;
            }
        });
        resultSet.start();
    }

    private AnimatorSet createTranslationAnimations(View view, float startX,
                                                    float endX, float startY, float endY) {
        ObjectAnimator animX = ObjectAnimator.ofFloat(view, "translationX",
                startX, endX);
        ObjectAnimator animY = ObjectAnimator.ofFloat(view, "translationY",
                startY, endY);
        AnimatorSet animSetXY = new AnimatorSet();
        animSetXY.playTogether(animX, animY);
        return animSetXY;
    }

    private OnChangeListener onChangeListener;

    public void setOnChangeListener(OnChangeListener onChangeListener) {
        this.onChangeListener = onChangeListener;
    }

    interface OnChangeListener
    {
        void onChange(int drayPosition,int swapPosition);
        void onStop();
    }

//    @Override
//    public void onChange(int drayPosition, int swapPosition) {
//        mHidePosition = swapPosition;
//        Integer integer = list.get(drayPosition);
//        list.remove(drayPosition);
//        list.add(swapPosition,integer);
//        notifyDataSetChanged();
//    }
//
//    @Override
//    public void onStop() {
//        mHidePosition = -1;
//    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值