gpt4 book ai didi

android - 如何创建一个重复的动画移动渐变drawable,就像一个不确定的进度?

转载 作者:IT老高 更新时间:2023-10-28 23:07:02 28 4
gpt4 key购买 nike

背景

Android 有一个标准的 ProgressBar,当不确定时有一个特殊的动画。还有很多可用的各种进度 View 库(here)。

问题

在我搜索的所有内容中,我找不到做一件非常简单的事情的方法:

有一个从 X 色到 Y 色的渐变,水平显示,并在 X 坐标中移动,这样 X 之前的颜色就会变为 Y 色。

例如(只是一个插图),如果我有一个蓝色渐变<->红色,从边缘到边缘,它会这样:

enter image description here

我尝试过的

我已经尝试过 StackOverflow 上提供的一些解决方案:

但遗憾的是,它们都是关于 Android 的标准 ProgressBar View ,这意味着它以不同的方式显示可绘制对象的动画。

我也尝试在 Android Arsenal 网站上找到类似的东西,但即使有很多不错的东西,我也找不到这样的东西。

当然,我可以自己制作 2 个 View 的动画,每个 View 都有自己的渐变(一个与另一个相反),但我相信还有更好的方法。

问题

是否可以使用 Drawable 或它的动画,使渐变(或其他任何东西)以这种方式移动(当然是重复)?

也许只是从 ImageView 扩展并在那里为 drawable 设置动画?

是否也可以设置容器的多少将用于重复绘制?我的意思是,在上面的例子中,它可能是从蓝色到红色,所以蓝色会在边缘,红色会在中间。


编辑:

好的,我已经取得了一点进展,但是我不确定运动是否正常,并且我认为它的速度不会像它应该的那样一致,以防 CPU 有点忙,因为它不考虑丢帧。我所做的是一个接一个地绘制 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))

结果(它确实循环良好,只是很难编辑视频):

enter image description here

所以我现在的问题是,我应该怎么做才能确保它的动画效果很好,即使 UI 线程有点忙?

只是 invalidate 对我来说似乎不是一种可靠的方法,独自一人。我认为它应该检查更多。也许它可以使用一些动画 API 来代替 interpolator 。

最佳答案

我决定将“pskink”答案放在 Kotlin 中(来源 here)。我在这里写它只是因为其他解决方案要么不起作用,要么是解决方法而不是我所询问的。

class ScrollingGradient(private val pixelsPerSecond: Float) : Drawable(), Animatable, TimeAnimator.TimeListener {
private val paint = Paint()
private var x: Float = 0.toFloat()
private val animator = TimeAnimator()

init {
animator.setTimeListener(this)
}

override fun onBoundsChange(bounds: Rect) {
paint.shader = LinearGradient(0f, 0f, bounds.width().toFloat(), 0f, Color.WHITE, Color.BLUE, Shader.TileMode.MIRROR)
}

override fun draw(canvas: Canvas) {
canvas.clipRect(bounds)
canvas.translate(x, 0f)
canvas.drawPaint(paint)
}

override fun setAlpha(alpha: Int) {}

override fun setColorFilter(colorFilter: ColorFilter?) {}

override fun getOpacity(): Int = PixelFormat.TRANSLUCENT

override fun start() {
animator.start()
}

override fun stop() {
animator.cancel()
}

override fun isRunning(): Boolean = animator.isRunning

override fun onTimeUpdate(animation: TimeAnimator, totalTime: Long, deltaTime: Long) {
x = pixelsPerSecond * totalTime / 1000
invalidateSelf()
}
}

用法:

MainActivity.kt

    val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200f, resources.getDisplayMetrics())
progress.indeterminateDrawable = ScrollingGradient(px)

activity_main.xml

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"
tools:context=".MainActivity">

<ProgressBar
android:id="@+id/progress" style="?android:attr/progressBarStyleHorizontal" android:layout_width="200dp"
android:layout_height="20dp" android:indeterminate="true"/>
</LinearLayout>

关于android - 如何创建一个重复的动画移动渐变drawable,就像一个不确定的进度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48520655/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com