我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛
完成效果:
前言
大家公司的中秋福利都发了吗?今年我们公司发了一盒月饼和一箱小零食,去年发了一盒月饼和一箱杂粮。虽然出来工作后几乎都是身在他乡过得中秋节,不能和家人团圆,但是还是要祝福大家中秋快乐的。作为一名Android开发者程序员实在没有什么好的创意,奔着尽可能看上去真实的动画效果和符合中秋主题,在此融入了月亮、星空、流行、云朵、团圆、嫦娥、月饼等元素,并且附有百度百科借鉴来的中秋小知识哦~
百度百科地址:中秋节
主要效果
1、嫦娥奔月
2、闪动的星空
3、飘动的云朵
主要运用技术
1、组合动画
2、自定义View
属性动画ObjectAnimator介绍
• translationX和translationY:用来沿着X轴或者Y轴进行平移。
• rotation、rotationX、rotationY:用来围绕View的支点进行旋转。
• scaleX、scaleY:横向拉伸和纵向拉伸
• alpha:透明度,默认是1(不透明),0代表完全透明。
• x和y:描述View对象在其容器中的最终位置。
组合动画AnimatorSet介绍
• after(Animator anim):将现有动画插入到传入的动画之后执行。
• after(long delay):将现有动画延迟指定毫秒后执行。
• before(Animator anim):将现有动画插入到传入的动画之前执行。
• with(Animator anim):将现有动画和传入的动画同时执行。
嫦娥奔月实现
嫦娥奔月其实非常简单就是一张图片用上组合动画,把图片进行平移、缩放、和渐变
//平移
ObjectAnimator animator1 = ObjectAnimator.ofFloat(binding.ivChange, "translationX", 1000f, 0f).setDuration(1000 * 10);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(binding.ivChange, "translationY", 1500f, 0f).setDuration(1000 * 10);
//透明度渐变
ObjectAnimator animator3 = ObjectAnimator.ofFloat(binding.ivChange, "alpha", 1f, 0f).setDuration(1000 * 1);
//缩放
ObjectAnimator animator4 = ObjectAnimator.ofFloat(binding.ivChange, "scaleX", 1.5f, 0.5f).setDuration(1000 * 10);
ObjectAnimator animator5 = ObjectAnimator.ofFloat(binding.ivChange, "scaleY", 1.5f, 0.5f).setDuration(1000 * 10);
//组合动画
AnimatorSet set = new AnimatorSet();
set.play(animator1).with(animator2).with(animator4).with(animator5).before(animator3);
//开始动画
set.start();
星空及流行的实现
初始化背景和星空画笔
private void init() {
starBitmap = zoomImg(BitmapFactory.decodeResource(getResources(), R.drawable.snow), 20, 20);
//初始化 画笔
weatherPaint = new Paint();
weatherPaint.setAntiAlias(true);
weatherPaint.setStyle(Paint.Style.FILL);
starPaint = new Paint();
starPaint.setMaskFilter(new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL));
starPaint.setColor(Color.WHITE);
starPaint.setStyle(Paint.Style.FILL);
initAlphaFilter();
}
public Bitmap zoomImg(Bitmap bm, int newWidth, int newHeight) {
// 获得图片的宽高
int width = bm.getWidth();
int height = bm.getHeight();
// 计算缩放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要缩放的matrix参数
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的图片
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}
private void initAlphaFilter() {
for (int i = 0; i < 100; i++) {
alphaFilters[i] = new ColorMatrixColorFilter(new float[]{
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0.01f * i, 0});
}
}
初始化流行星星参数:
private void initStarMeteorParams() {
meteorParams.clear();
starParams.clear();
if (width == 0 || height == 0) {
return;
}
float widthRatio = Unit.px2dip(context, width) / 392.0f;
for (int i = 0; i < 50; i++) {
int index = (int) (Math.random() * 2);
StarParam starParam = new StarParam(index);
starParam.init(width, height, widthRatio);
starParams.add(starParam);
}
for (int i = 0; i < 2; i++) {
MeteorParam param = new MeteorParam();
param.init(width, height, widthRatio);
meteorParams.add(param);
}
}
绘制背景、星星和流行
/**
* 绘制背景
*/
private void drawWeatherBg(Canvas canvas) {
int[] color = new int[]{Color.parseColor(context.getResources().getStringArray(R.array.weather_cloudy_light)[0]),
Color.parseColor(context.getResources().getStringArray(R.array.weather_cloudy_light)[1])};
mBackgroundShader = new LinearGradient(0, 0, 0, height, color[0], color[1], Shader.TileMode.MIRROR);
weatherPaint.setShader(mBackgroundShader);
weatherPaint.setShadowLayer(15, 10, 10, Color.GRAY);
backgroundRect = new Rect(0, 0, width, height);
canvas.drawRect(backgroundRect, weatherPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
/**
* 绘制星星 和流星
*/
private void drawStarMeteor(Canvas canvas) {
if (starParams.size() > 0) {
for (StarParam param : starParams) {
drawStar(param, canvas);
}
}
if (meteorParams.size() > 0) {
for (MeteorParam param : meteorParams) {
drawMeteor(param, canvas);
}
}
}
/**
* 绘制星星
*
* @param star
* @param canvas
*/
private void drawStar(StarParam star, Canvas canvas) {
if (star == null) {
return;
}
canvas.save();
int index = (int) (star.alpha * 100);
if (index < 0) {
index = 0;
}
if (index > 99) {
index = 99;
}
starIdentity = alphaFilters[index];
starPaint.setColorFilter(starIdentity);
canvas.scale((float) star.scale, (float) star.scale);
canvas.drawBitmap(starBitmap, (float) star.x, (float) star.y, starPaint);
canvas.restore();
star.move();
}
/**
* 绘制流星
*/
private void drawMeteor(MeteorParam meteor, Canvas canvas) {
if (meteor == null) {
return;
}
canvas.save();
if (mStarShader == null) {
mStarShader = new LinearGradient(0, 0, 0, width, Color.parseColor("#FFFFFFFF"), Color.parseColor("#00FFFFFF"), Shader.TileMode.MIRROR);
}
starPaint.setShader(mStarShader);
starPaint.setColorFilter(null);
starPaint.setAntiAlias(true);
canvas.rotate((float) (Math.PI * meteor.radians));
float scale = Unit.px2dip(context, width) / 392.0f;
canvas.scale(scale, scale);
canvas.translate(
(float) meteor.translateX, (float) (Math.tan(Math.PI * 0.1) * Unit.dip2px(context, meteorWidth) + meteor.translateY));
if (starRectF == null) {
starRectF = new RectF(0, 0, Unit.dip2px(context, meteorWidth), Unit.dip2px(context, meteorHeight));
}
float starRadius = Unit.dip2px(context, radius);
canvas.drawRoundRect(starRectF, starRadius, starRadius, starPaint);
meteor.move(context);
canvas.restore();
}
星空和流行绘制参考:包含雨,雪,雷电,雾等多种天气效果。
dp、px互转工具
public class Unit {
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
循环漂浮的云的实现
private Runnable task = new Runnable() {
public void run() {
handler.postDelayed(this, 30 * 1000);//设置循环时间,此处是5秒
//平移
ObjectAnimator.ofFloat(binding.ivCloud, "translationX", -1000f, 1200f).setDuration(1000 * 30).start();
}
};
调用:
//保持屏幕常亮
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//立即调用
handler.post(task);
文字对齐使用:AlignTextView
完整代码请查看:流行效果和嫦娥奔月动画。
Android安装包体验:去下载