简体   繁体   English

使用滑动手势上下移动对象

[英]Move object up/down with swipe gesture

I'm trying to move an object between max_height and min_height value, I've found a piece of code and I tried to adapt it, but the object ( CardView ) move around full height of screen, and when I try to move the object reappears in another location before moving, I do not know how to adapt it to my needs, any ideas? 我正在尝试在max_heightmin_height值之间移动对象,我找到了一段代码,并尝试对其进行调整,但是对象( CardView )在屏幕的整个高度上移动,并且当我尝试移动对象时重新出现在移动之前的另一个位置,我不知道该如何适应我的需求,有什么想法吗?

public interface OnLayoutCloseListener {
    void OnLayoutClosed();
}

enum Direction {
    UP_DOWN,
    LEFT_RIGHT,
    NONE
}
private Direction direction = Direction.NONE;
private int previousFingerPositionY;
private int previousFingerPositionX;
private int baseLayoutPosition;
private boolean isScrollingUp;
private boolean isLocked = false;
private OnLayoutCloseListener listener;

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

    if (isLocked) {
        return false;
    } else {
        final int y = (int) ev.getRawY();
        final int x = (int) ev.getRawX();


        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {

            previousFingerPositionX = x;
            previousFingerPositionY = y;

        } else if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) {


            int diffY = y - previousFingerPositionY;
            int diffX = x - previousFingerPositionX;

            if (Math.abs(diffX) + 50 < Math.abs(diffY)) {
                return true;
            }

        }

        return false;
    }

}

@Override
public boolean onTouchEvent(MotionEvent ev) {

    if (!isLocked) {

        final int y = (int) ev.getRawY();
        final int x = (int) ev.getRawX();

        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {

            previousFingerPositionX = x;
            previousFingerPositionY = y;
            baseLayoutPosition = (int) this.getY();

        } else if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) {


            int diffY = y - previousFingerPositionY;
            int diffX = x - previousFingerPositionX;

            if (direction == Direction.NONE) {
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    direction = Direction.LEFT_RIGHT;
                } else if (Math.abs(diffX) < Math.abs(diffY)) {
                    direction = Direction.UP_DOWN;
                } else {
                    direction = Direction.NONE;
                }
            }

            if (direction == Direction.UP_DOWN) {
                isScrollingUp = diffY <= 0;

                this.setY(baseLayoutPosition + diffY);
                requestLayout();
                return true;
            }

        } else if (ev.getActionMasked() == MotionEvent.ACTION_UP) {

            if (direction == Direction.UP_DOWN) {

                if (isScrollingUp) {

                    //Calculates height according to my needs
                    int max_height = height - (card.getHeight() + toolbar.getHeight());

                    if (Math.abs(this.getY()) > max_height) {

                        if (listener != null) {
                            listener.OnLayoutClosed();
                        }

                    }

                } else {

                    //Calculates height according to my needs
                    int min_height = height - ((int)(toolbar.getHeight() * 1.7));
                    if (Math.abs(this.getY()) > min_height) {
                        if (listener != null) {
                            listener.OnLayoutClosed();
                        }

                    }

                }

                ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(card, "y", this.getY(), 0);
                positionAnimator.setDuration(0);
                positionAnimator.start();

                direction = Direction.NONE;
                return true;
            }

            direction = Direction.NONE;
        }

        return true;

    }

    return false;
}

public void setOnLayoutCloseListener(OnLayoutCloseListener closeListener) {
    this.listener = closeListener;
}

public void lock() {
    isLocked = true;
}

public void unLock() {
    isLocked = false;
}

UPDATE SOLUTION: 更新解决方案:

Reset LayoutParam at any instance of card: 在任何卡实例上重置LayoutParam

card.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

Than use this code for scroll view between min_height and max_height 比使用此代码在min_heightmax_height之间滚动视图

private int previousFingerPositionY;
private int previousFingerPositionX;
int min_height = 500;
int max_height = 100;
int pressedy;
int viewMariginY;

private boolean isLocked = false;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (isLocked) {
        return false;
    } else {
        final int y = (int) ev.getRawY();
        final int x = (int) ev.getRawX();
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
            previousFingerPositionX = x;
            previousFingerPositionY = y;
        } else if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) {
            int diffY = y - previousFingerPositionY;
            int diffX = x - previousFingerPositionX;
            if (Math.abs(diffX) + 25 < Math.abs(diffY)) {
                return true;
            }
        }
        return false;
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    int currenty=(int) event.getRawY();
    FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) card.getLayoutParams();
    switch(event.getAction())
    {

        case MotionEvent.ACTION_DOWN :
            pressedy=currenty;
            viewMariginY=layoutParams.topMargin;
            break;


        case MotionEvent.ACTION_MOVE :
            int diffy=currenty-pressedy;
            int marginy=viewMariginY+diffy;
            layoutParams.topMargin=marginy;
            if(marginy >= max_height && marginy <= min_height)
            {
                ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(card, "y", this.getY(), marginy);
                positionAnimator.setDuration(0);
                positionAnimator.start();
            }
            break;

        case MotionEvent.ACTION_UP :
            int diffy2=currenty-pressedy;
            int marginy2=viewMariginY+diffy2;
            layoutParams.topMargin=marginy2;
            if(marginy2 >= max_height && marginy2 <= min_height)
            {
                ObjectAnimator positionAnimator1 = ObjectAnimator.ofFloat(card, "y", this.getY(), marginy2);
                positionAnimator1.setDuration(0);
                positionAnimator1.start();
            }
            break;
    }

    return true;
}
int pressedx,pressedy;
    int viewMariginX,viewMariginY;  

@Override
public boolean onTouch(View v, MotionEvent event) {

    int currentx=(int) event.getRawX();
    int currenty=(int) event.getRawY();


//get Layout Param of your cardView 

    FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) v.getLayoutParams();

    switch(event.getAction())
    {

    case MotionEvent.ACTION_DOWN :

        pressedx=currentx;
        pressedy=currenty;

        viewMariginX=layoutParams.leftMargin;
        viewMariginY=layoutParams.topMargin;
        break;


    case MotionEvent.ACTION_MOVE : 

        int diffx=currentx-pressedx;
        int diffy=currenty-pressedy;

        int marginx=viewMariginX+diffx;
        int marginy=viewMariginY+diffy;


        layoutParams.leftMargin=marginx;
        layoutParams.topMargin=marginy;     
        v.setLayoutParams(layoutParams);          
        break;

    case MotionEvent.ACTION_UP : 

        int diffx2=currentx-pressedx;
        int diffy2=currenty-pressedy;

        int marginx2=viewMariginX+diffx2;
        int marginy2=viewMariginY+diffy2;


        layoutParams.leftMargin=marginx2;
        layoutParams.topMargin=marginy2;            
        v.setLayoutParams(layoutParams);    
        break;
    }

    return true;
}

Your reference is similar to what i have done few days ago. 您的参考与我几天前所做的相似。

It take difference of two postions and add them to the current View margin from left and from top. 它需要两个位置的差值,并将它们从左和从顶部添加到当前视图边距。

You can retain View's Position by saving those margin values. 您可以通过保存这些边距值来保留View的Position。

NOTE : You have to take care of your MAX and MIN Bounds 注意 :您必须注意自己的最大和最小界限

hope it helps you... 希望对您有帮助...

UPDATE : 1) Attach onTouchListners on you as many cardviews as you want 更新 :1)将onTouchListners附加到您想要的任意多个卡片视图上

cardview.setOnTouchListener(this); cardview.setOnTouchListener(this); cardview1.setOnTouchListener(this); cardview1.setOnTouchListener(this);

OnTouch(View v, MotionEvent event) Called when a touch event is dispatched to a view. OnTouch(View v,MotionEvent event)在将touch事件调度到视图时调用。 This allows listeners to get a chance to respond before the target view. 这使听众有机会在目标视图之前做出响应。

Specified by: onTouch(...) in OnTouchListener Parameters: v : The view the touch event has been dispatched to. 指定者:OnTouchListener中的onTouch(...)参数:v:已将touch事件调度到的视图。 event : The MotionEvent object containing full information about the event. event:包含有关事件的完整信息的MotionEvent对象。 by docs. 通过文档。

change your cardview in onTouch to v 在onTouch中将您的Cardview更改为v

From your question 从你的问题

FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) v.getLayoutParams(); FrameLayout.LayoutParams layoutParams =(FrameLayout.LayoutParams)v.getLayoutParams();

ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(v, "y", this.getY(), marginy); ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(v,“ y”,this.getY(),marginy); positionAnimator.setDuration(0); positionAnimator.setDuration(0); positionAnimator.start(); positionAnimator.start();

change further references in same method. 用相同的方法更改其他参考。

2) problem in setting bounds is simple Condition check just before changing the position. 2)设置边界的问题很简单,仅在更改位置之前进行条件检查。

and sorry for bad explanation. 很抱歉,您的解释不正确。

This animation: 此动画:

ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(card, "y", this.getY(), 0);

Moves the view on the vertical axis from the this.getY() y position to 0 (the top of the screen). 将垂直轴上的视图从this.getY() y位置移动到0(屏幕顶部)。

I see you're setting some bounds max_height and min_height , but you're not using them in any way. 我看到您正在设置max_heightmin_height一些界限,但是您没有以任何方式使用它们。

I'm not sure what you're requirements are but you can do something like this: 我不确定您的要求是什么,但是您可以执行以下操作:

ObjectAnimator positionAnimator = ObjectAnimator.ofFloat(card, "y", this.getY(), (Math.abs(this.getY() - min_height) < Math.abs(this.getY() - max_height))?min_height:max_height);

What this will do is to move the object to min_height or max_height based on which one is the closest. 这样做是根据最接近的对象将对象移动到min_heightmax_height

The view seems to also be animated by this calls this.setY(baseLayoutPosition + diffY); requestLayout(); 通过调用this.setY(baseLayoutPosition + diffY); requestLayout();该视图似乎也可以动画化this.setY(baseLayoutPosition + diffY); requestLayout(); this.setY(baseLayoutPosition + diffY); requestLayout(); , you will have to make sure that baseLayoutPosition + diffY is within the bounds, something like: ,您必须确保baseLayoutPosition + diffY在范围之内,例如:

int amount = baseLayoutPosition + diffY;
this.setY(Math.min(max_height, Math.max(min_height, amount)));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM