Android 中的脉动按钮动画
Pulsating button animation in Android
我正在使用语音识别应用程序,我想在录音时让我的 play/stop 按钮 "pulse"。像这样:
我尝试制作一个 ScaleAnimation,让按钮变大,但当然,它会使所有按钮变大。
public static ObjectAnimator pulseAnimation(ImageView target){
ObjectAnimator scaleDown = ObjectAnimator.ofPropertyValuesHolder(target,
PropertyValuesHolder.ofFloat("scaleX", 1.1f),
PropertyValuesHolder.ofFloat("scaleY", 1.1f));
scaleDown.setDuration(310);
scaleDown.setRepeatCount(ObjectAnimator.INFINITE);
scaleDown.setRepeatMode(ObjectAnimator.REVERSE);
return scaleDown;
}
所以这个想法是实现类似的东西,但只是在实际按钮后面有一个 alpha。我想知道在我的按钮后面添加第二个 "Alpha Button" 以使其增长并实现此效果之前,是否可以使用 alpha 动画或其他方式执行此操作。
终于找到解决办法了!我重写了 onDraw 方法并为我的按钮绘制了第一个圆圈,当我的布尔值为真时。我以 alpha 作为背景绘制了第二个圆圈。制作脉动效果:
@Override
protected void onDraw(Canvas canvas) {
int w = getMeasuredWidth();
int h = getMeasuredHeight();
mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setColor(mColor);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(Util.adjustAlpha(mColor, 0.4f));
//Draw circle
canvas.drawCircle(w/2, h/2, MIN_RADIUS_VALUE , mCirclePaint);
if (mAnimationOn) {
if (mRadius >= MAX_RADIUS_VALUE)
mPaintGoBack = true;
else if(mRadius <= MIN_RADIUS_VALUE)
mPaintGoBack = false;
//Draw pulsating shadow
canvas.drawCircle(w / 2, h / 2, mRadius, mBackgroundPaint);
mRadius = mPaintGoBack ? (mRadius - 0.5f) : (mRadius + 0.5f);
invalidate();
}
super.onDraw(canvas);
}
public void animateButton(boolean animate){
if (!animate)
mRadius = MIN_RADIUS_VALUE;
mAnimationOn = animate;
invalidate();
}
使用 Jetpack Compose 更容易做到
无需自定义视图或 canvas
@Composable
fun PulseLoading(
durationMillis:Int = 1000,
maxPulseSize:Float = 300f,
minPulseSize:Float = 50f,
pulseColor:Color = Color(234,240,246),
centreColor:Color = Color(66,133,244)
){
val infiniteTransition = rememberInfiniteTransition()
val size by infiniteTransition.animateFloat(
initialValue = minPulseSize,
targetValue = maxPulseSize,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis, easing = LinearEasing),
repeatMode = RepeatMode.Restart
)
)
val alpha by infiniteTransition.animateFloat(
initialValue = 1f,
targetValue = 0f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis, easing = LinearEasing),
repeatMode = RepeatMode.Restart
)
)
Box(contentAlignment = Alignment.Center,modifier = Modifier.fillMaxSize()) {
//Card for Pulse Effect
Card(
shape = CircleShape,
modifier = Modifier.size(size.dp).align(Alignment.Center).alpha(alpha),
backgroundColor = pulseColor,
elevation = 0.dp
) {}
//Card For inner circle
Card(modifier = Modifier
.size(minPulseSize.dp)
.align(Alignment.Center),
shape = CircleShape,
backgroundColor = centreColor){}
}
}
您可以根据自己的需要进行定制。在“内圈”卡片中,您可以添加文字或任何您想要的内容。
我已经为此创建了一个完整的分步教程
你可以看看here.
我正在使用语音识别应用程序,我想在录音时让我的 play/stop 按钮 "pulse"。像这样:
我尝试制作一个 ScaleAnimation,让按钮变大,但当然,它会使所有按钮变大。
public static ObjectAnimator pulseAnimation(ImageView target){
ObjectAnimator scaleDown = ObjectAnimator.ofPropertyValuesHolder(target,
PropertyValuesHolder.ofFloat("scaleX", 1.1f),
PropertyValuesHolder.ofFloat("scaleY", 1.1f));
scaleDown.setDuration(310);
scaleDown.setRepeatCount(ObjectAnimator.INFINITE);
scaleDown.setRepeatMode(ObjectAnimator.REVERSE);
return scaleDown;
}
所以这个想法是实现类似的东西,但只是在实际按钮后面有一个 alpha。我想知道在我的按钮后面添加第二个 "Alpha Button" 以使其增长并实现此效果之前,是否可以使用 alpha 动画或其他方式执行此操作。
终于找到解决办法了!我重写了 onDraw 方法并为我的按钮绘制了第一个圆圈,当我的布尔值为真时。我以 alpha 作为背景绘制了第二个圆圈。制作脉动效果:
@Override
protected void onDraw(Canvas canvas) {
int w = getMeasuredWidth();
int h = getMeasuredHeight();
mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setColor(mColor);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(Util.adjustAlpha(mColor, 0.4f));
//Draw circle
canvas.drawCircle(w/2, h/2, MIN_RADIUS_VALUE , mCirclePaint);
if (mAnimationOn) {
if (mRadius >= MAX_RADIUS_VALUE)
mPaintGoBack = true;
else if(mRadius <= MIN_RADIUS_VALUE)
mPaintGoBack = false;
//Draw pulsating shadow
canvas.drawCircle(w / 2, h / 2, mRadius, mBackgroundPaint);
mRadius = mPaintGoBack ? (mRadius - 0.5f) : (mRadius + 0.5f);
invalidate();
}
super.onDraw(canvas);
}
public void animateButton(boolean animate){
if (!animate)
mRadius = MIN_RADIUS_VALUE;
mAnimationOn = animate;
invalidate();
}
使用 Jetpack Compose 更容易做到 无需自定义视图或 canvas
@Composable
fun PulseLoading(
durationMillis:Int = 1000,
maxPulseSize:Float = 300f,
minPulseSize:Float = 50f,
pulseColor:Color = Color(234,240,246),
centreColor:Color = Color(66,133,244)
){
val infiniteTransition = rememberInfiniteTransition()
val size by infiniteTransition.animateFloat(
initialValue = minPulseSize,
targetValue = maxPulseSize,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis, easing = LinearEasing),
repeatMode = RepeatMode.Restart
)
)
val alpha by infiniteTransition.animateFloat(
initialValue = 1f,
targetValue = 0f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis, easing = LinearEasing),
repeatMode = RepeatMode.Restart
)
)
Box(contentAlignment = Alignment.Center,modifier = Modifier.fillMaxSize()) {
//Card for Pulse Effect
Card(
shape = CircleShape,
modifier = Modifier.size(size.dp).align(Alignment.Center).alpha(alpha),
backgroundColor = pulseColor,
elevation = 0.dp
) {}
//Card For inner circle
Card(modifier = Modifier
.size(minPulseSize.dp)
.align(Alignment.Center),
shape = CircleShape,
backgroundColor = centreColor){}
}
}
您可以根据自己的需要进行定制。在“内圈”卡片中,您可以添加文字或任何您想要的内容。
我已经为此创建了一个完整的分步教程 你可以看看here.