2014-12-05 2 views
1

У меня есть несколько динамических изображений, которые отображаются на основе X, Y, Height, Width. Эти изображения связываются с RelativeLayout, и этот макет связывается с моим классом ZoomableViewGroup. Когда я нажимаю на изображение, цвет заполняется.Android: ImageView не улучшается после сброса zoom

public class ZoomableViewGroup extends ViewGroup { 

private Context mContext; 
private static final int INVALID_POINTER_ID = 1; 
private int mActivePointerId = INVALID_POINTER_ID; 

private float mScaleFactor = 1; 
private ScaleGestureDetector mScaleDetector; 
private Matrix mScaleMatrix = new Matrix(); 
private Matrix mScaleMatrixInverse = new Matrix(); 

private float mPosX; 
private float mPosY; 
private Matrix mTranslateMatrix = new Matrix(); 
private Matrix mTranslateMatrixInverse = new Matrix(); 

private float mLastTouchX; 
private float mLastTouchY; 

private float mFocusY; 

private float mFocusX; 

private float[] mInvalidateWorkingArray = new float[6]; 
private float[] mDispatchTouchEventWorkingArray = new float[2]; 
private float[] mOnTouchEventWorkingArray = new float[2]; 

public ZoomableViewGroup(Context context) { 
    super(context); 
    this.mContext = context; 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    mTranslateMatrix.setTranslate(0, 0); 
    mScaleMatrix.setScale(1, 1); 
} 

@Override 
protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    int childCount = getChildCount(); 
    for (int i = 0; i < childCount; i++) { 
     View child = getChildAt(i); 
     if (child.getVisibility() != GONE) { 
      child.layout(l, t, l + child.getMeasuredWidth(), 
        t + child.getMeasuredHeight()); 
     } 
    } 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    int childCount = getChildCount(); 
    for (int i = 0; i < childCount; i++) { 
     View child = getChildAt(i); 
     if (child.getVisibility() != GONE) { 
      measureChild(child, widthMeasureSpec, heightMeasureSpec); 
     } 
    } 
} 

@Override 
protected void dispatchDraw(Canvas canvas) { 
    canvas.save(); 
    canvas.translate(mPosX, mPosY); 
    canvas.scale(mScaleFactor, mScaleFactor, mFocusX, mFocusY); 
    super.dispatchDraw(canvas); 
    canvas.restore(); 
} 

@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 
    mDispatchTouchEventWorkingArray[0] = ev.getX(); 
    mDispatchTouchEventWorkingArray[1] = ev.getY(); 
    mDispatchTouchEventWorkingArray = screenPointsToScaledPoints(mDispatchTouchEventWorkingArray); 
    ev.setLocation(mDispatchTouchEventWorkingArray[0], 
      mDispatchTouchEventWorkingArray[1]); 
    return super.dispatchTouchEvent(ev); 
} 

@Override 
public ViewParent invalidateChildInParent(int[] location, Rect dirty) { 
    mInvalidateWorkingArray[0] = dirty.left; 
    mInvalidateWorkingArray[1] = dirty.top; 
    mInvalidateWorkingArray[2] = dirty.right; 
    mInvalidateWorkingArray[3] = dirty.bottom; 

    mInvalidateWorkingArray = scaledPointsToScreenPoints(mInvalidateWorkingArray); 
    dirty.set(Math.round(mInvalidateWorkingArray[0]), 
      Math.round(mInvalidateWorkingArray[1]), 
      Math.round(mInvalidateWorkingArray[2]), 
      Math.round(mInvalidateWorkingArray[3])); 

    location[0] *= mScaleFactor; 
    location[1] *= mScaleFactor; 
    return super.invalidateChildInParent(location, dirty); 
} 

private float[] scaledPointsToScreenPoints(float[] a) { 
    mScaleMatrix.mapPoints(a); 
    mTranslateMatrix.mapPoints(a); 
    return a; 
} 

private float[] screenPointsToScaledPoints(float[] a) { 
    mTranslateMatrixInverse.mapPoints(a); 
    mScaleMatrixInverse.mapPoints(a); 
    return a; 
} 

@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    mOnTouchEventWorkingArray[0] = ev.getX(); 
    mOnTouchEventWorkingArray[1] = ev.getY(); 

    mOnTouchEventWorkingArray = scaledPointsToScreenPoints(mOnTouchEventWorkingArray); 

    ev.setLocation(mOnTouchEventWorkingArray[0], 
      mOnTouchEventWorkingArray[1]); 
    mScaleDetector.onTouchEvent(ev); 

    final int action = ev.getAction(); 
    switch (action & MotionEvent.ACTION_MASK) { 
    case MotionEvent.ACTION_DOWN: { 
     final float x = ev.getX(); 
     final float y = ev.getY(); 

     mLastTouchX = x; 
     mLastTouchY = y; 

     // Save the ID of this pointer 
     mActivePointerId = ev.getPointerId(0); 
     break; 
    } 

    case MotionEvent.ACTION_MOVE: { 
     // Find the index of the active pointer and fetch its position 
     final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
     final float x = ev.getX(pointerIndex); 
     final float y = ev.getY(pointerIndex); 

     final float dx = x - mLastTouchX; 
     final float dy = y - mLastTouchY; 

     mPosX += dx; 
     mPosY += dy; 
     mTranslateMatrix.preTranslate(dx, dy); 
     mTranslateMatrix.invert(mTranslateMatrixInverse); 

     mLastTouchX = x; 
     mLastTouchY = y; 

     invalidate(); 
     break; 
    } 

    case MotionEvent.ACTION_UP: { 
     mActivePointerId = INVALID_POINTER_ID; 
     break; 
    } 

    case MotionEvent.ACTION_CANCEL: { 
     mActivePointerId = INVALID_POINTER_ID; 
     break; 
    } 

    case MotionEvent.ACTION_POINTER_UP: { 
     // Extract the index of the pointer that left the touch sensor 
     final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
     final int pointerId = ev.getPointerId(pointerIndex); 
     if (pointerId == mActivePointerId) { 
      // This was our active pointer going up. Choose a new 
      // active pointer and adjust accordingly. 
      final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
      mLastTouchX = ev.getX(newPointerIndex); 
      mLastTouchY = ev.getY(newPointerIndex); 
      mActivePointerId = ev.getPointerId(newPointerIndex); 
     } 
     break; 
    } 
    } 
    return true; 
} 

private class ScaleListener extends 
     ScaleGestureDetector.SimpleOnScaleGestureListener { 

    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
     mScaleFactor *= detector.getScaleFactor(); 
     if (detector.isInProgress()) { 
      mFocusX = detector.getFocusX(); 
      mFocusY = detector.getFocusY(); 
     } 
     mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); 
     mScaleMatrix.setScale(mScaleFactor, mScaleFactor, mFocusX, mFocusY); 
     mScaleMatrix.invert(mScaleMatrixInverse); 
     invalidate(); 
     requestLayout(); 

     return true; 
    } 
} 

public void restoreView() { 
    mPosX = 0; 
    mPosY = 0; 
    mFocusX = 0; 
    mFocusY = 0; 
    mScaleFactor = 1; 
    mTranslateMatrix.setTranslate(0, 0); 
    mScaleMatrix.setScale(1, 1); 
    invalidate(); 
} 
} 

Увеличение/Out работает perfectly.The restoreView() фикция используется шоу Показать в первоначальном состоянии и она отлично работает. Но после восстановления в исходном состоянии, щелчок ImageView в представлении не получает совершенно щелчок. Это означает, что цвет не заполняется целым изображением, так как половина цвета заполняется, а половина изображения - с оригинальным цветом.

Что не так или не все что нужно изменить в моем коде?

Заранее спасибо.

ответ

0

Одна вещь, которая кажется немного подозрительной, заключается в том, что вы восстанавливаете две из своих матриц в restoreView, но не в двух других. Разве вы не должны сбросить свои обратные матрицы? Поскольку вы сразу вызываете недействительный, и поскольку это вызовет invalidateChildInParent, который затем отображает точки, я думаю, что это может быть вашей проблемой.

Это классный код, который у вас есть здесь, но вы уверены, что можно переопределить invalidateChildInParent? Есть комментарий, который говорит вам не делать этого. Вы уверены, что нет другого способа трансформировать представления детей? К сожалению, я раньше не делал этого типа кода, поэтому я действительно не знаю, как правильно это сделать. Похоже, вы почти все равно. Удачи.

Смежные вопросы