7

अंदर खींचें करने के लिए एक बाँधा हुआ मैं RelativeLayout अंदर एक खींचने योग्य दृश्य पैदा की है। लेकिन ऐसा लगता है कि रिलेवेटिवआउट से परे है।RelativeLayout

मैं बस एक दृश्य ViewGroup

अंदर खींचने योग्य बनाना चाहते और इस दृश्य स्क्रीन के अनुसार draggable है। और यह 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 (नया OnDragTouchListener (myView, myParentView)); wroks धन्यवाद – Nepster

+0

महान! धन्यवाद दोस्त! – belphegor

+0

हाय अच्छा स्निपेट ... उसी कार्यक्षमता के साथ उसी दृश्य पर क्लिकक्लिक लिस्टर कैसे जोड़ें? – 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

छविबटन के अंदर सीमाएं कैसे प्राप्त करें कस्टम – Nepster

3

आप rootView.getX() और rootView.getY() छोड़ दिया और शीर्ष bounderies के रूप में इस्तेमाल करना चाहिए ... और (rootView.getX() + rootView.getWidth()) के रूप में निचली सीमा के लिए दाएं और (rootView.getY() + rootView.getHeight())

आपको ACTION_MOVE मामले में ऑन-टच() में अपना सीमा तर्क लिखना होगा।

उम्मीद है कि इससे मदद मिलती है।

संबंधित मुद्दे