Android吹风车效果
最近闲来无事,在网上看到一遍文章,写的是模拟吹气实现风车效果,感觉还不错,自己也尝试着写了下,效果如下
package com.blowwind.project;
/**
* Created by marven on 2017/12/13.
* [email protected]
*/
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;
@Override
protected 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;//是否进入onPause
isBlowing = false;//转动线程是否已开启
isBegin = false;//是否按住吹起按钮
blowAngle = 0;//每一帧旋转的角度
isReset = false;//是否补气
}
Handler handler = new Handler(new Handler.Callback() {
@Override
public 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:
//更新UI
mWindmillImg.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);
}
@Override
protected void onStart() {
super.onStart();
isPause = false;
blowSenser.start();
}
@Override
protected void onPause() {
super.onPause();
blowSenser.shutDown();
isPause = true;
}
@Override
protected void onDestroy() {
blowSenser.destory();
super.onDestroy();
}
private float rotationAngle = 1f;
//转动风车
class blowRun implements Runnable {
@Override
public 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 {
@Override
public void run() {
while (isReset && !isPause) {
if (rotationAngle <= 10) {
rotationAngle += 0.4;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//控制减速
class stopRun implements Runnable {
@Override
public 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);
}
}
}
@Override
public 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.
* [email protected]
*/
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;
}
@Override
public void start() {
if (isGetVoiceRun) {
return;
}
if (mAudioRecord == null) {
throw new NullPointerException("mAudioRecord初始化失败!");
}
isGetVoiceRun = true;
new Thread(new Runnable() {
@Override
public void run() {
mAudioRecord.startRecording();
short[] buffer = new short[BUFFER_SIZE];
while (isGetVoiceRun) {
//record是实际读取的数据长度,一般而言record会小于buffersize
int 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();
}
@Override
public void shutDown() {
isGetVoiceRun = false;
}
@Override
public 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.
* [email protected]
*/
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