7

我在RelativeLayout內部創建了一個可拖動視圖。但它似乎超越了RelativeLayout。綁定一個視圖在RelativeLayout中拖動

我只想做一個視圖中的ViewGroup

拖動這種觀點根據屏幕是draggable。它可以在RelativeLayout的邊界之外拖動。我如何限制它在RelativeLayout中保持可拖動狀態。

CustomImageButton

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

編輯:

ImageButton的可拖動而且走得outside of parent限制它在它的父級佈局中拖動。

+0

也試過http://stackoverflow.com/問題/ 21662397 /如何保持圖像內的佈局與拖放 – Nepster

回答

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)); 
+0

myView.setOnTouchListener(new OnDragTouchListener (myView,myParentView)); wroks謝謝 – Nepster

+0

太棒了!謝啦! – belphegor

+0

嗨好片段...如何將onClickListener添加到具有相同功能的相同視圖? – AndiM

1

在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或監聽器或類似Determining the size of an Android view at runtime

+0

如何獲得BoundayParams裏面ImageButtonCustom – Nepster

3

您應該使用rootView.getX()rootView.getY()的左側和頂部bounderies ......和(rootView.getX() + rootView.getWidth())爲右邊和(rootView.getY() + rootView.getHeight())爲底部邊界。

您必須在ACTION_MOVE案例中的onTouch()中編寫邊界邏輯。

希望這會有所幫助。

相關問題