持续创造,加快成长!这是我参加「日新计划 6 月更文应战」的第1天,点击检查活动详情
牙叔教程 简单易懂
正常动画速度500ms
慢速动画3秒
思路
- 制作布景, 白色的圆角矩形
- 制作爱心, 红色的心形
- 添加点击动画
制作白色的矩形
drawBg(that.roundRectPaint, that.fraction, canvas, that.width, that.height);
是现已封装好的代码, 便是画个圆角矩形
function drawBg(paint, fraction, canvas, width, height) {
let left = 0;
let top = 0;
let right = width;
let bottom = height;
// scale
let scaleX = leap(1, 0.9, 1, fraction);
let scaleY = scaleX;
let pivotX = width / 2;
let pivotY = height / 2;
canvas.scale(scaleX, scaleY, pivotX, pivotY);
let radius = 100;
canvas.drawRoundRect(left, top, right, bottom, radius, radius, paint);
}
其中有5个参数
function drawBg(paint, fraction, canvas, width, height)
paint是画笔
fraction是操控Canvas缩放的
canvas是画板
width, height是矩形的宽高
fraction是这里边最要害的, 由于咱们这个教程首要便是写动画;
动画的首要形式便是操控canvas的缩放
fraction首要用在leap函数里边, 咱们看看leap是什么?
leap
function leap(a, b, c, fraction) {
if (fraction <= 0.5) {
return MathUtils.lerp(a, b, fraction * 2);
} else {
let tempFraction = fraction - 0.5;
return MathUtils.lerp(b, c, tempFraction * 2);
}
}
leap返回一个数字, 用这个数字来操控动画;
数字是用lerp计算出来的
lerp
com.google.android.material.math.MathUtils.lerp
咱们去安卓官网看看这个办法
public static float lerp (float start,
float stop,
float amount)
Returns the linear interpolation of amount between start and stop.
返回两个数字时间的线性插值
Canvas
canvas从哪里来的?
canvas是自定义控件的参数, 是onDraw的参数
CustomView.prototype.render = function () {
let that = this;
return JavaAdapter(
android.view.View,
{
onDraw: function (canvas) {...}
咱们制作矩形和心形都是在 onDraw 办法中制作;
制作矩形的时分, 要知道矩形的宽高;
宽高要测量, 测量办法是 onMeasure
onMeasure: function (widthMeasureSpec, heightMeasureSpec) {
this.super$onMeasure(heightMeasureSpec, widthMeasureSpec);
this.setMeasuredDimension(this.getMeasuredHeight(), this.getMeasuredWidth());
that.width = this.getMeasuredWidth();
that.height = this.getMeasuredHeight();
},onMeasure: function (widthMeasureSpec, heightMeasureSpec) {
心形
制作完矩形, 咱们要制作心形;
心形运用的是内置icon,
let drawableId = "ic_favorite_black_48dp";
let imgId = resources.getIdentifier(drawableId, "drawable", context.getPackageName());
let drawable = resources.getDrawable(imgId);
let bitmap = drawable.getBitmap();
这时分的bitmap不能直接运用, 咱们要仿制一下bitmap
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
扩大心形图片
内置的icon一般都很小, 咱们要把心形扩大到矩形巨细
var img = com.stardust.autojs.core.image.ImageWrapper.ofBitmap(bitmap);
let width = that.width;
let height = that.height;
let fx = 1;
if (width > height) {
fx = height / img.width;
} else {
fx = width / img.width;
}
let fy = fx;
let img2 = images.scale(img, fx, fy);
要及时回收图片
events.on("exit", function () {
img2.recycle();
});
setTimeout(() => {
img.recycle();
}, 666);
图片搞好以后, 咱们还要给图片设置色彩
图片上色
用扩大后的心形图片, 创立一个canvas实例,
let srcInMode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
// let drawableCanvas = Canvas(iconBitmap);
let drawableCanvas = null;
function tintBitmap(paint, iconBitmap) {
// change to src in
paint.xfermode = srcInMode;
drawableCanvas.drawRect(0, 0, iconBitmap.width, iconBitmap.height, paint);
paint.xfermode = null;
}
这里用的模式是 SRC_IN , 只显现两者相交的部分, 且显现前景色, 也便是咱们设置的色彩
动画操控
运用的是 ValueAnimator
// 创立动画
function createAnimator(that) {
//动画
let animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(config.duration);
animator.setInterpolator(new BounceInterpolator());
animator.addListener(
new AnimatorListenerAdapter({
onAnimationStart: function (animation) {
that.uiState = UIState.Animating;
},
onAnimationEnd: function (animation) {
that.uiState = that.uiStateStart == UIState.Like ? UIState.UnLike : UIState.Like;
},
onAnimationCancel: function (animation) {},
})
);
animator.addUpdateListener(
new ValueAnimator.AnimatorUpdateListener({
onAnimationUpdate: function (valueAnimator) {
let value = valueAnimator.getAnimatedValue();
that.fraction = value;
that.view.invalidate();
},
})
);
return animator;
}
ValueAnimator始终是从0改变到1, 然后赋值给 fraction ,
fraction 改变, 又会引起 scaleX 的改变, scaleX又是 canvas.scale 的参数
canvas.scale(scaleX, scaleY, pivotX, pivotY);
每次制作矩形和心形之前, 都会先缩放canvas
而且修改了默认的差值器, 运用的是 BounceInterpolator , 弹跳插值器, 模仿自由落体后的回弹动画
animator.setInterpolator(new BounceInterpolator());
自定义控件结构
(function () {
util.extend(CustomView, ui.Widget);
function CustomView() {
ui.Widget.call(this);
}
CustomView.prototype.render = function () {
return JavaAdapter(
android.view.View,
{
onDraw: function (canvas) {
this.super$onDraw(canvas);
...
},
onMeasure: function (widthMeasureSpec, heightMeasureSpec) {
this.super$onMeasure(heightMeasureSpec, widthMeasureSpec);
this.setMeasuredDimension(this.getMeasuredHeight(), this.getMeasuredWidth());
},
onSizeChanged: function (w, h, oldW, oldH) {
this.super$onSizeChanged(w, h, oldW, oldH);
},
},
activity
);
};
CustomView.prototype.onViewCreated = function (view) {};
CustomView.prototype.onFinishInflation = function (view) {};
ui.registerWidget("like-button", CustomView);
return CustomView;
})();
以上, 便是一个点赞动画的要害常识
测试环境
手机: Mi 11 Pro
Android版别: 12
Autojs版别: 9.1.17
名人名言
思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最终才是群里问问 — 牙叔教程
声明
部分内容来自网络 本教程仅用于学习, 禁止用于其他用途\
微信公众号 牙叔教程