Android版网易云音乐唱片机唱片磁盘旋转及唱片机机械臂动画关键代码实现思路

简介: Android版网易云音乐唱片机唱片磁盘旋转及唱片机机械臂动画关键代码实现思路先看一看我的代码运行结果。代码运行起来初始化状态:点击开始按钮,唱片机的机械臂匀速接近唱片磁盘,同时唱片磁盘也开始匀速顺时针旋转:点击停止按钮,唱片机的机械臂匀速抬离唱片磁盘,同时唱片磁盘停止旋转:实现思路:(一)旋转唱片磁盘。


Android版网易云音乐唱片机唱片磁盘旋转及唱片机机械臂动画关键代码实现思路

先看一看我的代码运行结果。
代码运行起来初始化状态:



点击开始按钮,唱片机的机械臂匀速接近唱片磁盘,同时唱片磁盘也开始匀速顺时针旋转:



点击停止按钮,唱片机的机械臂匀速抬离唱片磁盘,同时唱片磁盘停止旋转:


实现思路:
(一)旋转唱片磁盘。在附录文章12的基础上,实现网易云音乐风格的唱片磁盘。核心代码:

 //最外部的半透明边线
        OvalShape ovalShape0 = new OvalShape();
        ShapeDrawable drawable0 = new ShapeDrawable(ovalShape0);
        drawable0.getPaint().setColor(0x10000000);
        drawable0.getPaint().setStyle(Paint.Style.FILL);
        drawable0.getPaint().setAntiAlias(true);

        //黑色唱片边框
        RoundedBitmapDrawable drawable1 = RoundedBitmapDrawableFactory.create(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.disc));
        drawable1.setCircular(true);
        drawable1.setAntiAlias(true);

        //内层黑色边线
        OvalShape ovalShape2 = new OvalShape();
        ShapeDrawable drawable2 = new ShapeDrawable(ovalShape2);
        drawable2.getPaint().setColor(Color.BLACK);
        drawable2.getPaint().setStyle(Paint.Style.FILL);
        drawable2.getPaint().setAntiAlias(true);

        //最里面的图像
        RoundedBitmapDrawable drawable3 = RoundedBitmapDrawableFactory.create(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.zhangphil));
        drawable3.setCircular(true);
        drawable3.setAntiAlias(true);

        Drawable[] layers = new Drawable[4];
        layers[0] = drawable0;
        layers[1] = drawable1;
        layers[2] = drawable2;
        layers[3] = drawable3;

        LayerDrawable layerDrawable = new LayerDrawable(layers);

        int width = 10;
        //针对每一个图层进行填充,使得各个圆环之间相互有间隔,否则就重合成一个了。
        //layerDrawable.setLayerInset(0, width, width, width, width);
        layerDrawable.setLayerInset(1, width , width, width, width );
        layerDrawable.setLayerInset(2, width * 11, width * 11, width * 11, width * 11);
        layerDrawable.setLayerInset(3, width * 12, width * 12, width * 12, width * 12);

        final View discView = findViewById(R.id.myView);
        discView.setBackgroundDrawable(layerDrawable);
AI 代码解读


唱片磁盘旋转,则通过属性动画ObjectAnimator实现唱片磁盘的顺时针旋转:

 discObjectAnimator = ObjectAnimator.ofFloat(discView, "rotation", 0, 360);
        discObjectAnimator.setDuration(20000);
        //使ObjectAnimator动画匀速平滑旋转
        discObjectAnimator.setInterpolator(new LinearInterpolator());
        //无限循环旋转
        discObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);
        discObjectAnimator.setRepeatMode(ValueAnimator.INFINITE);
AI 代码解读


(二)唱片机的机械臂。在相对布局的顶部放置一个ImageView,这个ImageView就是机械臂的素材,当点击开始按钮时候,就使用Android属性动画操作该ImageView以左上角坐标位置(x=0,y=0)向下顺时针匀速旋转一定角度使得机械臂刚好落入到唱片磁盘内。当点击停止按钮时候,一方面控制唱片磁盘停止旋转,另一方面要操纵机械臂匀速逆时针向上旋转离开唱片磁盘。


我写的这个例子需要布局文件:




    

    

    

    

 
  上层全部完整Java代码:
 
 package zhangphil.app;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
import android.os.Bundle;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;


public class MainActivity extends Activity {
    private ObjectAnimator discObjectAnimator,neddleObjectAnimator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //最外部的半透明边线
        OvalShape ovalShape0 = new OvalShape();
        ShapeDrawable drawable0 = new ShapeDrawable(ovalShape0);
        drawable0.getPaint().setColor(0x10000000);
        drawable0.getPaint().setStyle(Paint.Style.FILL);
        drawable0.getPaint().setAntiAlias(true);

        //黑色唱片边框
        RoundedBitmapDrawable drawable1 = RoundedBitmapDrawableFactory.create(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.disc));
        drawable1.setCircular(true);
        drawable1.setAntiAlias(true);

        //内层黑色边线
        OvalShape ovalShape2 = new OvalShape();
        ShapeDrawable drawable2 = new ShapeDrawable(ovalShape2);
        drawable2.getPaint().setColor(Color.BLACK);
        drawable2.getPaint().setStyle(Paint.Style.FILL);
        drawable2.getPaint().setAntiAlias(true);

        //最里面的图像
        RoundedBitmapDrawable drawable3 = RoundedBitmapDrawableFactory.create(getResources(), BitmapFactory.decodeResource(getResources(), R.drawable.zhangphil));
        drawable3.setCircular(true);
        drawable3.setAntiAlias(true);

        Drawable[] layers = new Drawable[4];
        layers[0] = drawable0;
        layers[1] = drawable1;
        layers[2] = drawable2;
        layers[3] = drawable3;

        LayerDrawable layerDrawable = new LayerDrawable(layers);

        int width = 10;
        //针对每一个图层进行填充,使得各个圆环之间相互有间隔,否则就重合成一个了。
        //layerDrawable.setLayerInset(0, width, width, width, width);
        layerDrawable.setLayerInset(1, width , width, width, width );
        layerDrawable.setLayerInset(2, width * 11, width * 11, width * 11, width * 11);
        layerDrawable.setLayerInset(3, width * 12, width * 12, width * 12, width * 12);

        final View discView = findViewById(R.id.myView);
        discView.setBackgroundDrawable(layerDrawable);

        ImageView needleImage= (ImageView) findViewById(R.id.needle);

        findViewById(R.id.startButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                discObjectAnimator.start();
                neddleObjectAnimator.start();
            }
        });

        findViewById(R.id.stopButton).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                discObjectAnimator.cancel();
                neddleObjectAnimator.reverse();
            }
        });

        discObjectAnimator = ObjectAnimator.ofFloat(discView, "rotation", 0, 360);
        discObjectAnimator.setDuration(20000);
        //使ObjectAnimator动画匀速平滑旋转
        discObjectAnimator.setInterpolator(new LinearInterpolator());
        //无限循环旋转
        discObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);
        discObjectAnimator.setRepeatMode(ValueAnimator.INFINITE);


        neddleObjectAnimator = ObjectAnimator.ofFloat(needleImage, "rotation", 0, 25);
        needleImage.setPivotX(0);
        needleImage.setPivotY(0);
        neddleObjectAnimator.setDuration(800);
        neddleObjectAnimator.setInterpolator(new LinearInterpolator());
    }
}

        
          
        
        
        
          
          AI 代码解读
        
      
       
 
  遗留问题: (1)实际上,右上角机械臂这个ImageView以(x=0,y=0)的坐标位置旋转不是很恰当,因为这个机械臂作为图像素材,它本身的左上角肯定有部分空间位置,使得旋转时候不能够刚好以图中机械臂左上角那个螺丝衔接的位置旋转,也许是把机械臂衔接螺丝那个位置遮挡起来就像网易云音乐的做法,但是更完美的处理方法,我个人感觉勇应该分段设计这个机械臂:在素材设计上,把这个机械臂分为两段设计,最上的那个衔接螺丝单独抽出来,固定在布局上,然后螺丝下面把机械臂的尾部遮挡起来,旋转只选择机械臂,这样旋转就非常逼真。 (2)从代码中可以看出里面很多位置、角度、距离的值都是写死的,比如机械臂旋转的角度,机械臂的最大高度等等,作为demo说明解决方案没问题,但是在涉及到千百种Android屏幕尺寸各异的设备时候,情况变得比较复杂,要精心计算这些空间位置距离。 (3)发现一个Android自身的问题。在本例中,如果把背景图片background.jpg换成更高质量和分辨率的图如1080 X 1920,则动画执行非常之卡。但是如果把背景图片质量换成低分辨率图540 X 960则不影响动画执行效率。
 
 我写的这个例子中用到的一些素材。 整个背景图background.jpg:
 
 
  唱片机的机械臂needle.png
 
 
 
 唱片磁盘包括头像的外部黑色外圈disc.png:
 
 
 头像是我csdn的博客头像:
 
 
 
 附录: 1,《Android动画Animation的两种加载执行方式》链接地址:http://blog.csdn.net/zhangphil/article/details/47394225  2,《Android AnimationDrawable动画与APP启动引导页面》链接地址:http://blog.csdn.net/zhangphil/article/details/47416915    3,《Android layer-list(1)》 4,《Android layer-list:联合shape(2)》链接地址:http://blog.csdn.net/zhangphil/article/details/51721283   5,《Android layer-list(3)》链接地址:http://blog.csdn.net/zhangphil/article/details/51721816  6,《Android Property Animation属性动画初识:透明渐变(1)》链接地址:http://blog.csdn.net/zhangphil/article/details/50484224     7,《Android Property Animation属性动画:rotation旋转(2)》链接地址:http://blog.csdn.net/zhangphil/article/details/50495555    8,《Android Property Animation属性动画初识:位移translation(3)》链接地址:http://blog.csdn.net/zhangphil/article/details/50495844   9,《Android Property Animation属性动画:scale缩放动画(4)》链接地址:http://blog.csdn.net/zhangphil/article/details/50497404  10,《Android Property Animation属性动画集:AnimatorSet(5)》链接地址:http://blog.csdn.net/zhangphil/article/details/50498531  11,《Android ImageView加载圆形图片且同时绘制圆形图片的外部边缘边线及边框》链接地址:http://blog.csdn.net/zhangphil/article/details/51944262  12,《Android View加载圆形图片且同时绘制圆形图片的外部边缘边线及边框:LayerDrawable实现》链接:http://blog.csdn.net/zhangphil/article/details/52035255
AI 代码解读
目录
打赏
0
0
0
0
15
分享
相关文章
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
143 2
基于Android P,自定义Android开机动画的方法
Android 中加载 Gif 动画
【10月更文挑战第20天】加载 Gif 动画是 Android 开发中的一项重要技能。通过使用第三方库或自定义实现,可以方便地在应用中展示生动的 Gif 动画。在实际应用中,需要根据具体情况进行合理选择和优化,以确保用户体验和性能的平衡。可以通过不断的实践和探索,进一步掌握在 Android 中加载 Gif 动画的技巧和方法,为开发高质量的 Android 应用提供支持。
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
64 1
探索安卓与iOS开发的差异:从代码到用户体验
【10月更文挑战第5天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。它们在技术架构、开发环境及用户体验上有着根本的不同。本文通过比较这两种平台的开发过程,揭示背后的设计理念和技术选择如何影响最终产品。我们将深入探讨各自平台的代码示例,理解开发者面临的挑战,以及这些差异如何塑造用户的日常体验。
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
在Android开发中,每位开发者都渴望应用响应迅速、体验流畅。然而,代码执行缓慢却是常见问题。本文将跟随一位大神的脚步,剖析三大典型案例:主线程阻塞导致卡顿、内存泄漏引发性能下降及不合理布局引起的渲染问题,并提供优化方案。通过学习这些技巧,你将能够显著提升应用性能,从新手蜕变为高手。
66 2
Android调用Vue中的JavaScript代码
Android调用Vue中的JavaScript代码
96 3
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
238 12
Android远程连接和登录FTPS服务代码(commons.net库)
很多文章都介绍了FTPClient如何连接ftp服务器,但却很少有人说如何连接一台开了SSL认证的ftp服务器,现在代码来了。
141 2
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
【7月更文挑战第28天】在Android开发中,每位开发者都追求极致的用户体验。然而,“代码执行慢”的问题时常困扰着开发者。通过案例分析,我们可探索从新手到高手的成长路径。
55 3

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
    12
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    21
  • 3
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    15
  • 4
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    2
  • 5
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    3
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    3
  • 7
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    2
  • 8
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    6
  • 9
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    3
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    1
  • 1
    android FragmentManager 删除所有Fragment 重建
    18
  • 2
    Android实战经验之Kotlin中快速实现MVI架构
    30
  • 3
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    35
  • 4
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    42
  • 5
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    142
  • 6
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    46
  • 7
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    58
  • 8
    Android历史版本与APK文件结构
    160
  • 9
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    48
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    41
  • AI助理

    你好,我是AI助理

    可以解答问题、推荐解决方案等