BlowWind

Android吹风车效果
最近闲来无事,在网上看到一遍文章,写的是模拟吹气实现风车效果,感觉还不错,自己也尝试着写了下,效果如下

主要思路是: 通过AudioRecord计算出声音分贝,AudioManagerSensor发送通知风车实现转动,(先判断风车是不是正在转动,不是则开启一个匀速转动风车的线程,同时开启一个加速线程和一个等待线程,等待线程会计时,计时到300ms便停止加速开始减速,减速中又开始吹气的话停止减速,开启加速,并重新计时,Handler每次收到AudioManagerSensor的消息都会重置 记时变量。 持续吹气会一直加速,一旦停止吹气,就会开始减速;

package com.blowwind.project;/*** Created by marven on 2017/12/13.* 240902545@qq.com*/
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;import com.blowwind.project.Sensor.AudioManagerSensor;
import com.blowwind.project.Sensor.MySensor;public class MainActivity extends Activity implements View.OnTouchListener{private ImageView mWindmillImg;private Button mBlowBtn;private MySensor blowSenser;private boolean isBlowing;private boolean isBegin;private float blowAngle;private int blowTime;public static final int BLOW_START = 0;public static final int BLOWING = 1;public static final int BLOW_END = 2;private boolean isReset;private boolean isPause;DisplayMetrics dm;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);initLayout();initData();blowSenser = AudioManagerSensor.getInstance(handler);}public void initData() {isPause = false;//是否进入onPauseisBlowing = false;//转动线程是否已开启isBegin = false;//是否按住吹起按钮blowAngle = 0;//每一帧旋转的角度isReset = false;//是否补气}Handler handler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {switch (msg.what) {case BLOW_START:if (isBegin) {//收到吹气通知,重置部分标识if (!isReset)isReset = true;if (blowTime > 0)blowTime = 0;if (!isBlowing) {//如果吹起线程没有开启,则开启新的线程isBlowing = true;new Thread(new blowRun()).start();}}break;case BLOWING://更新UImWindmillImg.setRotation(blowAngle);break;case BLOW_END://转动停止isBlowing = false;break;}return false;}});protected void initLayout() {//获得控件mWindmillImg = (ImageView) this.findViewById(R.id.activity_blow_windmill);mBlowBtn = (Button) this.findViewById(R.id.activity_blow_btn);mBlowBtn.setOnTouchListener(this);RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);int btnWidth = dm.heightPixels / 6;layoutParams.width = btnWidth;//设置宽高layoutParams.height = btnWidth;layoutParams.setMargins((dm.widthPixels - btnWidth) / 2, dm.heightPixels / 6 * 4, 0, 0);mBlowBtn.setLayoutParams(layoutParams);}@Overrideprotected void onStart() {super.onStart();isPause = false;blowSenser.start();}@Overrideprotected void onPause() {super.onPause();blowSenser.shutDown();isPause = true;}@Overrideprotected void onDestroy() {blowSenser.destory();super.onDestroy();}private float rotationAngle = 1f;//转动风车class blowRun implements Runnable {@Overridepublic void run() {new Thread(new stopRun()).start();new Thread(new rotationRun()).start();while (isBlowing && !isPause) {blowAngle += rotationAngle;if (blowAngle > 360) {blowAngle = 1;}handler.sendEmptyMessage(BLOWING);try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}}}//控制加速class rotationRun implements Runnable {@Overridepublic void run() {while (isReset && !isPause) {if (rotationAngle <= 10) {rotationAngle += 0.4;}try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}}//控制减速class stopRun implements Runnable {@Overridepublic void run() {while (blowTime <= 2 && !isPause) {blowTime++;try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}isReset = false;while (rotationAngle > 0 && !isReset && !isPause) {rotationAngle -= 0.4;try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}if (isReset) {new Thread(new stopRun()).start();new Thread(new rotationRun()).start();} else {handler.sendEmptyMessage(BLOW_END);}}}@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_UP) {isBegin = false;}if (event.getAction() == MotionEvent.ACTION_DOWN) {isBegin = true;}return false;}
}

AudioManagerSensor

package com.blowwind.project.Sensor;import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Handler;
import android.util.Log;import com.blowwind.project.MainActivity;/*** Created by marven on 2017/12/13.* 240902545@qq.com*/public class AudioManagerSensor extends MySensor {private static AudioManagerSensor mAudioSensor = null;static final int SAMPLE_RATE_IN_HZ = 8000;static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);AudioRecord mAudioRecord;boolean isGetVoiceRun;//是否正在录音private Handler mHandler;private AudioManagerSensor(Handler handler) {super();this.mHandler = handler;isGetVoiceRun = false;mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT,AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE);}public static AudioManagerSensor getInstance(Handler handler) {if (mAudioSensor == null) {synchronized (AudioManagerSensor.class) {if (mAudioSensor == null) {mAudioSensor = new AudioManagerSensor(handler);}}}return mAudioSensor;}@Overridepublic void start() {if (isGetVoiceRun) {return;}if (mAudioRecord == null) {throw new NullPointerException("mAudioRecord初始化失败!");}isGetVoiceRun = true;new Thread(new Runnable() {@Overridepublic void run() {mAudioRecord.startRecording();short[] buffer = new short[BUFFER_SIZE];while (isGetVoiceRun) {//record是实际读取的数据长度,一般而言record会小于buffersizeint record = mAudioRecord.read(buffer, 0, BUFFER_SIZE);long v = 0;// 将 buffer 内容取出,进行平方和运算for (int i = 0; i < buffer.length; i++) {v += buffer[i] * buffer[i];}// 平方和除以数据总长度,得到音量大小。double mean = v / (double) record;double volume = 10 * Math.log10(mean);
//                    if (needVolume > 0) {//采集平均值不太稳定(iPhone非常稳定)这里用定值if (volume > 75) {mHandler.sendEmptyMessage(MainActivity.BLOW_START);}synchronized (mLock) {try {mLock.wait(100);} catch (InterruptedException e) {e.printStackTrace();}}}if (mAudioRecord != null) {mAudioRecord.stop();}}}).start();}@Overridepublic void shutDown() {isGetVoiceRun = false;}@Overridepublic void destory() {if (mAudioRecord != null) {mAudioRecord.release();mAudioRecord = null;}mAudioSensor = null;}
}

MySensor

package com.blowwind.project.Sensor;import android.content.Context;
import android.hardware.SensorManager;
import android.os.Handler;/*** Created by marven on 2017/12/13.* 240902545@qq.com*/public abstract class MySensor {Object mLock;SensorManager sensorManager;Context hostContext;Handler mHandler;public MySensor(Context context, Handler mHandler) {mLock = new Object();this.mHandler = mHandler;hostContext = context;sensorManager = (SensorManager) hostContext.getSystemService(hostContext.SENSOR_SERVICE);}public MySensor() {mLock = new Object();}public abstract void start();public abstract void shutDown();public abstract void destory();
}

下载地址https://github.com/marven88cn/BlowWind

Android吹风车效果相关推荐

  1. android 下拉窗帘,Android 窗帘(Curtain)效果二之波浪式动态扭曲效果

    上一篇文章已经实现了如何把一张图片扭曲成波浪效果,那么这一篇文章我们介绍如何动态调整系数,去改变波浪图片的皱褶成度.我们自一次观察下图morning routine的效果: 仔细观察我们发现,当往右滑 ...

  2. Android m 自定义下拉菜单,Android实现动画效果的自定义下拉菜单功能

    我们在购物APP里面设置收货地址时,都会有让我们选择省份及城市的下拉菜单项.今天我将使用Android原生的 Spinner 控件来实现一个自定义的下拉菜单功能,并配上一个透明渐变动画效果. 要实现的 ...

  3. android 卡片旋转动画,Android 卡片翻转效果

    Android 卡片翻转效果使用的Cramre来完成 记录一下: 一个好用的3D旋转工具类 oid.graphics.Matrix; import android.util.Log; import a ...

  4. 【Android源代码下载】收集整理android界面UI效果源码

    在Android开发中,Android界面UI效果设计一直都是很多童鞋关注的问题,今天给大家分享下大神收集整理的多个android界面UI效果,都是源码,都是干货,贡献给各位网友! 话不多说,直接上效 ...

  5. android 动态创建view,react-native动态创建Android View 无效果

    问题描述 react-native动态创建Android View 无效果,我想在react-native里面直接点击函数进行创建,也就是通过module中的方法创建View 问题出现的环境背景及自己 ...

  6. android 移动拼图效果实现

    android 移动拼图效果实现 代码地址: https://github.com/tingsky9985/Puzzle

  7. android中倒计时动画,Android实现倒计时效果

    本文实例为大家分享了Android实现倒计时效果的具体代码,供大家参考,具体内容如下 一个倒计时的效果 先看效果图: 直接上代码: 这里是关于倒计时 -天时分秒-的逻辑判断 /** * 倒计时计算 * ...

  8. Android 实现指南针效果

    Android 实现指南针效果 前一段时间在做指南针,于是想偷偷懒.在网上直接找一个Demo.然后改改旧差不多了.可是看到的效果却和预期的差太多了,所以就不得不自己撸一个: 大致上会用到内容 自定义V ...

  9. Android 吸入动画效果详解(仿mac退出效果)

    转载自:http://m.blog.csdn.net/blog/leehong2005/9127095 [转]Android 吸入动画效果详解 1,背景 吸入(Inhale)效果,最初我是在iOS上面 ...

最新文章

  1. java newline_Java BufferedWriter.newLine()方法示例
  2. Linux 内核中的 Device Mapper 机制
  3. 看一家公司发展得如何就看这家公司的财务部门
  4. js 调用C#.NET后台方法 转载自:http://www.cnblogs.com/lizhao/archive/2010/11/23/1990436.html...
  5. 【转】Hibernate和IBatis对比
  6. PaddlePaddle训练营——公开课——AI核心技术掌握——第1章迈入现代人工智能的大门——Modern AI骨架脉络
  7. Mysql bat脚本编写_第一次编写bat脚本
  8. java同步方法同步块_java使用同步方法和同步块的区别
  9. matlab销量预测的数学模型,数学建模:酒店最优化问题.用matlab算出《酒店价格预测模型》...
  10. linux 访问samba共享文件夹权限,请教:linux下 利用samba网络共享文件夹修改权限的问题...
  11. 二、Sql Server 基础培训《进度2-关于主键(知识点学习)》
  12. [.NET开发] NPOI导出
  13. 考勤系统 服务器管理,考勤管理系统ZKNet Web Server管理
  14. 实验用USB转RS-232下载线制作
  15. Java中的日期和时间
  16. 民间53个不传之密 ,看了不后悔
  17. Java可变参数的基本使用
  18. 动手学深度学习笔记3.4+3.5+3.6+3.7
  19. 变革中的微软:裁员7800人,对诺基亚业务减记76亿美元
  20. 1024程序员节Keep裁员两三百人

热门文章

  1. 奥运、NBA、UCF等,30+个体育比赛数据集
  2. c++ array容器 传参_香港城市大学支春义AEM:磷烯正极材料助力于高电压、抗自放电锌离子混合超级电容器...
  3. 论文阅读:基于用户上网数据的电影个性化推荐系统研究
  4. mybatis一对多sql写法
  5. 使用python将将接口data修改为键值对格式
  6. 链接redis清空指定库数据
  7. Matlab2018安装成功后,打开出现licensing error:-8523解决方法
  8. cocos2d-x - 2d跑酷游戏地图素材(TiledMap)
  9. Tensorflow使用CPU, 不用GUP
  10. python爬上去飞卢_pyhon3爬虫爬取飞卢小说网小说