Android进阶之仿抖音的音乐旋转效果

文导读|   点击标题阅读

互联网寒冬下,程序员如何突围提升自己?

android性能评测与优化-内存

裸辞两个月,海投一个月,从 Android 转战 Web 前端的求职之路

原文:https://myml666.github.io ( 源码下载见文末
 
  

这次是实现一个仿抖音的音乐旋转自定义View,先看一下效果

640?wx_fmt=gif
效果图

实现这个效果主要是采用的拼凑的方法,即先实现音符动画再实现图片旋转动画然后将两个效果合并到一起。

640?wx_fmt=jpeg

先看下概念图

640?wx_fmt=jpeg
概念图

音符动画

音符动画这里是利用贝塞尔曲线+PathMeasure+ValueAnimator来实现的

640?wx_fmt=jpeg
音符动画概念

1.贝塞尔曲线的绘制:因为音符的运动轨迹是自下而上的,因此我们在添加Path路径的时候需要先将起点移到右下角,然后再绘制贝塞尔曲线。

path = new Path();//将起点移到右下角path.moveTo(getWidth(),getHeight()-getWidth()/6);//绘制自下而上的贝塞尔曲线path.quadTo(0,getHeight(),getWidth()/4,0);
//将起点移到右下角
path.moveTo(getWidth(),getHeight()-getWidth()/6);
//绘制自下而上的贝塞尔曲线
path.quadTo(0,getHeight(),getWidth()/4,0);

640?wx_fmt=gif

2.PathMeasure+ValueAnimator实现音符沿轨迹运动

private void initPath() {    //新建两个float数组pos用来存储每个轨迹点的坐标,tan用来存储正切值    pos = new float[2];    tan = new float[2];    path = new Path();    path.moveTo(getWidth(),getHeight()-getWidth()/6);    path.quadTo(0,getHeight(),getWidth()/4,0);    pathMeasure = new PathMeasure(path,false);    length = pathMeasure.getLength();    valueAnimator = ValueAnimator.ofFloat(0,2f);    valueAnimator.setDuration(3000);    //设置重复执行动画    valueAnimator.setRepeatCount(ValueAnimator.INFINITE);    //设置为匀速运动    valueAnimator.setInterpolator(new LinearInterpolator());    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {float temp=(float) animation.getAnimatedValue();val= temp/2;//这里实现音符的透明度从0~1~0的效果if(temp>1){    Music3.this.setAlpha(Math.abs(temp-2f));}else {    Music3.this.setAlpha(temp);}//更新界面invalidate();        }    });    valueAnimator.start();}@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //获取每个点对应的坐标    pathMeasure.getPosTan(length*val,pos,tan);    //创建音符BitMap宽高是逐渐放大的    scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int)(getWidth()/5*val)+4, (int)(getWidth()/5*val)+4, true);    canvas.drawPath(path,paint);    canvas.drawBitmap(scaledBitmap,pos[0],pos[1],paint);}
    //新建两个float数组pos用来存储每个轨迹点的坐标,tan用来存储正切值
    pos = new float[2];
    tan = new float[2];
    path = new Path();
    path.moveTo(getWidth(),getHeight()-getWidth()/6);
    path.quadTo(0,getHeight(),getWidth()/4,0);
    pathMeasure = new PathMeasure(path,false);
    length = pathMeasure.getLength();
    valueAnimator = ValueAnimator.ofFloat(0,2f);
    valueAnimator.setDuration(3000);
    //设置重复执行动画
    valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    //设置为匀速运动
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
float temp=(float) animation.getAnimatedValue();
val= temp/2;
//这里实现音符的透明度从0~1~0的效果
if(temp>1){
    Music3.this.setAlpha(Math.abs(temp-2f));
}else {
    Music3.this.setAlpha(temp);
}
//更新界面
invalidate();
        }
    });
    valueAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //获取每个点对应的坐标
    pathMeasure.getPosTan(length*val,pos,tan);
    //创建音符BitMap宽高是逐渐放大的
    scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int)(getWidth()/5*val)+4, (int)(getWidth()/5*val)+4true);
    canvas.drawPath(path,paint);
    canvas.drawBitmap(scaledBitmap,pos[0],pos[1],paint);
}

640?wx_fmt=gif
音符动画

图片旋转

这里我引用的一个第三方的圆形图片库

implementation 'de.hdodenhof:circleimageview:2.2.0''de.hdodenhof:circleimageview:2.2.0'

实现图片旋转

circleImageView = findViewById(R.id.mm);RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);rotateAnimation.setInterpolator(new LinearInterpolator());rotateAnimation.setDuration(4000);rotateAnimation.setRepeatCount(Animation.INFINITE);circleImageView.startAnimation(rotateAnimation);new RotateAnimation(0360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(4000);
rotateAnimation.setRepeatCount(Animation.INFINITE);
circleImageView.startAnimation(rotateAnimation);

640?wx_fmt=gif
图片旋转

最后附上源码:https://gitee.com/itfittnesss/DouYinMusic,更多android学习和视频欢迎加入我们的知识星球,这里有1000+小伙伴,让你的学习不寂寞~·

看完本文有收获?请转发分享给更多人


我们的知识星球第三期开期了,已达到1100人了,能连续做三期已很不容易了,有很多老用户续期,目前续期率达到50%,说明了大家对我们的知识星球还是很认可的,欢迎大家加入尽早我们的知识星球,更多星球信息参见:

欢迎加入Java和Android架构社群

如何进阶成为Java的Android版和架构师?

说两件事

640?wx_fmt=jpeg

微信扫描或者点击上方二维码领取的Android \ Python的\ AI \的Java等高级进阶资源

更多学习资料点击下面的“阅读原文 ”获取

640?wx_fmt=gif

谢谢老板,点个好看↓

猜你喜欢

转载自blog.csdn.net/xJ032w2j4cCjhOW8s8/article/details/90653825