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

可拖拽 GridView的相关文章

可拖拽GridView代码解析

本片学习笔记是对eoe网上一个项目代码的解读,具体项目作者的博客如下:http://blog.csdn.net/vipzjyno1/article/details/26514543.项目源码下载地址为https://github.com/Rano1/TopNews本篇只对可拖拽的GridView的代码进行解读,同时修改了原项目中不必要的变量.去掉了不必要或者逻辑错误的代码,也删除了方法中不必要的局部变量和计算.通过对这个读这个代码,自己也着实学到了不少的东西(毕竟自己刚接触android不久,特

android ListView和GridView拖拽移位实现代码

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:             首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点

Android 仿今日头条频道管理(下)(GridView之间Item的移动和拖拽)

前言 上篇博客我们说到了今日头条频道管理的操作交互体验,我也介绍了2个GridView之间Item的相互移动.详情请參考:Android 仿今日头条频道管理(上)(GridView之间Item的移动和拖拽) 今天把相对照较复杂的gridView的拖拽也记录下.在開始之前我们事先要了解下Android的事件分发机制.网上这方面的资料也比較多.由于自己定义控件大部分要用到事件分发机制的知识. 实现思路 要实现Item的拖拽.事实上并非真正要去拖拽GridView的Item.而是使用WindowMan

android ListView和GridView拖拽移位具体实现及拓展

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:              首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在 ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范 围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.

Android中GridView拖拽的效果

最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子.还是很有趣的,实现的流畅度没有人家的那么好,我只是模仿这种效果,我写的这个拖拽是两个图标之间进行交换,所以,当从一行的某个位置,换到下 一行的另一列的时候,发现有好几个图标都改变位置了,因为是相邻两个交换位置,所以每经过相邻的图标的时候都改变位置.先弄个雏形,以后再更新优化. 转载请标明出处:http://blog.csdn.net/wd

两个GridView之间数据转移,交互,实现拖拽,网易新闻列表效果实现

两个GridView之间数据转移,交互,实现拖拽,网易新闻列表效果实现 摘要 :android 高仿频道管理网易新闻. 新闻频道增删,排序,以及一些动画的实现 可拖动的GridView 地址  :  http://www.itnose.net/detail/6035345.html

devpress 的gridview 控件的行拖拽 z

首先,添加引用:using DevExpress.XtraGrid.Views.Grid.ViewInfo; gridControl1.AllowDrop = true; // 确保能够拖拽 gridView1.OptionsSelection.MultiSelect = true;     //确保能够多选 gridView1.OptionsSelection.EnableAppearanceFocusedCell = false; //确保选定行的背景色一样. gridView1.Optio

DraggableView GridView项目拖拽效果

DraggableView GridView项目拖拽效果 DraggableView GridView项目拖拽效果, 自顶一个SampleGridContainer 集成FrameLayout实现DragController.IDragViewGroup ,里面主要提供了onDragStart ,onDragEnd,onMoveEvent等几个方法实现拖拽效果 运行效果: 相关代码 DraggableView GridView项目拖拽效果 PullDownListView高仿微信下拉眼睛出现动画

Android中GridView拖拽的效果【android进化三十六】

  最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子.还是很有趣的,实现的流畅度没有人家的那么好,我只是模仿这种效果,我写的这个拖拽是两个图标之间进行交换,所以,当从一行的某个位置,换到下 一行的另一列的时候,发现有好几个图标都改变位置了,因为是相邻两个交换位置,所以每经过相邻的图标的时候都改变位置.先弄个雏形,以后再更新优化. 转载请标明出处:http://blog.csdn.net/