首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何设置RadialGradient的大小、位置和颜色,或者在GradientDrawable上设置XferMode

如何设置RadialGradient的大小、位置和颜色,或者在GradientDrawable上设置XferMode
EN

Stack Overflow用户
提问于 2016-10-25 04:47:08
回答 1查看 228关注 0票数 2

这是我在Stackoverflow上的第一个问题,所以别问我了。我试着在一个点周围画一个放射状的布隆效果,找到了RadialGradient,以及GradientDrawable。然而,这两种方法都没有给出完整的解决方案。

这就是我现在画画的方式:

代码语言:javascript
复制
//global
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
Paint mainP = new Paint();
Paint whiteP = new Paint();
whiteP.setColor(Color.WHITE);
RadialGradient gradient;

// in a drawing method with a canvas
gradient = new RadialGradient((int) x, (int) y, tempRadius, mainP.getColor(),
    0x00000000, Shader.TileMode.CL
mainP.setShader(gradient);
mainP.setXfermode(xferMode);

canvas.drawCircle((int) x, (int) y, tempRadius, mainP);

gradient = new RadialGradient((int) x, (int) y, tempRadius/2, whiteP.getColor(),
      0x00000000, Shader.TileMode.CLAMP);
whiteP.setXfermode(xferMode);
whiteP.setShader(gradient);

canvas.drawCircle((int) x, (int) y, tempRadius/2, whiteP);    

这将得到预期的结果:

Screenshot

然而,新的RadialGradient会在内存中构建每个点的每一帧。这显然是后来的一个问题。该类中唯一公开的东西是构造函数,所以每次需要新的大小、位置或颜色时,都可以使用RadialGradient创建一个新的构造函数。我想这样做的原因是因为您将渐变指定给要绘制它的Paint对象,这允许您使用它的setXferMode()。

另一种方法是使用GradientDrawable,只允许创建其自身的一个实例,因此可以更改大小、位置和颜色,但它用于绘制自身的Paint对象是私有的,因此不能在其上设置XferMode。这是必要的,这样如果你有多个点,它们就不会相互覆盖。它有一个colorfilter,但看起来colorfilter并不关心目的地,只关心指定的颜色和源。

因为我是新人,所以我只能发布两个链接,而不是只发布两张图片,我会链接回我在reddit上写的同一个问题,其中有所有的图片作为上下文。(还没有答案,这就是我来这里的原因,哈哈)

https://www.reddit.com/r/learnandroid/comments/590uce/having_a_shader_issue_using_radialgradient_and/

所以,应该如何做,我知道我需要一个类或另一个类。据我所知,如果我不需要每次需要不同的大小、位置或颜色时都创建一个新的RadialGradient,那就太好了。GradientDrawable同样很棒,因为你可以只有一个实例,但是我需要能够在它使用的画图上设置XferMode。有没有另外一个类,或者我在这两个类之间遗漏了什么?

谢谢!!

EN

回答 1

Stack Overflow用户

发布于 2016-10-28 13:45:31

因此,虽然我确实找到了解决方案,但它仍然导致了更多的问题。我找到的解决方案部分是here。它唯一缺少的是能够更改预先分配的RadialGradient位图的颜色。所以我想出了这个:

代码语言:javascript
复制
// Global
int tempRadius;
Paint p = new Paint();
RadialGradient gradient;    
Bitmap circleBitmap = Bitmap.createBitmap((int) (tempRadius * 2.0f), (int) (tempRadius * 2.0f),
Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(circleBitmap);
Rect gradBMPRect = new Rect(0,0,200,200);
Rect destRect = new Rect();
int[] hsv = {0,1,1};
PorterDuffColorFilter[] myColors = new PorterDuffColorFilter[360];
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);


// Initialize
gradient = new RadialGradient(tempRadius, tempRadius, tempRadius, Color.WHITE, 0x00000000, Shader.TileMode.CLAMP);
circleBitmap = Bitmap.createBitmap((int) (100 * 2.0f), (int) (100 * 2.0f),
Bitmap.Config.ARGB_8888);
tempCanvas = new Canvas(circleBitmap);
for(int i = 0; i < 360; i++){
  hsv[0] = i;
  myColors[i] = new PorterDuffColorFilter(Color.HSVtoColor(hsv), PorterDuff.Mode.MULTIPLY)
}

// update/draw
p.setDither(true);
p.setShader(gradient);
tempCanvas.drawCircle(100, 100, 100, p);
p.setXfermode(xferMode);


if(p.getColor() != mainP.getColor()) {
p.setColorFilter(myColors[hue]);
p.setColor(mainP.getColor());

destRect.set((int)x-tempRadius,(int)y-tempRadius,(int)x+tempRadius,(int)y+tempRadius);
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p);

p.setColorFilter(null);
destRect.set((int)x-(tempRadius/2),(int)y-(tempRadius/2),(int)x+(tempRadius/2),(int)y+(tempRadius/2));
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p);

使用RadialGradient创建灰度位图,然后使用HSVtoColor制作360 PorterDuffColorFilters的调色板。所有360的模式都设置为正片相乘。当绘制这些时,用于绘制位图的颜料被设置为使用由其色调指定的ColorFilter。colorfilter将灰度位图着色为滤镜的任何颜色。并且没有更多的内存泄漏:)

然而,与使用RadialGradient渲染圆形相比,渲染RadialGradient的位图需要更长的时间。对于30个圆圈,我的Galaxy S5每帧绘制需要15-20毫秒,而位图大约需要30-35毫秒。不过,只要多做一点工作和进行一些调整,就可以解决这个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40227269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档