Android 4.3 ImageView方法getImageMatrix()的错误



我最近升级到了Android 4.4,我的应用程序的某些功能令人惊讶地停止了工作。

我有这段代码用于初始化,然后绘制我的自定义视图。其基本思想是调整缩放级别,使整个视图适合屏幕。

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];
    ....
}

这适用于我拥有的ANDROID 4.1.2和4.2.2设备

但在Android 4.4/4.3上,getImageMatrix().getValues(values)停止工作它返回一个单位矩阵,而不是我在应用程序启动时期望的转换矩阵!

调试打印输出:

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]}

我环顾四周,似乎找不到任何有关这方面的文件。不知怎的,我的视图的图像矩阵正在重置;安卓4.4改变了我们应该做的事情吗?有其他人遇到这个问题吗?

注意:问题似乎起源于Android 4.3-在模拟器上运行时也会出现同样的问题

更新:我已经检查了从4.2到4.3的更改日志,但在Matrix类上方没有任何内容,也没有任何与View类相关的内容。

更新2:我的缩放捏也不起作用,它使用了相同的setImageMatrix()方法,而且它显然没有卡住,因为getImageMatrix().getValues() 中没有发生任何事情

我发现了我认为的问题所在。我查看了ImageView的源代码,发现setImageMatrix(Matrix matrix)将矩阵保存在与getImageMatrix()返回的字段不同的字段中。。。

Android 4.4图像视图

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();
    }
}

矩阵存储在字段中mMatrix

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

getImageMatrix()返回mDrawMatrix时

Android 4.1.2图像视图

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();
    }
}

两种方法使用相同的字段-mMatrix

所以问题就在这里——突然间,getImageMatrix()返回了错误的字段。。。

虽然我之前的回答确实概述了整个问题,但事实上它可能不是一个bug。正如Generic Holiday Name所指出的,在configureBounds()方法中,mDrawMatrix应该被设置为mMatrix,这将消除这个问题/bug/anthe。

但是,我必须添加几行代码才能使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's the where mDrawMatrix == mMatrix IF using scaleType.MATRIX
             ...
    }
}

因此,为了真正实现我对4.2及以下版本的预期,您需要确保:

  1. mDrawable != null。这以前不是问题,但在我的情况下,我没有使用drawable,所以一切都失败了(return语句立即命中)
  2. 'dwidth >0 && dheight >0。如果你有一个真正的抽屉,这不是问题,但正如我所说,我没有
  3. mHaveFrame = true。我不知道这是什么-从来没有用过。唯一能将其设置为true的方法是调用setFrame(int, int, int, int)

为了让我的缩放代码再次工作,我必须添加以下内容:

 //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

相关内容

  • 没有找到相关文章

最新更新