如何在Canvas中使用颜色变化在Android中绘制渐变颜色?

时间:2011-01-18 23:28:53

标签: android canvas gradient shader

我需要使用阴影/渐变来绘制我的Canvas一种颜色的背景,但是每次onDraw调用我都希望改变颜色。

我无法在每次onDraw调用时创建新对象时遇到此问题。有人有主意吗?如果我使用drawPaint()并为我的绘画设置一个新的着色器(),那么我创建了一个新的着色器对象,如果我创建一个新的GradientDrawable(),我也有。我想避免GC。

我以为我可以重用一个GradientDrawable()对象并调用.setColor()方法,但这只会重置与之关联的任何渐变数据,并将drawable绘制为纯色。

任何?

3 个答案:

答案 0 :(得分:6)

不幸的是,您每次都必须创建一个新的LinearGradient。请注意,您不必使用GradientDrawable,您可以使用您在其上设置着色器的Paint绘制形状。

答案 1 :(得分:0)

我想你想做的就是这个。创建一个LayerDrawable,然后将两个Drawables插入其中。你插入的第一个Drawable应该将其颜色设置为你想要的背景颜色,第二个应该是一个设置为黑色并从alpha 0过渡到alpha 255的渐变颜色。

有关详细信息,请参阅:http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList

答案 2 :(得分:0)

这个问题几乎在2017年中期仍然有效。我想为我的自定义视图创建一个平滑的颜色变化过渡。我使用了使用LinearGradients的着色器。

我的目的是在我的观点的平静状态和禁用状态之间平稳过渡。

由于视图的构造和目的,我的情况更加复杂。这是一个滑块。因此,我的视图包含几乎2个相同的图层,使用画布在第二个图层的顶部绘制。第三个元素是指针。

两个图层都使用LinearGradients,指针使用单一颜色。

总结我必须同时在5种颜色之间进行过渡:

  • 底层的开始和结束颜色 - 一个LinearGradient,
  • 顶层的开始和结束颜色 - 第二个LinearGradient,
  • 指针颜色 - 正常颜色;

解决方案是拥有5个独立的ValueAnimators。最重要的是使用ValueAnimator.ofArgb():

private ValueAnimator frontStartColorAnimator;
private ValueAnimator frontEndColorAnimator;
private ValueAnimator bottomStartColorAnimator;
private ValueAnimator bottomEndColorAnimator;
private ValueAnimator pointerColorAnimator;
private AnimatorSet colorsAnimatorSet;

...

frontStartColorAnimator = ValueAnimator.ofArgb(frontLayerStartColor, frontLayerDisabledStartColor);
frontStartColorAnimator.setDuration(animationDuration);
frontStartColorAnimator.setInterpolator(new LinearInterpolator());
frontStartColorAnimator.addUpdateListener(animation
            -> shaderFrontLayerStartColor = (int) animation.getAnimatedValue());

frontEndColorAnimator = ValueAnimator.ofArgb(frontLayerEndColor, frontLayerDisabledEndColor);
frontEndColorAnimator.setDuration(animationDuration);
frontEndColorAnimator.setInterpolator(new LinearInterpolator());
frontEndColorAnimator.addUpdateListener(animation -> {
        shaderFrontLayerEndColor = (int) animation.getAnimatedValue();
        frontLayerPaint.setShader(new LinearGradient(0, 0, getWidth(), 0, shaderFrontLayerStartColor,
                shaderFrontLayerEndColor, Shader.TileMode.CLAMP));
    });

bottomStartColorAnimator = ValueAnimator.ofArgb(bottomLayerStartColor, bottomLayerDisabledStartColor);
bottomStartColorAnimator.setDuration(animationDuration);
bottomStartColorAnimator.setInterpolator(new LinearInterpolator());
bottomStartColorAnimator.addUpdateListener(animation ->
            shaderBottomLayerStartColor = (int) animation.getAnimatedValue());

bottomEndColorAnimator = ValueAnimator.ofArgb(bottomLayerEndColor, bottomLayerDisabledEndColor);
bottomEndColorAnimator.setDuration(animationDuration);
bottomEndColorAnimator.setInterpolator(new LinearInterpolator());
bottomEndColorAnimator.addUpdateListener(animation -> {
        shaderBottomLayerEndColor = (int) animation.getAnimatedValue();
        backLayerPaint.setShader(new LinearGradient(0, 0, 0, getHeight(), shaderBottomLayerStartColor,
                shaderBottomLayerEndColor, Shader.TileMode.CLAMP));
    });

pointerColorAnimator = ValueAnimator.ofArgb(pointerEnabledColor, pointerDisabledColor);
pointerColorAnimator.setDuration(animationDuration);
pointerColorAnimator.setInterpolator(new LinearInterpolator());
pointerColorAnimator.addUpdateListener(animation -> {
        pointerColor = (int) animation.getAnimatedValue();
        pointerPaint.setColor(pointerColor);
    });

colorsAnimatorSet = new AnimatorSet();
colorsAnimatorSet.playTogether(frontStartColorAnimator, frontEndColorAnimator,
            bottomStartColorAnimator, bottomEndColorAnimator, pointerColorAnimator);

...

colorsAnimatorSet.start();

我还开始关注在每次动画更新时创建一个新的LinearGradient,然后我在设备上使用“On screen as bars”启动了GPU分析。一切都很好,在安全范围内运行。