Bound a View to drag inside RelativeLayout

前端 未结 3 1477
小鲜肉
小鲜肉 2021-01-04 22:36

I have created a draggable view inside RelativeLayout. But it seems to go beyond the RelativeLayout.

I simply

相关标签:
3条回答
  • 2021-01-04 23:01

    In OnTouch you calculate where to move your view

    case MotionEvent.ACTION_MOVE:
                v.animate()
                        .x(event.getRawX() + dX)
                        .y(event.getRawY() + dY)
                        .setDuration(0)
                        .start();
    

    You should check the boundaries for x and y before moving it.

    case MotionEvent.ACTION_MOVE:
            float x = event.getRawX() + dX; float y = event.getRawY() + dY;
            if (x > boundaryRight) x = boundaryRight;
            else if (x < boundaryLeft) x = boundaryLeft;
            if (y < boundaryTop) y = boundaryTop;
            else if (y > boundaryBottom) y = boundaryBottom;
            v.animate()
                    .x(x)
                    .y(y)
                    .setDuration(0)
                    .start();
    

    And to calculate boundaries of your RelativeLayout at run-time you should use Runnable or a Listener or similar Determining the size of an Android view at runtime

    0 讨论(0)
  • 2021-01-04 23:02

    You should use rootView.getX() and rootView.getY() as the left and top bounderies... and (rootView.getX() + rootView.getWidth()) as the right and (rootView.getY() + rootView.getHeight()) for the bottom boundary.

    You have to write your boundary logic in onTouch() in the ACTION_MOVE case.

    Hope this helps.

    0 讨论(0)
  • 2021-01-04 23:15

    Here's an extract from my old diaries. Hope it works for you.

    public class OnDragTouchListener implements View.OnTouchListener {
    
        /**
         * Callback used to indicate when the drag is finished
         */
        public interface OnDragActionListener {
            /**
             * Called when drag event is started
             *
             * @param view The view dragged
             */
            void onDragStart(View view);
    
            /**
             * Called when drag event is completed
             *
             * @param view The view dragged
             */
            void onDragEnd(View view);
        }
    
        private View mView;
        private View mParent;
        private boolean isDragging;
        private boolean isInitialized = false;
    
        private int width;
        private float xWhenAttached;
        private float maxLeft;
        private float maxRight;
        private float dX;
    
        private int height;
        private float yWhenAttached;
        private float maxTop;
        private float maxBottom;
        private float dY;
    
        private OnDragActionListener mOnDragActionListener;
    
        public OnDragTouchListener(View view) {
            this(view, (View) view.getParent(), null);
        }
    
        public OnDragTouchListener(View view, View parent) {
            this(view, parent, null);
        }
    
        public OnDragTouchListener(View view, OnDragActionListener onDragActionListener) {
            this(view, (View) view.getParent(), onDragActionListener);
        }
    
        public OnDragTouchListener(View view, View parent, OnDragActionListener onDragActionListener) {
            initListener(view, parent);
            setOnDragActionListener(onDragActionListener);
        }
    
        public void setOnDragActionListener(OnDragActionListener onDragActionListener) {
            mOnDragActionListener = onDragActionListener;
        }
    
        public void initListener(View view, View parent) {
            mView = view;
            mParent = parent;
            isDragging = false;
            isInitialized = false;
        }
    
        public void updateBounds() {
            updateViewBounds();
            updateParentBounds();
            isInitialized = true;
        }
    
        public void updateViewBounds() {
            width = mView.getWidth();
            xWhenAttached = mView.getX();
            dX = 0;
    
            height = mView.getHeight();
            yWhenAttached = mView.getY();
            dY = 0;
        }
    
        public void updateParentBounds() {
            maxLeft = 0;
            maxRight = maxLeft + mParent.getWidth();
    
            maxTop = 0;
            maxBottom = maxTop + mParent.getHeight();
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (isDragging) {
                float[] bounds = new float[4];
                // LEFT
                bounds[0] = event.getRawX() + dX;
                if (bounds[0] < maxLeft) {
                    bounds[0] = maxLeft;
                }
                // RIGHT
                bounds[2] = bounds[0] + width;
                if (bounds[2] > maxRight) {
                    bounds[2] = maxRight;
                    bounds[0] = bounds[2] - width;
                }
                // TOP
                bounds[1] = event.getRawY() + dY;
                if (bounds[1] < maxTop) {
                    bounds[1] = maxTop;
                }
                // BOTTOM
                bounds[3] = bounds[1] + height;
                if (bounds[3] > maxBottom) {
                    bounds[3] = maxBottom;
                    bounds[1] = bounds[3] - height;
                }
    
                switch (event.getAction()) {
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        onDragFinish();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        mView.animate().x(bounds[0]).y(bounds[1]).setDuration(0).start();
                        break;
                }
                return true;
            } else {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        isDragging = true;
                        if (!isInitialized) {
                            updateBounds();
                        }
                        dX = v.getX() - event.getRawX();
                        dY = v.getY() - event.getRawY();
                        if (mOnDragActionListener != null) {
                            mOnDragActionListener.onDragStart(mView);
                        }
                        return true;
                }
            }
            return false;
        }
    
        private void onDragFinish() {
            if (mOnDragActionListener != null) {
                mOnDragActionListener.onDragEnd(mView);
            }
    
            dX = 0;
            dY = 0;
            isDragging = false;
        }
    }
    

    And you can set it using:

    myView.setOnTouchListener(new OnDragTouchListener(myView));
    

    Or by adding this directly in init method of your Custom View:

    setOnTouchListener(new OnDragTouchListener(this));
    
    0 讨论(0)
提交回复
热议问题