返回

剖析 ImageView 的源码,一览其像素级的艺术创作奥秘

Android

ImageView 在安卓应用程序开发中的位图绘制之旅

加载位图

ImageView 组件是安卓应用程序开发中展示图像数据的重要组件。它允许开发者从本地存储或互联网加载位图(图像数据集合)并将其显示在应用程序中。setImageBitmap() 方法是加载位图的关键入口,接受一个 Bitmap 参数,包含要加载到 ImageView 中的像素数据。

public void setImageBitmap(Bitmap bitmap) {
    ...
    if (bitmap != null && !bitmap.isRecycled()) {
        setImageBitmap(bitmap);
        imageMatrix = null;
        invalidate();
    }
}

首先,该方法检查传入的位图是否有效,然后将它分配给 ImageView 的内部位图变量。它还清空 imageMatrix(位图转换信息),并调用 invalidate() 重新绘制组件。

转换位图

setImageMatrix() 方法用于转换 ImageView 中的位图。它接受一个 Matrix 参数,包含平移、旋转和缩放等转换详细信息。

public void setImageMatrix(Matrix matrix) {
    ...
    if (!object.equals(mImageMatrix)) {
        mImageMatrix = matrix;
        invalidate();
    }
}

该方法检查传入的转换矩阵与当前矩阵是否不同,如果不同,则更新内部 mImageMatrix 并调用 invalidate() 重新绘制。

绘制位图

onDraw() 回调方法中绘制位图,该方法在 ImageView 需要重新绘制时调用。

protected void onDraw(Canvas canvas) {
    ...
    if (mBitmap != null) {
        drawBitmap(canvas);
    }
}

private void drawBitmap(Canvas canvas) {
    ...
    float[] values = new float[9];
    mImageMatrix.getValues(values);

    float scaleX = values[Matrix.MSCALEX];
    float scaleY = values[Matrix.MSCALEY];
    float transX = values[Matrix.MTRANSX];
    float transY = values[Matrix.MTRANSY];

    if (scaleX != 1 || scaleY != 1 || transX != 0 || transY != 0) {
        canvas.save();
        canvas.concat(mImageMatrix);
        canvas.drawBitmap(mBitmap, 0, 0, mBitmap.density, null);
        canvas.restore();
    } else {
        canvas.drawBitmap(mBitmap, 0, 0, mBitmap.density, null);
    }
}

onDraw() 方法检查位图是否存在,如果存在,则调用 drawBitmap() 方法进行绘制。drawBitmap() 方法获取转换矩阵的值,如果这些值不等于单位矩阵(没有缩放、旋转或平移),它将变换画布并应用转换矩阵。然后,它将位图绘制到画布上,并通过传递位图的密度作为附加参数来确保正确的显示。

常见问题解答

1. ImageView 中如何加载本地位图?

通过调用 setImageResource() 方法并提供本地资源 ID。

2. ImageView 中如何应用滤镜?

使用 setColorFilter() 方法应用 ColorFilter 对象。

3. 如何裁剪 ImageView 中的位图?

使用 setImageBitmap() 方法加载位图,并调用 setScaleType() 方法将其设置为 CENTER_CROP

4. 如何让位图在 ImageView 中适应大小?

使用 setScaleType() 方法将其设置为 FIT_XYFIT_CENTER

5. 如何获取 ImageView 中位图的像素数据?

通过调用 getPixelCopy() 方法并将结果复制到一个 Bitmap 对象中。