Android 在触摸事件上移动视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23120807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:48:22  来源:igfitidea点击:

Android move view on touch event

androidtouchontouchlistener

提问by Manitoba

I would like to move two different views into my layout, so that an user can display it like his wishes.

我想将两个不同的视图移动到我的布局中,以便用户可以按照自己的意愿显示它。

So far I've made the following code to handle the touch event:

到目前为止,我已经编写了以下代码来处理触摸事件:

this.viewEvent.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent event)
    {           
        final int y = (int) event.getRawY();

        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();
        switch (event.getAction() & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:
                element.setEventY(y - params.topMargin);
                break;

            case MotionEvent.ACTION_UP:
                viewGroup.invalidate();
                break;

            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_POINTER_UP:
                break;

            case MotionEvent.ACTION_MOVE:
                params.topMargin = y - element.getEventY();
                params.bottomMargin = screenHeight - view.getHeight() - params.topMargin;

                // Avoid out of screen
                if (params.topMargin < 0) return true;

                // Apply changes
                view.setLayoutParams(params);
                break;
        }

        return true;
    }
});

elementis an instance of a custom object to handle the position. screenHeightis the screen height given by the Displayclass.

element是用于处理位置的自定义对象的实例。 screenHeightDisplay类给出的屏幕高度。

I'm able to move the element but it's blinking when I touch it and once I put my finger up, the view just disapear. I can't even retrieve it, it's just out of the screen.

我可以移动元素,但是当我触摸它时它会闪烁,一旦我抬起手指,视图就会消失。我什至无法检索它,它只是在屏幕外。

Did I make something wrong ?

我做错了什么吗?

Thanks for your help

谢谢你的帮助

回答by Manitoba

USe the following code to perform a simple Touch to move:

使用以下代码执行一个简单的Touch to move

layout_counter.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent event)
        {
            if (currentState != State.EDIT_MOVE) return false;

            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
            if (view.getId() != R.id.layout_counter) return false;

            switch (event.getAction())
            {
                case MotionEvent.ACTION_MOVE:
                    params.topMargin = (int) event.getRawY() - view.getHeight();
                    params.leftMargin = (int) event.getRawX() - (view.getWidth() / 2);
                    view.setLayoutParams(params);
                    break;

                case MotionEvent.ACTION_UP:
                    params.topMargin = (int) event.getRawY() - view.getHeight();
                    params.leftMargin = (int) event.getRawX() - (view.getWidth() / 2);
                    view.setLayoutParams(params);
                    break;

                case MotionEvent.ACTION_DOWN:
                    view.setLayoutParams(params);
                    break;
            }

            return true;
        }
    });

Where layout_counteris the view you want to move.

layout_counter您要移动的视图在哪里。

Don't forget to put your movable elements into a FrameLayout

不要忘记将可移动元素放入 FrameLayout

回答by Vladyslav Baidak

I created the library, which moves the view:

我创建了移动视图的库:

  • For API lower than JellyBean (16) it modifies the view's margins within its parent container
  • For API JellyBean and higher it modifies the absolute view position within its parent container
  • 对于低于 JellyBean (16) 的 API,它会在其父容器内修改视图的边距
  • 对于 API JellyBean 及更高版本,它会修改其父容器内的绝对视图位置

Just add the dependency:

只需添加依赖项:

dependencies {
    compile 'com.scalified:viewmover:1.1.0'
}

More info you can find on GitHub

您可以在GitHub 上找到更多信息

回答by Ayaz Alifov

I will provide an alternative solution for those who use Relative layout for example.

例如,我将为那些使用相对布局的人提供替代解决方案。

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class MainActivity extends Activity implements View.OnTouchListener
{
    private int       _xDelta;
    private int       _yDelta;
    private int       _rightMargin;
    private int       _bottomMargin;
    private ImageView _floatingView;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this._floatingView = (ImageView) findViewById(R.id.textView);

        this._floatingView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
        {
            @Override
            public boolean onPreDraw()
            {
                if (_floatingView.getViewTreeObserver().isAlive())
                    _floatingView.getViewTreeObserver().removeOnPreDrawListener(this);

                updateLayoutParams(_floatingView);
                return false;
            }
        });

        this._floatingView.setOnTouchListener(this);
    }

    private void updateLayoutParams(View view)
    {
        this._rightMargin = -view.getMeasuredWidth();
        this._bottomMargin = -view.getMeasuredHeight();

        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(view.getMeasuredWidth(), view.getMeasuredHeight());
        layoutParams.bottomMargin = this._bottomMargin;
        layoutParams.rightMargin = this._rightMargin;

        view.setLayoutParams(layoutParams);
    }

    @Override
    public boolean onTouch(View view, MotionEvent event)
    {
        if (view == this._floatingView)
        {
            final int X = (int) event.getRawX();
            final int Y = (int) event.getRawY();

            switch (event.getAction() & MotionEvent.ACTION_MASK)
            {
                case MotionEvent.ACTION_DOWN:
                    RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
                    this._xDelta = X - lParams.leftMargin;
                    this._yDelta = Y - lParams.topMargin;
                    break;

                case MotionEvent.ACTION_MOVE:
                    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
                    layoutParams.leftMargin = X - this._xDelta;
                    layoutParams.topMargin = Y - this._yDelta;
                    layoutParams.rightMargin = this._rightMargin;
                    layoutParams.bottomMargin = this._bottomMargin;
                    view.setLayoutParams(layoutParams);
                    break;
            }

            return true;
        }
        else
        {
            return false;
        }
    }
}