Android移动触摸事件视图



我想在布局中移动两个不同的视图,这样用户就可以随心所欲地显示它。

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

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;
    }
});

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

我可以移动元素,但当我触摸它时,它会闪烁,一旦我竖起手指,视图就会消失。我甚至找不到它,它就在屏幕外。

我做错什么了吗?

感谢您的帮助

使用以下代码执行简单的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;
        }
    });

其中layout_counter是要移动的视图。

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

我创建了库,它移动了视图:

  • 对于低于JellyBean(16)的API,它在其父容器中修改视图的页边距
  • 对于API JellyBean和更高版本,它修改其父容器中的绝对视图位置

只需添加依赖项:

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

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

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

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;
        }
    }
}

最新更新