代码之家  ›  专栏  ›  技术社区  ›  Zar E Ahmer

绑定视图以在RelativeLayout中拖动

  •  10
  • Zar E Ahmer  · 技术社区  · 9 年前

    我创建了一个 。但它似乎超越了RelativeLayout。

    我只想在ViewGroup中创建一个可拖动的视图

    这个视图是 draggable

    自定义图像按钮

    public class ImageButtonCustom extends ImageButton implements View.OnTouchListener{
    
        float dX, dY;
    
        private RelativeLayout rootView;
        private ImageButtonCustom imageButtonCustom;
        private OnMoveListener onMoveListener;
    
        public ImageButtonCustom(Context context,RelativeLayout rootView){
            super(context);
            this.rootView = rootView;
            init();
    
        }
        public ImageButtonCustom(Context context) {
            super(context);
            init();
        }
    
        public ImageButtonCustom(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public ImageButtonCustom(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init(){
            imageButtonCustom = this;
            setImageResource(R.drawable.upper_left);
            setBackgroundColor(Color.TRANSPARENT);
            setOnTouchListener(this);
    
            /*RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            rl.addRule(RelativeLayout.ALIGN_BOTTOM);*/
    
            rootView.addView(this);
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    dX = v.getX() - event.getRawX();
                    dY = v.getY() - event.getRawY();
                    break;
                case MotionEvent.ACTION_UP:
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    break;
                case MotionEvent.ACTION_MOVE:
                    v.animate()
                            .x(event.getRawX() + dX)
                            .y(event.getRawY() + dY)
                            .setDuration(0)
                            .start();
                    //no use of ViewPositionUtil
                    onMoveListener.onMove(new Position());//positionXY);
                    break;
            }
            rootView.invalidate();
            return true;
        }
    
        public void setOnMoveListener(OnMoveListener onMoveListener){
            this.onMoveListener = onMoveListener;
        }
    
        public float getCenterX(){
            return getX() + getWidth()  / 2;
    
        }
        public float getCenterY(){
            return getY() + getHeight() / 2;
    
        }
    
        public interface OnMoveListener{
            void onMove(Position positionXY);
        }
    }
    

    编辑:

    这个 但它去了 outside of parent . 限制 在其父布局中拖动。

    3 回复  |  直到 9 年前
        1
  •  26
  •   Rehan    9 年前

    这是我旧日记的摘录。希望它对你有用。

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

    您可以使用以下方法进行设置:

    myView.setOnTouchListener(new OnDragTouchListener(myView));
    

    init

    setOnTouchListener(new OnDragTouchListener(this));
    
        2
  •  4
  •   Pirdad Sakhizada    9 年前

    你应该使用 rootView.getX() rootView.getY() 作为左上边界…和 (rootView.getX() + rootView.getWidth()) 作为权利和 (rootView.getY() + rootView.getHeight()) 用于底部边界。

    在ACTION_MOVE案例中,您必须在onTouch()中编写边界逻辑。

    希望这能有所帮助。

        3
  •  1
  •   Community Mohan Dere    9 年前

    在OnTouch中,您可以计算视图的移动位置

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

    在移动之前,应该检查x和y的边界。

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

    要在运行时计算RelativeLayout的边界,您应该使用Runnable或Listener或类似工具 Determining the size of an Android view at runtime