Фон
Android имеет стандартный ProgressBar со специальной анимацией, когда он неопределен. Существует также множество библиотек с таким количеством видов прогресса, которые доступны ( здесь).
Эта проблема
Во всем, что я искал, я не могу найти способ сделать очень простую вещь:
Имейте градиент от цвета X к цвету Y, который отображается горизонтально, и перемещается по координате X, чтобы цвета до X переходили в цвет Y.
Например (только иллюстрация), если у меня есть градиент синего <-> красного, от края до края, он будет выглядеть следующим образом:
Что я пробовал
Я пробовал некоторые решения, предлагаемые здесь в StackOverflow:
- Изменение горизонтального индикатора хода неопределенного цвета
- Как изменить андроид неопределенный цвет ProgressBar?
- Пользовательский Drawable для ProgressBar/ProgressDialog
- Как изменить цвет прогресса индикатора выполнения в Android
- Как изменить горизонтальный цвет начала и конца начального цвета
но, к сожалению, все они касаются стандартного представления ProgressBar для Android, что означает, что у него есть другой способ показать анимацию рисования.
Я также попытался найти что-то подобное на веб-сайте Android Arsenal, но, несмотря на то, что есть много хороших, я не мог найти такого.
Конечно, я мог бы просто анимировать 2 взгляда, каждый из которых имеет свой собственный градиент (одна противоположность другой), но я уверен, что есть лучший способ.
Вопрос
Можно ли использовать Drawable или анимацию, что делает градиент (или что-то еще) перемещаться таким образом (повторяя, конечно)?
Может быть, просто простирайтесь от ImageView и оживите туда?
Можно ли также установить, какая часть контейнера будет использоваться для повторного рисования? Я имею в виду, что в приведенном выше примере это может быть от синего до красного, так что синий будет по краям, а красный цвет будет посередине.
РЕДАКТИРОВАТЬ:
Хорошо, я немного продвинулся, но я не уверен, что движение в порядке, и я думаю, что он не будет соответствовать скорости, как и следовало бы, в случае, если процессор немного занят, потому что он не учитывает капли кадров. Я сделал, чтобы нарисовать 2 GradientDrawables один рядом с другим, как таковой:
class HorizontalProgressView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val speedInPercentage = 1.5f
private var xMovement: Float = 0.0f
private val rightDrawable: GradientDrawable = GradientDrawable()
private val leftDrawable: GradientDrawable = GradientDrawable()
init {
if (isInEditMode)
setGradientColors(intArrayOf(Color.RED, Color.BLUE))
rightDrawable.gradientType = GradientDrawable.LINEAR_GRADIENT;
rightDrawable.orientation = GradientDrawable.Orientation.LEFT_RIGHT
rightDrawable.shape = GradientDrawable.RECTANGLE;
leftDrawable.gradientType = GradientDrawable.LINEAR_GRADIENT;
leftDrawable.orientation = GradientDrawable.Orientation.RIGHT_LEFT
leftDrawable.shape = GradientDrawable.RECTANGLE;
}
fun setGradientColors(colors: IntArray) {
rightDrawable.colors = colors
leftDrawable.colors = colors
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val widthSize = View.MeasureSpec.getSize(widthMeasureSpec)
val heightSize = View.MeasureSpec.getSize(heightMeasureSpec)
rightDrawable.setBounds(0, 0, widthSize, heightSize)
leftDrawable.setBounds(0, 0, widthSize, heightSize)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save()
if (xMovement < width) {
canvas.translate(xMovement, 0.0f)
rightDrawable.draw(canvas)
canvas.translate(-width.toFloat(), 0.0f)
leftDrawable.draw(canvas)
} else {
//now the left one is actually on the right
canvas.translate(xMovement - width, 0.0f)
leftDrawable.draw(canvas)
canvas.translate(-width.toFloat(), 0.0f)
rightDrawable.draw(canvas)
}
canvas.restore()
xMovement += speedInPercentage * width / 100.0f
if (isInEditMode)
return
if (xMovement >= width * 2.0f)
xMovement = 0.0f
invalidate()
}
}
использование:
horizontalProgressView.setGradientColors(intArrayOf(Color.RED, Color.BLUE))
И результат (он хорошо работает, просто трудно редактировать видео):
Итак, теперь мой вопрос: что мне делать, чтобы он хорошо анимировал, даже если поток пользовательского интерфейса немного занят?
Это просто, что invalidate
не кажется мне надежным способом сделать это в одиночку. Я думаю, он должен проверить больше, чем это. Возможно, он мог бы использовать некоторый API-интерфейс API, с интерполятором.