【问题标题】:Using a rounded corners drawable使用圆角drawable
【发布时间】:2012-12-16 01:27:42
【问题描述】:

有一个由流行的 Google 开发人员 Romain Guy 制作的 nice post,它展示了如何在视图上有效地使用圆角 drawable(在 his code 中称为“StreamDrawable”)。

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

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

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

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

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

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

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

如何解决这些问题并使用这个出色的代码?

【问题讨论】:

  • 你应该对那篇文章发表评论或联系他在这里回答。
  • 问题解决了吗?
  • 现在,没有。但是您可以使用缩放位图的解决方法。不是最好的东西,但如果你时间不够,你可以使用它。
  • 由于在某些时候位图需要以不同于您开始的任何大小(即调整大小)的大小绘制,我认为我不会考虑手动调整它的大小解决方法/破解。这只是低级。要么你做,要么图书馆做。
  • 这是不正确的,因为它使用的内存超出了您的需要。当您创建一个新的缩放位图时,您可以同时拥有 2 个位图。相反,如果您已经有了位图,您只需通过仅采样您需要的内容来绘制您需要的内容。既然 drawable 已经做了一些特殊的绘图,为什么不也有这个呢?甚至可以使用 GPU 来完成这项任务。另一件事是,如果你有图像文件,你将无法使用 WRAP_CONTENT 因为你想自己设置大小。

标签: android rounded-corners android-drawable


【解决方案1】:

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

也许这对你也有帮助:

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

2) 覆盖另外两个方法:

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

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

最好的问候, 达罗拉

【讨论】:

  • 不,它没有帮助,顺便说一句,如果您只需要位图的宽度和高度,您可以存储它们并将它们设置在 CTOR 中。
  • @DaRolla 感谢您指出这一点,为我节省了很多时间。
【解决方案2】:

潜在的问题是 BitmapShader 的 TileMode 没有缩放选项。您会在源代码中注意到它已设置为 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);
    

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

【讨论】:

  • 这些方法的优缺点是什么?第三个显然既慢又占用更多内存,但是其他的呢?你推荐哪一个?
  • 如果你想让位图拉伸到视图的大小,一些类似于最后的实现几乎是使用BitmapShader时的唯一方法。第一个将限制视图本身的大小,而第二个只会在视图的左上角绘制着色器。
  • 好吧,如果我想让它表现得像一个普通的 imageView,只是它会让图像本身具有圆角呢?
【解决方案3】:

我认为this website 上提出的解决方案效果很好。

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

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

【讨论】:

  • 你能指出它背后的想法(或者我能找到的地方)吗?我真的没有时间阅读整个项目
  • 是的,这个想法很大程度上基于 Romain Guy 在他的网站上展示的内容:curious-creature.org/2012/12/11/…
猜你喜欢
  • 2019-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-23
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
相关资源
最近更新 更多