13

流行的 Google 开发人员Romain Guy发表了一篇不错的文章,展示了如何在视图上有效地使用圆角可绘制对象(在他的代码中称为“StreamDrawable” )。

该示例在我的 Galaxy S3 纵向模式下运行良好,但我有一些问题:

  1. 如果屏幕很小(例如在 qvga 屏幕上),显示的图像会被裁剪。

  2. 如果我的输入位图比我希望的显示方式太小,则输出图像的边缘会被涂抹。即使在 Galaxy S3 上,当您运行示例代码并且它在横向上时,它看起来也很糟糕:

    在此处输入图像描述

  3. 我仍然不确定(因为我使用缩放图像的解决方法来使用示例代码),但它认为即使是这个解决方案在 listView 中使用时也会有点慢。也许有一个渲染脚本解决方案?

我使用 setImageDrawable 还是 setBackgroundDrawable 都没有关系。它必须是可绘制对象本身的东西。

我尝试使用变量和位图着色器,但没有任何效果。遗憾的是, TileMode并没有仅仅拉伸图像的价值,只能以某种方式平铺它。

作为一种解决方法,我可以创建一个新的缩放位图,但这只是一种解决方法。当然有一种更好的方法,它也不会使用比它应该使用的更多的内存。

我如何解决这些问题并使用这个很棒的代码?

4

3 回答 3

10

我认为本网站上提供的解决方案效果很好。

与其他解决方案不同,它不会导致内存泄漏,即使它基于 Romain Guy 的解决方案。

编辑:现在在支持库上,您还可以使用RoundedBitmapDrawable(使用RoundedBitmapDrawableFactory)。

于 2013-09-14T20:48:28.500 回答
4

我对这段代码有一些大小问题,我解决了。

也许这也会对您有所帮助:

1) 在构造函数中将位图存储在局部变量中(例如私有位图 bmp;)

2)覆盖另外两个方法:

@Override
    public int getIntrinsicWidth() {
    return bmp.getWidth();
}

@Override
    public int getIntrinsicHeight() {
    return bmp.getHeight();
}

最好的问候,达罗拉

于 2013-01-07T16:23:52.443 回答
1

潜在的问题是 BitmapShaderTileMode没有缩放选项。您会在源代码中注意到它已设置为Shader.TileMode.CLAMP,并且文档将其描述为:

如果着色器在其原始边界之外绘制,则复制边缘颜色

要解决此问题,有以下三种解决方案:

  1. 将使用可绘制对象的视图的大小限制为位图的大小。
  2. 约束绘图区域;例如,更改:

    int width = bounds.width() - mMargin;
    int height = bounds.height() - mMargin;
    mRect.set(mMargin, mMargin, width, height);
    

    到:

    int width = Math.min(mBitmap.getWidth(), bounds.width()) - mMargin;
    int height = Math.min(mBitmap.getHeight(), bounds.height()) - mMargin;
    mRect.set(mMargin, mMargin, width, height);
    
  3. 将位图缩放到可绘制对象的大小。我已将创建着色器移至 onBoundsChange() 并选择从此处创建新位图:

    bitmap = Bitmap.createScaledBitmap(mBitmap, width, height, true);
    mBitmapShader = new BitmapShader(bitmap,
            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    

    请注意,这是一个可能很慢的操作,将在主线程上运行。在选择最后一个解决方案之前,您可能需要仔细考虑如何实现它。

于 2013-07-19T10:19:21.693 回答