Android移动视图触摸事件

时间:2014-04-16 21:51:09

标签: android touch ontouchlistener

我想在我的布局中移动两个不同的视图,以便用户可以像他的意愿一样显示它。

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

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是处理该位置的自定义对象的实例。 screenHeightDisplay类给出的屏幕高度。

我能够移动元素,但是当我触摸它时它会闪烁,一旦我把手指放上,视图就会消失。我甚至无法取回它,它只是在屏幕之外。

我做错了吗?

感谢您的帮助

3 个答案:

答案 0 :(得分:19)

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

答案 1 :(得分:2)

我创建了移动视图的库:

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

只需添加依赖项:

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

您可以在GitHub

找到更多信息

答案 2 :(得分:0)

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

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;
        }
    }
}
相关问题