private int getViewHeight() {
   DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();
   if (draweeView != null) {
     return draweeView.getHeight() - draweeView.getPaddingTop() - draweeView.getPaddingBottom();
   }
   return 0;
 }
  @Override
  public void onDrag(float dx, float dy) {

    DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();

    if (draweeView != null && !mScaleDragDetector.isScaling()) {
      mMatrix.postTranslate(dx, dy);
      checkMatrixAndInvalidate();

      ViewParent parent = draweeView.getParent();
      if (parent == null) {
        return;
      }

      if (mAllowParentInterceptOnEdge
          && !mScaleDragDetector.isScaling()
          && !mBlockParentIntercept) {
        if (mScrollEdge == EDGE_BOTH
            || (mScrollEdge == EDGE_LEFT && dx >= 1f)
            || (mScrollEdge == EDGE_RIGHT && dx <= -1f)) {
          parent.requestDisallowInterceptTouchEvent(false);
        }
      } else {
        parent.requestDisallowInterceptTouchEvent(true);
      }
    }
  }
 @Override
 public void setScale(float scale, boolean animate) {
   DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();
   if (draweeView != null) {
     setScale(scale, (draweeView.getRight()) / 2, (draweeView.getBottom()) / 2, false);
   }
 }
 private void resetMatrix() {
   mMatrix.reset();
   checkMatrixBounds();
   DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();
   if (draweeView != null) {
     draweeView.invalidate();
   }
 }
 private RectF getDisplayRect(Matrix matrix) {
   DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();
   if (draweeView == null || (mImageInfoWidth == -1 && mImageInfoHeight == -1)) {
     return null;
   }
   mDisplayRect.set(0.0F, 0.0F, mImageInfoWidth, mImageInfoHeight);
   draweeView.getHierarchy().getActualImageBounds(mDisplayRect);
   matrix.mapRect(mDisplayRect);
   return mDisplayRect;
 }
  @Override
  public void onFling(float startX, float startY, float velocityX, float velocityY) {
    DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();
    if (draweeView == null) {
      return;
    }

    mCurrentFlingRunnable = new FlingRunnable(draweeView.getContext());
    mCurrentFlingRunnable.fling(getViewWidth(), getViewHeight(), (int) velocityX, (int) velocityY);
    draweeView.post(mCurrentFlingRunnable);
  }
  private int getViewWidth() {

    DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();

    if (draweeView != null) {

      return draweeView.getWidth() - draweeView.getPaddingLeft() - draweeView.getPaddingRight();
    }

    return 0;
  }
  public void checkMatrixAndInvalidate() {

    DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();

    if (draweeView == null) {
      return;
    }

    if (checkMatrixBounds()) {
      draweeView.invalidate();
    }
  }
  private void checkMinScale() {
    DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();
    if (draweeView == null) {
      return;
    }

    if (getScale() < mMinScale) {
      RectF rect = getDisplayRect();
      if (null != rect) {
        draweeView.post(
            new AnimatedZoomRunnable(getScale(), mMinScale, rect.centerX(), rect.centerY()));
      }
    }
  }
  @Override
  public void setScale(float scale, float focalX, float focalY, boolean animate) {
    DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();

    if (draweeView == null || scale < mMinScale || scale > mMaxScale) {
      return;
    }

    if (animate) {
      draweeView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));
    } else {
      mMatrix.setScale(scale, scale, focalX, focalY);
      checkMatrixAndInvalidate();
    }
  }
    @Override
    public void run() {
      if (mScroller.isFinished()) {
        return;
      }

      DraweeView<GenericDraweeHierarchy> draweeView = getDraweeView();

      if (draweeView != null && mScroller.computeScrollOffset()) {
        final int newX = mScroller.getCurrX();
        final int newY = mScroller.getCurrY();
        mMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
        draweeView.invalidate();
        mCurrentX = newX;
        mCurrentY = newY;
        postOnAnimation(draweeView, this);
      }
    }
 public Attacher(DraweeView<GenericDraweeHierarchy> draweeView) {
   mDraweeView = new WeakReference<DraweeView<GenericDraweeHierarchy>>(draweeView);
   draweeView.getHierarchy().setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER);
   draweeView.setOnTouchListener(this);
   mScaleDragDetector = new ScaleDragDetector(draweeView.getContext(), this);
   mGestureDetector =
       new GestureDetectorCompat(
           draweeView.getContext(),
           new GestureDetector.SimpleOnGestureListener() {
             @Override
             public void onLongPress(MotionEvent e) {
               super.onLongPress(e);
               if (null != mLongClickListener) {
                 mLongClickListener.onLongClick(getDraweeView());
               }
             }
           });
   mGestureDetector.setOnDoubleTapListener(new DefaultOnDoubleTapListener(this));
 }