仿照支付宝可拖动gridview


参考了github上一个dynamicgrid


源代码地址 https://github.com/aspros523/DragGridView

思路 

1.长按的时候触发拖动

获取所选择的item的图像,稍微放大并随手指移动。

显示图像用一个BitmapDrawable 移动的时候设置它的bounds,并调用invalidate函数重绘。

 public void startDrag(int position)
    {
        if (position == INVALID_POSITION)
        {
            return;
        }

        //恢复之前的图像,改变背景,去除删除按钮
        resumeView();

        selectView = getChildAt(position - getFirstVisiblePosition());
        if (selectView != null)
        {
            isDrag = true;
            isEdit = true;

            /**
             * 移动的图像背景要有区别,并显示删除按钮
             */
            selectView.findViewById(R.id.item_container).setBackgroundColor(Color.parseColor("#f0f0f0"));
            selectView.findViewById(R.id.delete_img).setVisibility(VISIBLE);

            originPosition = position;
            currentPosition = position;

            vibrator.vibrate(60);

            //获取图像
            hoverCell = getHoverCell(selectView);

            selectView.findViewById(R.id.item_container).setVisibility(INVISIBLE);

            if(dragCallback!=null)
            {
                dragCallback.startDrag(position);
            }

        }
    }
 @Override
    public boolean onTouchEvent(MotionEvent ev)
    {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                if (isDrag)
                {
                    int offsetX = x - lastX;
                    int offsetY = y - lastY;

                    lastX = x;
                    lastY = y;

                    currentRect.offset(offsetX, offsetY);
                    hoverCell.setBounds(currentRect);
                    invalidate();
                    if (!isSwap)
                    {
                        swapItems(x, y);
                    }
                    handleScroll();
                    return false;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (isDrag)
                {
                    endDrag();
                }
                break;
            default:
        }

        return super.onTouchEvent(ev);
    }



2.移动时根据bounds的中点用pointToPosition函数获取在gridview中的位置,判断是否要交换内容。

如果和原来的位置不同,就交换内容,并用动画显示交换过程。

private void swapItems(int x, int y)
    {
        int endPosition = pointToPosition(x, y);

        if (endPosition != INVALID_POSITION && endPosition != currentPosition)
        {
            isSwap = true;
            isEdit = false;
            resumeView();

            //交换数据内容
            getInterface().reOrder(currentPosition, endPosition);

            selectView=getChildAt(endPosition-getFirstVisiblePosition());
            selectView.findViewById(R.id.item_container).setVisibility(INVISIBLE);
            selectView.findViewById(R.id.item_container).setBackgroundColor(Color.parseColor("#f0f0f0"));
            selectView.findViewById(R.id.delete_img).setVisibility(VISIBLE);

            //动画显示交换过程
            animateSwap(endPosition);


        }
    }


3.放开后,用一个动画让图像回到原来位置

private void endDrag()
    {
        currentRect.set(selectView.getLeft(), selectView.getTop(), selectView.getRight(), selectView.getBottom());
        animateBound();
    }

    private void animateBound()
    {
        TypeEvaluator<Rect> evaluator = new TypeEvaluator<Rect>()
        {
            @Override
            public Rect evaluate(float fraction, Rect startValue, Rect endValue)
            {
                return new Rect(interpolate(startValue.left, endValue.left, fraction),
                        interpolate(startValue.top, endValue.top, fraction),
                        interpolate(startValue.right, endValue.right, fraction),
                        interpolate(startValue.bottom, endValue.bottom, fraction));
            }

            public int interpolate(int start, int end, float fraction)
            {
                return (int) (start + fraction * (end - start));
            }


        };

        ObjectAnimator animator = ObjectAnimator.ofObject(hoverCell, "bounds", evaluator, currentRect);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                invalidate();
            }
        });
        animator.addListener(new Animator.AnimatorListener()
        {
            @Override
            public void onAnimationStart(Animator animation)
            {

            }

            @Override
            public void onAnimationEnd(Animator animation)
            {
                isDrag = false;

                if (currentPosition != originPosition)
                {
                    resumeView();
                    originPosition = currentPosition;
                }

                hoverCell = null;
                selectView.findViewById(R.id.item_container).setVisibility(VISIBLE);

                if (dragCallback != null)
                {
                    dragCallback.endDrag(currentPosition);
                }

            }

            @Override
            public void onAnimationCancel(Animator animation)
            {

            }

            @Override
            public void onAnimationRepeat(Animator animation)
            {

            }
        });

        animator.start();
    }

4 拖动到顶部或者底部时自动滚动

    private void handleScroll()
    {
        int offset=computeVerticalScrollOffset();
        int height=getHeight();
        int extent=computeVerticalScrollExtent();
        int range=computeHorizontalScrollRange();
        if(currentRect.top<=0 && offset>0)
        {
            smoothScrollBy(-SCROLL_SPEED,0);
        }
        else
        if(currentRect.bottom>=height && (offset+extent)<range)
        {
            smoothScrollBy(SCROLL_SPEED,0);
        }
    }


评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值