2014-10-03 2 views
0

에 자식 드래그 앤 드롭이 나는 다음과 같은 상황이 안드로이드 :는 줌 및 팬과 긴 클릭

ZoomAndPanLayout 
    | 
    +---> ImageView 
    | 
    +---> FrameLayout (DragLayer) 
      | 
      +---> One or more controls. A view with a circle drawn on it. 

몇 가지 사소한 문제를 내가 걱정하지 않기 때문에 지금 화면에 대해 ZoomAndPanLayout 작동 바인딩. 나는이 같은 ZoomAndPan을 구현 :

public class ZoomAndPanLayout extends FrameLayout { 

    //region Constants 

    public static final float DEFAULT_MIN_SCALE_FACTOR = 1.0f; 
    public static final float DEFAULT_MAX_SCALE_FACTOR = 5.0f; 

    // endregion Constants 


    // region Fields 

    private float translationX = 0; 
    private float translationY = 0; 

    private float pivotX = 0; 
    private float pivotY = 0; 

    private float oldX; 
    private float oldY; 

    private float scaleFactor = 1.0f; 

    private float minScaleFactor = ZoomAndPanLayout.DEFAULT_MIN_SCALE_FACTOR; 
    private float maxScaleFactor = ZoomAndPanLayout.DEFAULT_MAX_SCALE_FACTOR; 

    private ScaleGestureDetector scaleGestureDetector = null; 

    // endregion Fields 


    // region Constructor 

    public ZoomAndPanLayout(Context context) { 
     super(context); 
     this.initialize(context); 
    } 

    public ZoomAndPanLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.initialize(context); 
    } 

    public ZoomAndPanLayout(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     this.initialize(context); 
    } 

    private void initialize(Context context) { 
     this.scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener()); 
    } 


    // endregion Constructor 


    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     this.scaleGestureDetector.onTouchEvent(event); 

     switch (event.getAction()) 
     { 
      case MotionEvent.ACTION_DOWN: 
      { 
       this.oldX = event.getX(); 
       this.oldY = event.getY(); 

       break; 
      } 

      case MotionEvent.ACTION_MOVE: 
      { 
       if (!this.scaleGestureDetector.isInProgress()) 
       { 
        float x = event.getX(); 
        float y = event.getY(); 

        float deltaX = x - this.oldX; 
        float deltaY = y - this.oldY; 

        this.translationX += deltaX; 
        this.translationY += deltaY; 

        this.applyTransformations(); 

        this.oldX = x; 
        this.oldY = y; 
       } 
      } 
     } 

     return true; 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent event) { 
     return this.scaleGestureDetector.onTouchEvent(event); 
    } 

    private void applyTransformations() { 
     final View child = this.getChildAt(0); 

     if (child != null) 
     { 
      child.setPivotX(this.pivotX); 
      child.setPivotY(this.pivotY); 

      child.setScaleX(this.scaleFactor); 
      child.setScaleY(this.scaleFactor); 

      // TODO: bound child to screen limits 

      child.setTranslationX(this.translationX); 
      child.setTranslationY(this.translationY); 
     } 
    } 

    public Rect getChildRect() { 

     View child = this.getChildAt(0); 

     if (child != null) 
     { 
      Rect outRect = new Rect(); 

      outRect.right = (int) (child.getWidth() * child.getScaleX()); 
      outRect.bottom = (int) (child.getHeight() * child.getScaleY()); 

      int[] location = new int[2]; 
      child.getLocationOnScreen(location); 

      outRect.offset(location[0], location[1]); 

      return outRect; 
     } 
     else 
     { 
      return new Rect(0, 0, 0, 0); 
     } 
    } 

    // region Private Inner Enums, Interfaces and Classes 

    private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
     private ZoomAndPanLayout upper = ZoomAndPanLayout.this; 

     @Override 
     public boolean onScale(ScaleGestureDetector detector) { 
      float newScaleFactor = detector.getScaleFactor(); 
      float originalScaleFactor = upper.scaleFactor; 

      upper.scaleFactor *= newScaleFactor; 

      // Bound the scaleFactor to the min and max limits 
      if (upper.scaleFactor >= upper.maxScaleFactor) 
      { 
       upper.scaleFactor = upper.maxScaleFactor; 
       newScaleFactor = upper.maxScaleFactor/originalScaleFactor; 
      } 
      else if (upper.scaleFactor * newScaleFactor <= upper.minScaleFactor) 
      { 
       upper.scaleFactor = upper.minScaleFactor; 
       newScaleFactor = upper.minScaleFactor/originalScaleFactor; 
      } 

      // set pivot 
      View child = upper.getChildAt(0); 

      if (child != null) 
      { 
       if (newScaleFactor * child.getWidth() * upper.scaleFactor <= originalScaleFactor * child.getWidth() 
         || newScaleFactor * child.getHeight() * upper.scaleFactor <= originalScaleFactor * child.getWidth()) 
       { 
        upper.pivotX = newScaleFactor * child.getWidth()/2; 
        upper.pivotY = newScaleFactor * child.getHeight()/2; 
       } 
       else 
       { 
        upper.pivotX = detector.getFocusX(); 
        upper.pivotY = detector.getFocusY(); 
       } 
      } 

      upper.applyTransformations(); 

      return true; 
     } 
    } 

    // endregion Private Inner Enums, Interfaces and Classes 
} 

내가 그들에게 OnLongClickListener를 할당 DragLayer 각각의 아이를 만들

하지만, 젠장 일이 발생하지 복용량. DragLayer의 자식을 오래 클릭하면

어떤 생각이든 내가 어떻게 ZoomAndPanLayout 또는 다른 아이디어를 사용하여 구현할 수 있습니까? 왜 내가 ZoomAndPanLayout이 필요한지 스스로에게 묻는다면, ImageView뿐만 아니라 모든 레이아웃을 확대/축소 할 수 있어야하기 때문입니다.

아이디어가 있으십니까?

답변

0

아마도 trueonTouchEvent 방법으로 반환하기 때문입니다. true이 반환되면 이벤트를 소비하고 어린이는 자신의 onTouchEvent을받지 못합니다.

@Override public boolean onInterceptTouchEvent(MotionEvent event) { return this.scaleGestureDetector.onTouchEvent(event); }

항상 이벤트를 수신 true과도 블록 아이들을 반환합니다.