【问题标题】:Draw transparent gradient with alpha transparency from 0 to 1用 0 到 1 的 alpha 透明度绘制透明渐变
【发布时间】:2012-12-19 18:34:01
【问题描述】:

我在 Android 中有一个动态生成的位图,我想从顶部边缘羽化,这样边界区域将在顶部完全透明,并逐渐变为稍微低于完全不透明。

创建一个完全透明的顶部边缘

transparentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
transparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
Shader shader = new LinearGradient(0, 0, 0, 20,
                    Color.TRANSPARENT, Color.TRANSPARENT, Shader.TileMode.CLAMP);
transparentPaint.setShader(shader);
// the bitmap is dynamically generated beforehand
Canvas c = new Canvas(bitmap);
c.drawRect(0, 0, bitmapWidth, 20, transparentPaint);

Alpha 渐变而不是完全透明的孔?

你将如何实现这样的目标:

[在这种情况下只是顶部边缘]

【问题讨论】:

  • 刚刚注意到你的线性渐变是完全透明的,它使用相同的颜色作为开始和结束
  • @Lumis 是的,这正是问题所在,我可以使用提供的代码创建一个完全透明的边缘,但不能创建如图所示的 alpha 渐变 - 怎么做?
  • 你必须在顶部使用任何颜色,比如 Color.BLACK 然后尝试各种 xFermodes

标签: java android graphics bitmap gradient


【解决方案1】:

看看这个例子:Make certain area of bitmap transparent on touch

这是一种使用渐变绘制的方法:

Paint framePaint = new Paint();
for(int i = 1; i < 5; i++){
   setFramePaint(framePaint, i, imageW, imageH);
   myCanvas.drawPaint(framePaint);
}

...

private void setFramePaint(Paint p, int side, float iw, float ih){
                // paint, side of rect, image width, image height

                p.setShader(null);
                p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

                float borderSize = 0.1f; //relative size of border
                //use the smaller image size to calculate the actual border size
                float bSize = (iw > ih)? ih * borderSize: ih * borderSize; 
                float g1x = 0;
                float g1y = 0;
                float g2x = 0;
                float g2y = 0;
                int c1 = 0, c2 = 0;

                if (side == 1){
                    //left
                    g1x = 0;
                    g1y = ih/2;
                    g2x = bSize;
                    g2y = ih/2;
                    c1 = Color.TRANSPARENT;
                    c2 = Color.BLACK;

                }else if(side == 2){
                    //top
                    g1x = iw/2;
                    g1y = 0;
                    g2x = iw/2;
                    g2y = bSize;
                    c1 = Color.TRANSPARENT;
                    c2 = Color.BLACK;


                }else if(side == 3){
                    //right
                    g1x = iw;
                    g1y = ih/2;
                    g2x = iw - bSize;
                    g2y = ih/2;
                    c1 = Color.TRANSPARENT;
                    c2 = Color.BLACK;


                }else if(side == 4){
                    //bottom
                    g1x = iw/2;
                    g1y = ih;
                    g2x = iw/2;
                    g2y = ih - bSize;
                    c1 = Color.TRANSPARENT;
                    c2 = Color.BLACK;
                }

                p.setShader(new LinearGradient(g1x, g1y, g2x, g2y, c1, c2, Shader.TileMode.CLAMP));

            }

【讨论】:

  • 这会产生 alpha 渐变吗?而不是我已经拥有的完全透明的边缘?
  • 这里的想法是,您可以创建一个黑色模糊圆角矩形,略小于图像选择,然后使用 xFermode 将创建透明边缘。您的解决方案的问题是角落将被处理两次,并且不会被圆角。模糊的矩形是一个蒙版,如果您对蒙版的形状感到满意,那么最终的结果应该看起来不错。我在 FireWorks 或 PhotoShop 中创建了一些蒙版,然后在我的应用程序中调整了它们的大小,而其他的则由代码生成。
  • 我还没有测试过代码,但我现在明白你的意思了 - 谢谢,这应该可以工作!
  • 实际上,经过几个小时的工作,我发现如果您不想创建单独的位图来创建这种效果,那么使用透明渐变的想法是最好的。例如,如果您将图像加载到位图中,然后使用 DEST_IN 应用此绘制,它就可以工作。对于模糊的矩形,它有点复杂。检查编辑
  • 非常感谢您回来分享您的发现!如果可以的话,我会给予更多的支持!
【解决方案2】:

如果您可以接受白色边缘而不是透明边缘,请尝试 SCREEN 模式。在PorterDuff.Mode.SCREEN 模式下,白色像素保持白色,黑色像素变得不可见。创建一个覆盖位图,其中边缘是白色的,中间是黑色的,并将其与您的图像混合。这将创建一个位图,其中白色边缘淡入照片中间。

【讨论】:

  • 我会接受这个作为答案,但我确实需要完全透明的边缘而不是外面的白色边缘..
【解决方案3】:

Romain Guy 使用了与你想要实现的效果非常相似的淡入淡出,只是他除了this effect之外还添加了圆角

【讨论】:

  • 我在您提供的链接中没有看到任何 alpha 渐变?问题是图像逐渐淡出,没有清晰的边缘..
  • 您是否尝试过示例应用程序并看到原始图像与显示的图像相比?我可能是错的,但它看起来是相同(或相似)的效果。
  • 没有检查示例应用程序,因为我认为链接中显示的图像将代表该应用程序 - 如果 lumis 答案不起作用,请查看。谢谢!
  • 是的,也尝试禁用圆角,这样效果会更明显......
猜你喜欢
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 2012-08-02
  • 2011-02-07
  • 2013-03-13
相关资源
最近更新 更多