Как рисовать градиентный цвет в Android на холсте с изменением цвета?

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

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

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

Кто угодно?

Solutions Collecting From Web of "Как рисовать градиентный цвет в Android на холсте с изменением цвета?"

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

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

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

Этот вопрос все еще действует почти в середине 2017 года. Я хотел создать плавный переход для изменения цвета для своего пользовательского представления. Я использовал шейдеры с LinearGradients.

Мое намерение состояло в том, чтобы сделать плавный переход между автономным и отключенным состоянием моего взгляда.

Мое дело еще сложнее из-за конструкции и цели зрения. Это слайдер. Таким образом, мой взгляд состоит из почти двух одинаковых слоев, нарисованных один поверх второго, используя холст. Третий элемент – это указатель.

Оба слоя используют 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 на устройстве с «On screen as bars». Все в порядке и работает в безопасном месте.