使用 Alpha 的最佳实践

发布于 2024-08-23 23:50:00 字数 2765 浏览 13 评论 0

Alpha 是图形界面开发中常用的特效,通常我们会使用以下代码来实现 Alpha 特效:

view.setAlpha(0.5f);
View.ALPHA.set(view, 0.5f);
ObjectAnimator.ofFloat(view, "alpha", 0.5f).start();
view.animate().alpha(0.5f).start();
view.setAnimation(new AlphaAnimation(1.0f, 0.5f));

其效果都等同于:

canvas.saveLayer(l, r, t, b, 127, Canvas.CLIP_TO_LAYER_SAVE_FLAG);

所以常见的 alpha 特效是通过将图像绘制到 offscreen buffer 中然后显示出来,这样的操作是非常消耗资源的,甚至可能导致性能问题,在开发过程中我们可以通过其他方式避免创建 offsreen buffer。

TextView

对于 TextView 我们通常需要文字透明效果,而不是 View 本身透明,所以,直接设置带有 alpha 值的 TextColor 是比较高效的方式。

 // Not this
textView.setAlpha(alpha);

// 以下方式可以避免创建 offscreen buffer
int newTextColor = (int) (0xFF * alpha) << 24 | baseTextColor & 0xFFFFFF;
textView.setTextColor(newTextColor);

ImageView

同样的对于只具有 src image 的 ImageView,直接调用 setImageAlpha() 方法更为合理。

// Not this, setAlpha 方法由 View 继承而来,性能不佳
imageView.setAlpha(0.5f);

// 使用以下方式时,ImageView 会在绘制图片时单独为图片指定 Alpha
// 可以避免创建 offScreenBuffer
imageView.setImageAlpha((int) alpha * 255);

CustomView

类似的,自定义控件时,应该直接去设置 paint 的 alpha。

// Not this
customView.setAlpha(alpha);

// But this
paint.setAlpha((int) alpha * 255);
canvas.draw*(..., paint);

同时 Android 提供了 hasOverlappingRendering() 接口,通过重写该接口可以告知系统当前 View 是否存在内容重叠的情况,帮助系统优化绘制流程,原理是这样的:对于有重叠内容的 View,系统简单粗暴的使用 offscreen buffer 来协助处理。当告知系统该 View 无重叠内容时,系统会分别使用合适的 alpha 值绘制每一层。

/**
 * Returns whether this View has content which overlaps. This function, intended to be
 * overridden by specific View types, is an optimization when alpha is set on a view. If
 * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
 * and then composited it into place, which can be expensive. If the view has no overlapping
 * rendering, the view can draw each primitive with the appropriate alpha value directly.
 * An example of overlapping rendering is a TextView with a background image, such as a
 * Button. An example of non-overlapping rendering is a TextView with no background, or
 * an ImageView with only the foreground image. The default implementation returns true;
 * subclasses should override if they have cases which can be optimized.
 *
 * @return true if the content in this view might overlap, false otherwise.
 */
public boolean hasOverlappingRendering() {
    return true;
}

最后引用 Chet Haase 的一句话作为总结:

You know what your view is doing, so do the right thing for your situation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

深者入戏

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文