Android 如何设置渐变动画?
如何设置从颜色1到颜色2的渐变动画?类似于Android 如何设置渐变动画?,android,animation,gradient,android-custom-view,ondraw,Android,Animation,Gradient,Android Custom View,Ondraw,如何设置从颜色1到颜色2的渐变动画?类似于 我计划将它用作unit的健康栏(因此,它将是以绿色开始,以红色结束的有限动画)在谷歌搜索它时,我发现了两种方法用于android:或扩展视图,使用新着色器(new LinearGradient())。两个答案的作用相同-调用newshader()everyView.onDraw(Canvas Canvas)method的调用。如果此类动画渐变的数量超过~3,则其成本将非常昂贵 所以我用另一种方法。我避免调用neweveryonDraw(),使用单个预
我计划将它用作unit的健康栏(因此,它将是以绿色开始,以红色结束的有限动画)在谷歌搜索它时,我发现了两种方法用于android:或扩展视图,使用
新着色器(new LinearGradient())
。两个答案的作用相同-调用newshader()
everyView.onDraw(Canvas Canvas)
method的调用。如果此类动画渐变的数量超过~3,则其成本将非常昂贵
所以我用另一种方法。我避免调用new
everyonDraw()
,使用单个预先计算的LinearGradient
。这就是它的样子(gif,所以动画衰减):
诀窍是创建LinearGradient
,它比View.getWidth()大colorsCount
倍。之后,您可以在绘制渐变时使用canvas.translate()
要创建渐变,需要当前的宽度和高度。我是在onSizeChanged()中完成的。我还在这里设置了Shader
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = getWidth();
height = getHeight();
LinearGradient gradient = new LinearGradient(
0, height / 2, width * colors.length - 1, height / 2,
colors, null, Shader.TileMode.REPEAT);
fillPaint.setShader(gradient);
shapePath = getParallelogrammPath(width, height, sidesGap);
shapeBorderPath = getParallelogrammPath(width, height, sidesGap);
}
我使用路径,因为平行四边形视图,你可以使用任何你想要的。在执行绘图时,您应该注意两件事:您需要对当前偏移量进行translate()
整个canvas
和offset()
填充形状:
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(-gradientOffset, 0);
shapePath.offset(gradientOffset, 0f, tempPath);
canvas.drawPath(tempPath, fillPaint);
canvas.restore();
canvas.drawPath(shapeBorderPath, borderPaint);
super.onDraw(canvas); // my View is FrameLayout, so need to call it after
}
您还应该使用canvas.save()
&canvas.restore()
。它将保存画布的内部矩阵以进行堆栈并相应地恢复
因此,您需要做的最后一件事是设置gradientOffset
的动画。你想用什么就用什么。我使用了,因为我需要直接控制updateTick
和起始偏移量。以下是我的体会(有点困难和苛刻):
完整的视图
您可以找到的代码我找到了不同的、更短的方法。只需使用setColors(int[]colors)
GradientDrawable的方法
并随时间对其进行动画制作
这是一个如何执行此操作的示例:
val start = Color.DKGRAY
val mid = Color.MAGENTA
val end = Color.BLUE
//content.background is set as a GradientDrawable in layout xml file
val gradient = content.background as GradientDrawable
val evaluator = ArgbEvaluator()
val animator = TimeAnimator.ofFloat(0.0f, 1.0f)
animator.duration = 1500
animator.repeatCount = ValueAnimator.INFINITE
animator.repeatMode = ValueAnimator.REVERSE
animator.addUpdateListener {
val fraction = it.animatedFraction
val newStart = evaluator.evaluate(fraction, start, end) as Int
val newMid = evaluator.evaluate(fraction, mid, start) as Int
val newEnd = evaluator.evaluate(fraction, end, mid) as Int
gradient.colors = intArrayOf(newStart, newMid, newEnd)
}
animator.start()
结果是:
刚刚重写了@Krzysztof Misztal对java
的回答:
public static void startAnimation(final int view, final Activity activity) {
final int start = Color.parseColor("#FDB72B");
final int mid = Color.parseColor("#88FDB72B");
final int end = Color.TRANSPARENT;
final ArgbEvaluator evaluator = new ArgbEvaluator();
View preloader = activity.findViewById(R.id.gradientPreloaderView);
preloader.setVisibility(View.VISIBLE);
final GradientDrawable gradient = (GradientDrawable) preloader.getBackground();
ValueAnimator animator = TimeAnimator.ofFloat(0.0f, 1.0f);
animator.setDuration(500);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Float fraction = valueAnimator.getAnimatedFraction();
int newStrat = (int) evaluator.evaluate(fraction, start, end);
int newMid = (int) evaluator.evaluate(fraction, mid, start);
int newEnd = (int) evaluator.evaluate(fraction, end, mid);
int[] newArray = {newStrat, newMid, newEnd};
gradient.setColors(newArray);
}
});
animator.start();
}
public static void stopAnimation(final int view, final Activity activity){
ObjectAnimator.ofFloat(activity.findViewById(view), "alpha", 0f).setDuration(125).start();
}
其中视图
是具有渐变背景的简单视图
:
//gradient_preloader
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#FDB72B"
android:endColor="#00000000"
android:angle="0"/>
</shape>
//gradient\u预加载程序
观点:
<View
android:id="@+id/gradientPreloaderView"
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="@dimen/basic_8_dp"
android:background="@drawable/gradient_preloader" />
希望我的答案能帮助你找到最新的备选答案
class GradientAnimationDrawable(
start: Int = Color.rgb(0, 143, 209),
center: Int = Color.rgb(1, 106, 154),
end: Int = Color.rgb(28, 179, 249),
frameDuration: Int = 3000,
enterFadeDuration: Int = 0,
exitFadeDuration: Int = 3000
) : AnimationDrawable() {
private val gradientStart = GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, intArrayOf(start, center, end))
.apply {
shape = GradientDrawable.RECTANGLE
gradientType = GradientDrawable.LINEAR_GRADIENT
}
private val gradientCenter = GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, intArrayOf(center, end, start))
.apply {
shape = GradientDrawable.RECTANGLE
gradientType = GradientDrawable.LINEAR_GRADIENT
}
private val gradientEnd = GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, intArrayOf(end, start, center))
.apply {
shape = GradientDrawable.RECTANGLE
gradientType = GradientDrawable.LINEAR_GRADIENT
}
init {
addFrame(gradientStart, frameDuration)
addFrame(gradientCenter, frameDuration)
addFrame(gradientEnd, frameDuration)
setEnterFadeDuration(enterFadeDuration)
setExitFadeDuration(exitFadeDuration)
isOneShot = false
}
}
我不明白。。。你在同一天的同一时间提出并回答了这个问题?“这从来不是一个问题,是吗?”小克里斯,我搜索了很多,没有找到我想要的答案。所以我做了一些研究,最终得到了它。然后我想,“嗯,也许将来会有其他人搜索它,然后像我一样被困在里面?”-所以我用答案创造了这个问题。此外,还有一个内置功能可以实现这一点。尝试单击询问问题
。这里有一个检查回答你自己的问题-分享你的知识,问答式啊,好的,我明白了,我只是被时间弄糊涂了。谢谢,谢谢分享你的解决方案。谢谢Nexen,这绝对是正确的做法。我很感激你的回答,我很高兴能从你的回答开始我自己的研究。谢谢你的指点,节省了时间。同样,TimeAnimator需要api16,带有AnimatorUpdateListener的Objectanimator也会这样做。你能用Java写吗?
class GradientAnimationDrawable(
start: Int = Color.rgb(0, 143, 209),
center: Int = Color.rgb(1, 106, 154),
end: Int = Color.rgb(28, 179, 249),
frameDuration: Int = 3000,
enterFadeDuration: Int = 0,
exitFadeDuration: Int = 3000
) : AnimationDrawable() {
private val gradientStart = GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, intArrayOf(start, center, end))
.apply {
shape = GradientDrawable.RECTANGLE
gradientType = GradientDrawable.LINEAR_GRADIENT
}
private val gradientCenter = GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, intArrayOf(center, end, start))
.apply {
shape = GradientDrawable.RECTANGLE
gradientType = GradientDrawable.LINEAR_GRADIENT
}
private val gradientEnd = GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, intArrayOf(end, start, center))
.apply {
shape = GradientDrawable.RECTANGLE
gradientType = GradientDrawable.LINEAR_GRADIENT
}
init {
addFrame(gradientStart, frameDuration)
addFrame(gradientCenter, frameDuration)
addFrame(gradientEnd, frameDuration)
setEnterFadeDuration(enterFadeDuration)
setExitFadeDuration(exitFadeDuration)
isOneShot = false
}
}