Error with Android 4.3 ImageView method getImageMatrix ()

I recently upgraded to Android 4.4, and some features of my application suddenly stopped working.

I have this code to initialize, and then a drawing of my user view. The basic idea is that it adjusts the zoom level so that the whole view matches the screen.

private void initAtZoomLevel(float zoomLevel){ .... Matrix transformMatrix = new Matrix(); transformMatrix.setScale(initialZoomLevel, initialZoomLevel); float yTransCenter = (screenHeight - mapHeight)/2.0f; setImageMatrix(transformMatrix); } protected void onDraw(Canvas canvas){ super.onDraw(canvas); float[] values = new float[9]; getImageMatrix().getValues(values); scaleFactor = values[0]; .... } 

THIS WORKS ON ANDROID 4.1.2 AND 4.2.2 DEVICES I HAVE

But on Android 4.4 / 4.3 getImageMatrix().getValues(values) stopped working! It returns an identity matrix instead of the transformation matrix that I expect when the application starts!

DEBUG PRINT-OUT:

4.1.2: @ setImageMatrix(transformMatrix) : transformMatrix = Matrix{[0.025122833, 0.0, 0.0][0.0, 0.025122833, 566.5][0.0, 0.0, 1.0]}

@ getImageMatrix().getValues(values) : transformMatrix = Matrix{[0.025122833, 0.0, 0.0][0.0, 0.025122833, 566.5][0.0, 0.0, 1.0]}

4.4: @ setImageMatrix(transformMatrix) : transformMatrix = Matrix{[0.025122833, 0.0, 0.0][0.0, 0.025122833, 553.0][0.0, 0.0, 1.0]}

@ getImageMatrix().getValues(values) : transformMatrix = Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}

I looked around and I can not find the documentation on this. Somehow the image matrix for my view is reset; Android 4.4 has changed the way we should do this? Anyone else run into this issue?

Note: the problem seems to have occurred on Android 4.3 - the same problem occurs on the emulator

UPDATE: I checked the change log from 4.2 to 4.3 , but there is nothing that I can see above the Matrix class or anything related to the View class.

UPDATE 2: My pinch-to-zoom also doesn't work, which uses the same setImageMatrix() method - and it obviously doesn't stick because nothing happens in getImageMatrix().getValues()

+6
source share
2 answers

Although my previous answer describes a general problem, it may not really be a mistake. As stated in the Generic Holiday Name, mDrawMatrix must be installed in mMatrix in the configureBounds() method, which will fix this problem / error / independently.

HOWEVER, I had to add a few lines of code to actually configureBounds() :

 private void configureBounds() { if (mDrawable == null || !mHaveFrame) { return; } int dwidth = mDrawableWidth; int dheight = mDrawableHeight; ... if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) { /* If the drawable has no intrinsic size, or we're told to scaletofit, then we just fill our entire view. */ mDrawable.setBounds(0, 0, vwidth, vheight); mDrawMatrix = null; } else { //here the where mDrawMatrix == mMatrix IF using scaleType.MATRIX ... } } 

So, in order to actually make it work the way I expect, from 4.2 and below you need to make sure:

  • mDrawable != null . Previously, this was not a problem, but for my case, I did not use drawable, so everything failed (the return immediately got into the game)
  • 'dwidth >0 && dheight >0 . This is not a problem if you have a real resource, but, as I said, I did not.
  • mHaveFrame = true . I had no idea what it was - never used it. The only way to set this value is to call setFrame(int, int, int, int) .

To run my scaling code again, I had to add the following:

  //potentially a fix for the "bug" that appears in Android 4.3+ //mDrawable cannot be null anymore for getImageMatrix to work---stupid //therefore the imageview class MUST set a drawable for matrix scaling to work //so here I am using a "empty" drawable to get around this ShapeDrawable fakeDrawable = new ShapeDrawable(); //so mDrawable != null fakeDrawable.setIntrinsicHeight(1); //so dwidth and dheight are > 0 fakeDrawable.setIntrinsicWidth(1); setImageDrawable(fakeDrawable); setFrame(0, 0, viewWidth, viewHeight); //setting a frame so mHaveFrame = true 

Yikes

0
source

I found what I consider a problem. I took a look at the source code for ImageView and found that setImageMatrix(Matrix matrix) stores the matrix in a different field, which returns getImageMatrix() ...

Android 4.4 ImageView

 public void setImageMatrix(Matrix matrix) { // collaps null and identity to just null if (matrix != null && matrix.isIdentity()) { matrix = null; } // don't invalidate unless we're actually changing our matrix if (matrix == null && !mMatrix.isIdentity() || matrix != null && !mMatrix.equals(matrix)) { mMatrix.set(matrix); configureBounds(); invalidate(); } } 

Here the matrix is ​​stored in the mMatrix field

 public Matrix getImageMatrix() { if (mDrawMatrix == null) { //<-- should be mMatrix == null return new Matrix(Matrix.IDENTITY_MATRIX); } return mDrawMatrix; //<-- NOT THE RIGHT FIELD TO RETURN } 

While getImageMatrix() returns mDrawMatrix ...

Android 4.1.2 ImageView

 public Matrix getImageMatrix() { return mMatrix; } public void setImageMatrix(Matrix matrix) { // collaps null and identity to just null if (matrix != null && matrix.isIdentity()) { matrix = null; } // don't invalidate unless we're actually changing our matrix if (matrix == null && !mMatrix.isIdentity() || matrix != null && !mMatrix.equals(matrix)) { mMatrix.set(matrix); configureBounds(); invalidate(); } } 

both methods use the same field - mMatrix

So there the problem is right ... suddenly getImageMatrix() returns the wrong field ...

+2
source

Source: https://habr.com/ru/post/959498/


All Articles