如何在Android中的Canvas上绘制渐变颜色并改变颜色?

发布于 2024-10-12 16:01:04 字数 303 浏览 2 评论 0原文

我需要将画布的背景绘制为一种颜色并应用阴影/渐变,但每次 onDraw 调用我都希望可能更改颜色。

如果每次 onDraw 调用都创建一个新对象,我将无法做到这一点。有人有什么想法吗?如果我使用drawPaint()并为我的绘画设置一个新的shader(),那么我就创建了一个新的着色器对象,如果我创建一个新的GradientDrawable(),我也有。我想避免GC。

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

有人吗?

I need to paint the background of my Canvas one color with shading/gradient applied, but each onDraw call I would like to potentially change the color.

I am having trouble doing this without creating a new object each onDraw call. Anyone have any ideas? If I use drawPaint() and set a new shader() to my paint, then I have created a new shader object and if I create a new GradientDrawable() I have as well. I want to avoid GC.

I thought I could reuse one GradientDrawable() object and call the .setColor() method, but this just resets any gradient data associated it and paints the drawable as that solid color.

Anyone?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伪心 2024-10-19 16:01:04

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

Unfortunately you have to create a new LinearGradient everytime. Note that you don't have to use a GradientDrawable, you can draw the shape yourself with a Paint on which you set the shader.

晚风撩人 2024-10-19 16:01:04

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

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

I think what you want to do is this. Create a LayerDrawable and then insert two Drawables into it. The first Drawable you insert should have its color set to the color you'd like your background to be and the second should be a Gradient that is set up to be black and transition from alpha 0 to alpha 255.

For more information, see: http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList

变身佩奇 2024-10-19 16:01:04

这个问题在 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,但后来我在设备上启动了 GPU 分析,并使用“在屏幕上作为条形”。一切都很好并且在安全范围内运行。

This question is still valid almost in the middle of 2017. I wanted to create a smooth transition for color changes for my custom view. I used shaders with LinearGradients.

My intention was to make a smooth transition betweeen anabled and disabled state of my view.

My case is even more complicated due to construction and purpose of the view. It's a slider. So my view consists of almost 2 identical layers drawn one on top of the second one using canvas. Third element is a pointer.

Both layers use LinearGradients, pointer use a single color.

Summing all I have to do a transition between 5 colors at the same time:

  • start and end color for bottom layer - one LinearGradient,
  • start and end color for top layer - second LinearGradient,
  • pointer color - normal color;

Solution to this is to have 5 separate ValueAnimators. The most important thing is to use 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();

I also was concerned at start about creating a new LinearGradient on each animation update but then I launched GPU profiling on device with "On screen as bars". Everything is fine and running within safe margin.

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