为 FolderIcon 添加摇晃动画
为 FolderIcon 添加摇晃动画可以分为三种情况:
- FolderIcon 整体摇晃:folder icon + folder name 都摇晃
- FolderIcon 局部摇晃: a. 仅 folder 内的所有 icon 摇晃,folder icon 背景和 folder name 不摇晃 b. 仅 folder icon 摇晃,folder name 不摇晃
1. 为 FolderIcon 整体添加摇晃动画
- 修改
com/android/launcher3/folder/FolderIcon.java文件:
private ValueAnimator shakeAnim = null;
// current shaking angle
float shakeAngle = 0F;
@Override
public void startShake() {
cancelShake();
shakeAnim = ObjectAnimator.ofFloat(view, "rotation", -4F, 4F).apply {
duration = 400L
repeatCount = ObjectAnimator.INFINITE
repeatMode = ObjectAnimator.REVERSE
interpolator = CycleInterpolator(0.5f)
}
shakeAnim.start();
}
@Override
public void cancelShake() {
if (shakeAnim != null) {
shakeAnim.cancel();
setRotation(0F);
}
}
看看效果:
2. 为 FolderIcon 局部添加摇晃动画
a. 先定义摇晃动画
object AnimatorHelper{
@JvmStatic
fun createShakeAnimator(): ValueAnimator {
return ValueAnimator.ofFloat(-15F, 15F).apply {
duration = 600L
repeatCount = ObjectAnimator.INFINITE
repeatMode = ObjectAnimator.REVERSE
interpolator = CycleInterpolator(0.5f)
}
}
}
b. 在 FolderIcon 内添加摇晃动画
修改 com/android/launcher3/folder/FolderIcon.java 文件:
private ValueAnimator shakeAnim = null;
// current shaking angle
float shakeAngle = 0F;
@Override
public void startShake() {
cancelShake();
shakeAnim = AnimatorHelper.createShakeAnimator();
shakeAnim.addUpdateListener(animation -> {
shakeAngle = (float) animation.getAnimatedValue();
invalidate();
});
shakeAnim.start();
}
@Override
public void cancelShake() {
if (shakeAnim != null) {
shakeAnim.cancel();
shakeAngle = 0F;
invalidate();
}
}
c. 为 Folder 内所有 icon 添加摇晃动画
- 仅 folder 内所有 icon 摇晃,folder 背景和 folder name 不摇晃
修改 com/android/launcher3/folder/PreviewItemManager.java 文件:
/**
* Draws each preview item.
*
* @param offset The offset needed to draw the preview items.
* @param shouldClipPath Iff true, clip path using {@param clipPath}.
* @param clipPath The clip path of the folder icon.
*/
private void drawPreviewItem(Canvas canvas, PreviewItemDrawingParams params, PointF offset,
boolean shouldClipPath, Path clipPath) {
canvas.save();
if (shouldClipPath) {
canvas.clipPath(clipPath);
}
canvas.translate(offset.x + params.transX, offset.y + params.transY);
canvas.scale(params.scale, params.scale);
Drawable d = params.drawable;
if (d != null) {
Rect bounds = d.getBounds();
canvas.save();
canvas.translate(-bounds.left, -bounds.top);
canvas.scale(mIntrinsicIconSize / bounds.width(), mIntrinsicIconSize / bounds.height());
// add folder icons shaking animation
canvas.rotate(mIcon.shakeAngle, bounds.width() / 2F, bounds.height() / 2F);
d.draw(canvas);
canvas.restore();
}
canvas.restore();
}
abc 的效果:
d. 为 FolderIcon 添加摇晃动画
- folder icon 摇晃,folder name 不摇晃
修改 com/android/launcher3/folder/PreviewBackground.java 文件:
// update mInvalidateDelegate type to FolderIcon
private FolderIcon mInvalidateDelegate;
public void drawBackground(Canvas canvas) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(getBgColor());
// add folder icon shaking animation
if (mInvalidateDelegate != null && mInvalidateDelegate.shakeAngle != 0F) {
float cx = getScaledRadius() + getOffsetX();
float cy = getScaledRadius() + getOffsetY();
canvas.rotate(mInvalidateDelegate.shakeAngle, cx, cy);
}
getShape().drawShape(canvas, getOffsetX(), getOffsetY(), getScaledRadius(), mPaint);
drawShadow(canvas);
}
abd 的效果:
通过以上修改,我们可以为 Launcher3 FolderIcon 添加类似 iOS 的图标摇晃效果。