Как нарисовать цвет градиента в Android на холсте с изменением цвета? - PullRequest
9 голосов
/ 19 января 2011

Мне нужно покрасить фон моего Canvas одним цветом с применением затенения / градиента, но при каждом вызове onDraw я хотел бы потенциально изменить цвет.

У меня проблемы с выполнением этого без создания нового объектакаждый вызов onDraw.У кого-нибудь есть идеи?Если я использую drawPaint () и устанавливаю новый шейдер () для своей краски, то я создаю новый объект шейдера, и если я создаю новый GradientDrawable (), у меня тоже есть.Я хочу избежать GC.

Я думал, что смогу повторно использовать один объект GradientDrawable () и вызвать метод .setColor (), но это просто сбрасывает все связанные с ним данные градиента и рисует нарисованный как этот сплошной цвет.

Кто-нибудь?

Ответы [ 3 ]

6 голосов
/ 19 января 2011

К сожалению, вы должны создавать новый LinearGradient каждый раз. Обратите внимание, что вам не нужно использовать GradientDrawable, вы можете нарисовать фигуру самостоятельно с помощью Paint, на котором вы устанавливаете шейдер.

0 голосов
/ 28 апреля 2017

Этот вопрос все еще действует почти в середине 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 на устройстве с надписью «На экране какбары».Все хорошо и работает в пределах допустимого.

0 голосов
/ 19 января 2011

Я думаю, что вы хотите сделать это.Создайте LayerDrawable, а затем вставьте в него два Drawables.Для первого элемента Drawable, который вы вставляете, его цвет должен соответствовать цвету, который вы хотели бы видеть на своем фоне, а вторым должен быть градиент, настроенный на черный цвет и переход от альфа 0 к альфа 255.

Для получения дополнительной информации см .: http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList

...