仿网易云音乐播放器(磁盘转圈、背景虚化等等)

先看效果,CSDN的git传上去总是不动。不知道为什么。

主要思路:

1 、 除了 開始/暂停 、上一首、下一首 这三个icon。你看到的是一个ViewGroup ,这个ViewGroup里面有圆形封面。黑色圈圈磁盘。唱针,高斯模糊背景图

2、 凝视掉了磁盘一起转动的效果,如今的方案不是最好的,建议若是想实现,能够把圆形封面和磁盘合并成一张图(最好在CicicleImageView这里面做)。给一个旋转动画。两个动画。两个View,帧的频率不会那么高

3、凝视掉了上一首、下一首切换的时候渐变的动画效果,原图从1-0 。新图从0-1 的渐变。 在模拟器上会报错。主要是由于改变ImageView的背景那一行报错。眼下不知道详细原因。好像是底层出现野指针

欢迎大家优化,改动上面的问题。改好一定要跟我交流下。

以下是代码结构:

CircleImageView : 生成圆形图片

GaussianBlurUtil : 高斯模糊

MusicPlayView : 播放器View

MainActivity:主控制类

布局2个,一个是主,一个是播放器的View.看下主的就知道思路了。

一个播放器。三个Button

<?

xml version="1.0" encoding="utf-8"?

>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <include layout="@layout/media_play_view"
        android:id="@+id/layout_media_play_view"
             />

        <Button
            android:id="@+id/btn_play_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/fm_btn_play"
            android:layout_centerInParent="true"/>

		<Button
            android:id="@+id/btn_previous"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_play_previous"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"/>

        <Button
            android:id="@+id/btn_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_play_next"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"/>
</RelativeLayout>

播放器源代码,里面注视代码不少。

/**
 * 代码说明: 1. 凝视掉了磁盘一起转动的效果。如今的方案不是最好的,建议若是想实现,能够把圆形封面和磁盘合并成一张图(最好在CicicleImageView这里面做)。

给一个旋转动画。

两个动画。两个View,帧的频率不会那么高
 *        2. 凝视掉了上一首、下一首切换的时候渐变的动画效果。原图从1-0 ,新图从0-1 的渐变。

在模拟器上会报错。主要是由于改变ImageView的背景那一行报错。

* @author xiu
 *
 */

public class MusicPlayView extends RelativeLayout {

	private Context mContext;
	//旋转一周所用时间
	private static final int ROTATE_TIME = 12 * 1000;
	//动画旋转反复运行的次数。这里代表无数次。似乎没有无限运行的属性,所以用了一个大数字代表
	private static final int ROTATE_COUNT = 10000;

	//唱针动画时间
	private static final int NEEDLE_TIME = 1 * 500 ;
	//唱针动画运行的角度
	private static final int NEEDLE_RADIUS = 30 ;

	//封面、背景切换时候的渐变动画
	private static final int AVATART_DISC_ALPHA_TIME = 1 * 300 ;

	private static final float AVATART_DISC_ALPHA_PERCENT = 0.3f;

	//背景
	private ImageView mBackground ;

	//唱针
	private ImageView mNeedle;
	//唱片
//	private ImageView mDisc;
	//封面
	private CircleImageView mAvatar;

	private boolean isPlay = false;

	//唱针移动动画
	ObjectAnimator mAniNeedle;

	//磁盘和封面旋转动画
//	ObjectAnimator mAniDisc;
	ObjectAnimator mAniAvatar;

//	//封面更换时的渐变效果
//	ObjectAnimator mAniAlphaAvatarHide;
//	ObjectAnimator mAniAlphaAvatarShow;
//
//	//背景更换时的渐变效果
//	ObjectAnimator mAniAlphaDiscBgHide;
//	ObjectAnimator mAniAlphaDiscBgShow;

	float mValueAvatar ;
	float mValueDisc ;
	float mValueNeedle ;

//	private int mCurrentImageResource = 0;

//	public MusicPlay mMusicPlayListener ;

	public MusicPlayView(Context context, AttributeSet attrs) {
		super(context);
		mContext = context;
	}

	public MusicPlayView(Context context) {
		super(context);
		mContext = context;
	}

	public MusicPlayView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mContext = context;
	}

	/*public interface MusicPlay{
		void onAvatarChange();

		void onDiscbgChange();
	}*/

	/*public void setMusicPlayerListener(MusicPlay listener ){
		this.mMusicPlayListener = listener ;
	}*/

	 @Override
     protected void onFinishInflate() {
        super.onFinishInflate();
        mBackground = (ImageView) findViewById(R.id.bg);

		mAvatar = (CircleImageView) findViewById(R.id.avatar);

//		Bitmap conformBitmap = toConformBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.fm_play_disc), mAvatar.getBitmap());
//		mAvatar.setImageBitmap(conformBitmap);
//		mAvatar.setBackgroundDrawable(new BitmapDrawable(conformBitmap));

//		mAvatar.setBackgroundDrawable(getResources().getDrawable(R.drawable.fm_play_disc));
//		mDisc = (ImageView) findViewById(R.id.disc);
		mNeedle = (ImageView) findViewById(R.id.needle);

//		mDisc.setVisibility(View.GONE);

		initAvatarAnimation(0f);
//		initDiscAnimation(0f);
		initNeedleAnimation(0f);

//		//封面页面动画
//		mAniAlphaAvatarHide = ObjectAnimator.ofFloat(mAvatar, "alpha", 1, AVATART_DISC_ALPHA_PERCENT).setDuration(AVATART_DISC_ALPHA_TIME);
//		mAniAlphaAvatarHide.addListener(avatarAlphaHideListener);
//		mAniAlphaAvatarShow = ObjectAnimator.ofFloat(mAvatar, "alpha", AVATART_DISC_ALPHA_PERCENT, 1).setDuration(AVATART_DISC_ALPHA_TIME);
//
//		mAniAlphaDiscBgHide = ObjectAnimator.ofFloat(mBackground, "alpha", 1, AVATART_DISC_ALPHA_PERCENT).setDuration(AVATART_DISC_ALPHA_TIME);
//		mAniAlphaDiscBgHide.addListener(discbgAlphaHideListener);
//		mAniAlphaDiscBgShow = ObjectAnimator.ofFloat(mBackground, "alpha", AVATART_DISC_ALPHA_PERCENT, 1).setDuration(AVATART_DISC_ALPHA_TIME);
    }

	/* AnimatorListener avatarAlphaHideListener = new AnimatorListener() {

		@Override
		public void onAnimationStart(Animator arg0) {

		}

		@Override
		public void onAnimationRepeat(Animator arg0) {

		}

		@Override
		public void onAnimationEnd(Animator arg0) {
			mMusicPlayListener.onAvatarChange();
			mAniAlphaAvatarShow.start();

		}

		@Override
		public void onAnimationCancel(Animator arg0) {

		}
	};

	 AnimatorListener discbgAlphaHideListener = new AnimatorListener() {

		@Override
		public void onAnimationStart(Animator arg0) {

		}

		@Override
		public void onAnimationRepeat(Animator arg0) {

		}

		@Override
		public void onAnimationEnd(Animator arg0) {
			mMusicPlayListener.onDiscbgChange();
			mAniAlphaDiscBgShow.start();

		}

		@Override
		public void onAnimationCancel(Animator arg0) {

		}
	};*/

	/**
	 *
	 * 设置背景
	 * @param d
	 */
	public void setBackgroundDrawable(Drawable d){
		mBackground.setBackgroundDrawable(d);
	}

	/**
	 *
	 * 设置背景
	 * @param d
	 */
	public void setBackgroundResource(int resourece){
		Bitmap bmp = GaussianBlurUtil.drawableToBitmap(getResources().getDrawable(resourece)) ;
		mBackground.setBackgroundDrawable(GaussianBlurUtil.BoxBlurFilter(bmp));
	}

	public void setAvatarImageResource(int resourceid){
		mAvatar.setImageDrawable(getResources().getDrawable(resourceid));
	}

	/**
	 * 播放
	 */
	public void play(){
		initNeedleAnimation(0f);
		AnimatorSet animSet = new AnimatorSet();
//        animSet.playTogether(mAniAvatar,mAniDisc);
        animSet.play(mAniAvatar).after(mAniNeedle);
        animSet.start();
		setPlay(true);
	}

	/**
	 * 暂停
	 */
	public void pause(){
		initNeedleAnimation(NEEDLE_RADIUS);
		mAniNeedle.start();
		mAniAvatar.cancel();
//		mAniDisc.cancel();
		initAvatarAnimation(mValueAvatar);
//		initDiscAnimation(mValueDisc);
		setPlay(false);
	}

	/**
	 * 下一首
	 */
	public void next(int resourceId){
//		mAniAlphaAvatarHide.start();
//		mAniAlphaDiscBgHide.start();
		changeImage(resourceId);
//		pause();
//		initAvatarAnimation(0f);
//		initDiscAnimation(0f);
//		initNeedleAnimation(0f);
//		play();
	}

	private void changeImage(final int resourceId){
		postDelayed(new Runnable() {

			@Override
			public void run() {
				setBackgroundResource(resourceId);
				setAvatarImageResource(resourceId);

			}
		}, 0);
	}

	private Bitmap toConformBitmap(Bitmap background, Bitmap foreground) {
        if( background == null ) {
           return null;
        }   

        int bgWidth = background.getWidth();
        int bgHeight = background.getHeight();
        //int fgWidth = foreground.getWidth();
        //int fgHeight = foreground.getHeight();
        //create the new blank bitmap 创建一个新的和SRC长度宽度一样的位图
        Bitmap newbmp = Bitmap.createBitmap(bgWidth, bgHeight, Config.RGB_565);
        Canvas cv = new Canvas(newbmp);
        //draw bg into
        cv.drawBitmap(background, 0, 0, null);//在 0,0坐标開始画入bg
        //draw fg into
        cv.drawBitmap(foreground, 0, 0, null);//在 0,0坐标開始画入fg ,能够从任何位置画入
        //save all clip
        cv.save(Canvas.ALL_SAVE_FLAG);//保存
        //store
        cv.restore();//存储
        return newbmp;
   }

	/**
	 * 上一首
	 */
	public void previous(int resourceId){

//		mAniAlphaAvatarHide.start();
//		mAniAlphaDiscBgHide.start();
		pause();
		changeImage(resourceId);
//		pause();
//		initAvatarAnimation(0f);
//		initDiscAnimation(0f);
//		initNeedleAnimation(0f);
//		play();
	}

	public boolean isPlay() {
		return isPlay;
	}

	public void setPlay(boolean isPlay) {
		this.isPlay = isPlay;
	}

	/**
	 * 初始化旋转封面动画对象
	 * @param start
	 */
	private void initAvatarAnimation(float start){
		mAniAvatar = ObjectAnimator.ofFloat(mAvatar, "rotation", start, 360f + start);
		mAniAvatar.addUpdateListener(new AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				mValueAvatar = (Float) animation.getAnimatedValue("rotation");
				Log.e("", "角度 : "+ mValueAvatar);
			}
		});
		mAniAvatar.setDuration(ROTATE_TIME);
		mAniAvatar.setInterpolator(new LinearInterpolator());
		mAniAvatar.setRepeatCount(ROTATE_COUNT);

	}

	/**
	 * 初始化旋转磁盘动画对象
	 * @param start
	 */
	/*private void initDiscAnimation(float start){
		mAniDisc = ObjectAnimator.ofFloat(mDisc, "rotation", start, 360f + start);
		mAniDisc.addUpdateListener(new AnimatorUpdateListener() {

			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				mValueDisc = (Float) animation.getAnimatedValue("rotation");
			}
		});
		mAniDisc.setDuration(ROTATE_TIME);
		mAniDisc.setInterpolator(new LinearInterpolator());
		mAniDisc.setRepeatCount(ROTATE_COUNT);

	}*/

	/**
	 * 初始化唱针动画
	 * @param start
	 */
	private void initNeedleAnimation(float start) {
		mAniNeedle = ObjectAnimator.ofFloat(mNeedle, "rotation", start, NEEDLE_RADIUS-start).setDuration(NEEDLE_TIME);
	}
}

源代码下载:http://download.csdn.net/detail/u013651247/8270811

时间: 2024-10-09 23:37:38

仿网易云音乐播放器(磁盘转圈、背景虚化等等)的相关文章

零基础实现网易云音乐播放器

H5增加了很多的标签,面试的时候,如果面试官问你H5都有哪些新标签,你回答header.footer.nav.这么回答几乎是无效的,因为这些标签在H5里面的角色,相当于鸡骨头.鱼刺.蘑菇腿--全是鸡肋,至少你得答出来audio.video.canvas,这些才是H5的核心功能,本文我们就重点说一下audio.audio广泛的应用于各种项目中,游戏背景.各种播放器,可以说有声音的地方就有audio,当然因为各种限制和坑,很容易让前端人员陷入尴尬,比如在iphone下audio 是不允许autopl

Swift版本仿网易云音乐播放音乐动画效果

个人技术博客站欢迎您 创建一个继承于UIView的视图我们叫他XTActivityView /// 立方柱的个数 var numberOfRect = 0; /// 立方柱的颜色 var rectBackgroundColor: UIColor? /// 立方柱初始化大小 var defaultSize: CGSize? /// 立方柱之间的间距 var space: CGFloat = 0.0 进行初始化 override init(frame: CGRect) { super.init(fr

仿网易云音乐的播放进度条

仿网易云音乐的播放进度条,有三种状态:播放.暂停和拖动,只是实现了动画和主要的交互逻辑,其他细节(如暂停音乐的播放等)还需要自己完善: DKPlayerBar 是继承于UIControl的,如果想获取播放\暂停的事件建议用标准的addTarget方法: [playerBar addTarget:self action:@selector(playOrPause) forControlEvents:UIControlEventValueChanged]; 然后在DKPlayerBar里监听DKPl

Android实战之酷云--&gt;仿网易云音乐开发

我的个人网站 Xuejianxin's Blog Google Blog Xuejianxin's Blog Android自定义View学习 Android自定义View之常用工具源码分析 Android自定义View之onMeasure()源码分析 Android自定义View之onLayout()源码分析 Android自定义View之对TouchEvent的处理 Android自定义View之draw原理分析 如果觉得我的文章还行的话,也可以关注我的公众号,里面也会第一时间更新,并且会有

C# WPF 低仿网易云音乐(PC)歌词控件

原文:C# WPF 低仿网易云音乐(PC)歌词控件 提醒:本篇博客记录了修改的过程,废话比较多,需要项目源码和看演示效果的直接拉到文章最底部~ 网易云音乐获取歌词的api地址 http://music.163.com/api/song/media?id=歌曲ID 填写歌曲的id即可获取到json格式的数据(歌曲ID获取的方法是:点击分享按钮>其他分享>复制链接,就可以在链接中看到了): {"songStatus":0,"lyricVersion":10,

《云阅》一个仿网易云音乐UI,使用Gank.Io及豆瓣Api开发的开源项目

CloudReader 一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目.项目采取的是Retrofit + RxJava + MVVM-DataBinding架构开发.开发中所遇到的各种问题已归纳在这里. github地址:CloudReader What can be learned about this project 那么,从本项目中你能学到哪些知识呢? 1.干货集中营内容与豆瓣电影书籍内容. 2.高仿网易云音乐歌单

关于仿酷狗音乐播放器开源:寻求一套音乐播放器素材,让仿酷狗开源

转载请说明原出处,谢谢~~ 距离公布測试版的仿酷狗音乐播放器.已经几个月过去了.期间非常多网友加我QQ来问我开源的问题,我也早有开源意向. 但我也一直没有得到可靠的信息,保证开源后没有不论什么问题. 所以我打算给这个软件全然换一套界面素材.放弃原来的酷狗素材. 这样开源也就没有不论什么问题了,问题是我个人PS水平太烂.仅仅会切切图.如今寻求一套完整的音乐播放器的素材,素材内容要全面,能够用来替代酷狗的素材. 假设有哪位朋友有这种素材,或者有时间能够做出一套素材让我使用,我将感激不尽.素材替换完成

仿酷狗音乐播放器开发日志二十一 开发动态调色板控件(附源代码)

转载请说明原出处,谢谢~~ 上一篇仿酷狗日志结束后,整个换肤功能就仅仅剩下调色板功能没有做了.我本以为会非常easy.可是研究了酷狗的调色板功能后发现不是那么简单的事情.首先看一下酷狗的调色板的样子: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemh1aG9uZ3NodQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" > waterm

仿酷狗音乐播放器已开源!

转载请说明原出处,谢谢:http://blog.csdn.net/zhuhongshu/article/details/41037875 距离我发布测试版的Redrain音乐盒(仿酷狗播放器),现在正好刚2个月.博客留言和QQ群里也一直有网友关心这个小项目开源的问题.先感谢网友对这个小项目的支持.之前我一直担心版权问题而没有开源这个项目,因为我只是个在校大学生,不想惹麻烦,希望大家体谅! 关于这个Redrain音乐盒的发布程序的说明和使用方法,见<Redrain仿酷狗音乐播放器开发完毕,发布测试