Question

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

element is an instance of a custom object to handle the position. screenHeight is the screen height given by the Display class.

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

Was it helpful?

Solution

USe the following code to perform a simple 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_counter is the view you want to move.

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

OTHER TIPS

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

Just add the dependency:

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

More info you can find on GitHub

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;
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top