Android吹风车效果

BlowWind

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

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

你可能感兴趣的:(源码类,android,android)