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; // } }
时间: 2024-10-10 04:49:46