Android笔记 之 旋转木马的音乐效果

一、前言——

大家一定在百度音乐上在线听过歌,有没有注意到那个旋转唱片——

就上面那个,当音乐在播放的时候,那个光碟轮子在转,就想旋转木马一般。感觉好好玩啊。

碰巧想起前阵子做音乐播放器,哎,那这个也可以做在手机的音乐播放器上,这样就代替了进度条了。

一想到,就兴奋,于是,首先画圆形,然后放置背景图片,然后使用动画旋转。当音乐播放时,同时

开始播放圆形图片的动画,当音乐暂停时,暂停旋转;当音乐停止播放时,就停止动画,图片回到原点。

二、效果——

三、源码——

(1)MainActivity

<span style="font-size:18px;">public class MainActivity extends Activity {
	MediaPlayer m1;
	ImageView infoOperatingIV;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		infoOperatingIV = (ImageView) findViewById(R.id.infoOperating);

		Button play = (Button) findViewById(R.id.play);
		Button stop = (Button) findViewById(R.id.stop);

		play.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				playMusic();
			}
		});

		stop.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				stopMusic();
			}
		});

	}

	private void playMusic() {
		m1 = MediaPlayer.create(this, R.raw.quiet);
		m1.start();

		Animation operatingAnim = AnimationUtils.loadAnimation(this, R.anim.tip);
		LinearInterpolator lin = new LinearInterpolator();
		operatingAnim.setInterpolator(lin);
		if (operatingAnim != null) {
			infoOperatingIV.startAnimation(operatingAnim);
		}

		m1.setOnCompletionListener(new OnCompletionListener() {
			@Override
			public void onCompletion(MediaPlayer mp) {
				mp.stop();
				infoOperatingIV.clearAnimation();
			}
		});
	}

	private void stopMusic() {
		m1.stop();
		infoOperatingIV.clearAnimation();
	}

}</span><span style="font-size: 16pt;">
</span>

(2)画圆的控件,这部分代码参考了网友的。

<span style="font-size:18px;">public class RoundImageView extends ImageView {
	private int mBorderThickness = 0;
	private Context mContext;
	private int defaultColor = 0xFFFFFFFF;
	// 如果只有其中一个有值,则只画一个圆形边框
	private int mBorderOutsideColor = 0;
	private int mBorderInsideColor = 0;
	// 控件默认长、宽
	private int defaultWidth = 0;
	private int defaultHeight = 0;

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

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

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

	private void setCustomAttributes(AttributeSet attrs) {
		TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview);
		mBorderThickness = a.getDimensionPixelSize(R.styleable.roundedimageview_border_thickness, 0);
		mBorderOutsideColor = a.getColor(R.styleable.roundedimageview_border_outside_color, defaultColor);
		mBorderInsideColor = a.getColor(R.styleable.roundedimageview_border_inside_color, defaultColor);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		Drawable drawable = getDrawable();
		if (drawable == null) {
			return;
		}

		if (getWidth() == 0 || getHeight() == 0) {
			return;
		}
		this.measure(0, 0);
		if (drawable.getClass() == NinePatchDrawable.class)
			return;
		Bitmap b = ((BitmapDrawable) drawable).getBitmap();
		Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
		if (defaultWidth == 0) {
			defaultWidth = getWidth();

		}
		if (defaultHeight == 0) {
			defaultHeight = getHeight();
		}
		// 保证重新读取图片后不会因为图片大小而改变控件宽、高的大小(针对宽、高为wrap_content布局的imageview,但会导致margin无效)
		// if (defaultWidth != 0 && defaultHeight != 0) {
		// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
		// defaultWidth, defaultHeight);
		// setLayoutParams(params);
		// }
		int radius = 0;
		if (mBorderInsideColor != defaultColor && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框
			radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - 2 * mBorderThickness;
			// 画内圆
			drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor);
			// 画外圆
			drawCircleBorder(canvas, radius + mBorderThickness + mBorderThickness / 2, mBorderOutsideColor);
		} else if (mBorderInsideColor != defaultColor && mBorderOutsideColor == defaultColor) {// 定义画一个边框
			radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness;
			drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor);
		} else if (mBorderInsideColor == defaultColor && mBorderOutsideColor != defaultColor) {// 定义画一个边框
			radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness;
			drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderOutsideColor);
		} else {// 没有边框
			radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2;
		}
		Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius);
		canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight / 2 - radius, null);
	}

	/**
	 * 获取裁剪后的圆形图片
	 *
	 * @param radius
	 *            半径
	 */
	public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) {
		Bitmap scaledSrcBmp;
		int diameter = radius * 2;

		// 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片
		int bmpWidth = bmp.getWidth();
		int bmpHeight = bmp.getHeight();
		int squareWidth = 0, squareHeight = 0;
		int x = 0, y = 0;
		Bitmap squareBitmap;
		if (bmpHeight > bmpWidth) {// 高大于宽
			squareWidth = squareHeight = bmpWidth;
			x = 0;
			y = (bmpHeight - bmpWidth) / 2;
			// 截取正方形图片
			squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight);
		} else if (bmpHeight < bmpWidth) {// 宽大于高
			squareWidth = squareHeight = bmpHeight;
			x = (bmpWidth - bmpHeight) / 2;
			y = 0;
			squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight);
		} else {
			squareBitmap = bmp;
		}

		if (squareBitmap.getWidth() != diameter || squareBitmap.getHeight() != diameter) {
			scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, diameter, true);

		} else {
			scaledSrcBmp = squareBitmap;
		}
		Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		Paint paint = new Paint();
		Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight());

		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setDither(true);
		canvas.drawARGB(0, 0, 0, 0);
		canvas.drawCircle(scaledSrcBmp.getWidth() / 2, scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(scaledSrcBmp, rect, rect, paint);

		bmp = null;
		squareBitmap = null;
		scaledSrcBmp = null;
		return output;
	}

	/**
	 * 边缘画圆
	 */
	private void drawCircleBorder(Canvas canvas, int radius, int color) {
		Paint paint = new Paint();
		/* 去锯齿 */
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setDither(true);
		paint.setColor(color);
		/* 设置paint的 style 为STROKE:空心 */
		paint.setStyle(Paint.Style.STROKE);
		/* 设置paint的外框宽度 */
		paint.setStrokeWidth(mBorderThickness);
		canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint);
	}

}</span><span style="font-size: 16pt;">
</span>

Android笔记 之 旋转木马的音乐效果,布布扣,bubuko.com

时间: 2024-08-07 00:14:38

Android笔记 之 旋转木马的音乐效果的相关文章

Android笔记之 Web Service 基础

一.Web Service是什么? 就是网络服务,根据W3C的定义,WebServices(Web服务)是一个用于支持网络间不同机器互操作的软件系统,它是一种自包含.自描述和模块化的应用程序,它可以在网络中被描述.发布和调用,可以将它看作是基于网络的.分布式的模块化组件.  Web Services是建立在通用协议的基础之上的,包括HTTP.SOAP.UDDI.WSDL等.其中Web Service三要素就是SOAP.WSDL和UDDI. SOAP用来描述传递信息的格式, WSDL用来描述如何访

Android笔记:SurfaceView与SurfaceHolder对象

摘要 调试Media播放时,不时用到SurfaceView与SurfaceHolder对象,写case测试及实际运行效果, 基本上搞清楚这两个对象的用法及区别 1.SurfaceView public class SurfaceView extends View SurfaceView是视图(View)的继承类, 这个视图里内嵌了一个专门用于绘制 调试Media播放时,不时用到SurfaceView与SurfaceHolder对象,写case测试及实际运行效果, 基本上搞清楚这两个对象的用法及区

Android笔记之 TTS中文发音

1.TTS 就是 Text to Speech ,把文本内容变为语音. 谷歌在Android 1.6 开始就支持TTS 了,但是可惜,只是支持英语法语德语等五种语言,唯独丫丫的木有我们中文. 所以,我们只能另外自己开发中文语音包程序. 目前主要有以下几种中文TTS . (1)开源项目 eyes-free  ,链接是:  http://code.google.com/p/eyes-free/ 在手机上安装了eyes-free  提供的   TTS Service Extended.apk 文件后,

Android笔记——Bitmap自动取色(纯搬运)

说明: 这个是一个老外写的自动自动从bitmap中取主色与第二主色的工具类,稍微研究了下用法,但感觉效果一般,记录下. 感兴趣的同学可以自行研究下,老外的代码没注释,这点给黄老师我造成的困惑不少. 顺便附上老外的github地址:https://gist.github.com/chrisbanes/ba8e7b9ec0e40f6949c6 大概的用法: 1 image = (ImageView)findViewById(R.id.image); 2 Bitmap bitmap = BitmapF

Android笔记:百度地图与高德地图坐标转换问题

Android笔记:百度地图与高德地图坐标转换问题 安卓项目使用了百度地图的定位SDK,web端使用的也是百度地图, 后来发现界面显示百度地图不如高德效果好,web改用高德地图,原本的百度地图坐标是可以直接使用的,由于高德和百度地图的坐标系不一致 要如何转换呢. 补充了下坐标系知识后发现高德使用的坐标系是“gcj02”也就是大家所说的“火星坐标”, 百度使用的是“BD09”因为是百度所用大家习惯称之为“百度坐标”  ,如何将bd09转为gcj02呢,突然想到在百度的定位sdk里有这样一段说明(来

Android Fragment应用实战(音乐播放器界面)

当下很多手机应用都会有一个非常类似的功能,即屏幕的下方显示一行Tab标签选项,点击不同的标签就可以切换到不同的界面,如以下几个应用所示: 以上底部这四个标签,每一个分别对应一个Fragment,这种底部标签式的布局策略真的非常常见,那么话说回来,这种效果到底是如何的呢?熟悉Android的朋友一定都会知道,很简单嘛,使用TabHost就OK了!但是殊不知,TabHost并非是那么的简单,它的可扩展性非常的差,不能随意地定制Tab项显示的内容,而且运行还要依赖于ActivityGroup.Acti

Android笔记之 开机自启动

在项目中用到开机自动运行功能,因此学习了下,在此作为笔记记录下. 主要是以下4个步骤: 1.原理了解: 通过搜查资料发现,当Android启动时,会发出一个系统广播,内容为ACTION_BOOT_COMPLETED,它的字符串常量表示为android.intent.action.BOOT_COMPLETED,因此我们只需要在自己的应用中接收这个广播,然后启动APP即可. 2.编写接收器 既然是接收广播,必然是要用广播接收器,因此新建一个继承自广播BroadcastReceiver的类来专门接收上

Android高斯模糊技术,实现毛玻璃效果(转)

本博客转自郭霖公众号:http://mp.weixin.qq.com/s?__biz=MzA5MzI3NjE2MA==&mid=2650235930&idx=1&sn=e328709c41ae208a9e41ef79d38cbeed&scene=24&srcid=09104fpQDG98JcRcUB9Ec7BN#wechat_redirect http://blog.csdn.net/grp0916/article/details/50494712 Android高

android笔记1——开发环境的搭建

Long Long ago...已经成为了历史,我还是要说出一个真相:早年前,那时候,android还不被大众所认知的时候,当然开发者也没不像现在那样趋于饱和状态.一位大牛前辈,也是我的学长,那时候我还在上大学.前辈告诫我有时间得去看看android开发,那时候的自己,年轻.冲动.不畏惧,毅然地选择了java服务端开发,放弃了学习android开发. 时隔数年的今天,因为公司业务项目的发展,我还是得去做android开发工作...虽然这几年间断断续续的看了些android开发,但是将成为历史的今