本实例是学习慕课网的《仿微信语音聊天》,得到的代码,尚未做过多的修改,自用
自定义Button
主要实现
- onTouchEvent的三种状态:被按下,抬起,移动的按钮样式变换及Dialog的更换图片。
- 处理录音状态,分几种情况
- 按下按钮时间太短以至于未唤醒长按事件
- 按下按钮时间太短以至于录音机还未准备好
- 按下按钮时间太短不到0.6秒(也可以是一秒)
- 正常结束
- 想要取消
- 回调
- 准备好录音后回调给AudioManger
- activity录好了回调给自己
package com.sjy.myrecorder.view;
import com.sjy.myrecorder.R;
import com.sjy.myrecorder.view.AudioManager.AudioStateListener;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
public class RecorderButton extends Button implements AudioStateListener {
private static final int DISTANCE_Y_CANCEL = 50;
private static final int STATE_NORMAL = 1;
private static final int STATE_RECORDING = 2;
private static final int STATE_WANT_TO_CANCEL = 3;
private AudioManager mAudioManager;
private boolean mReady = false;
private String mDir;
private int mRecState = STATE_NORMAL;
private boolean isRecording;
private DialogManager mDialogManager;
private float mTime;
public RecorderButton(Context context, AttributeSet attrs) {
super(context, attrs);
mDialogManager = new DialogManager(getContext());
//if(Util.isSdCardReadable()){
mDir = Environment.getExternalStorageDirectory() + "/collectfun_recorder/";
//}
mAudioManager = AudioManager.getInstance(mDir);
mAudioManager.setOnAudioStateListener(this);
setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mReady = true;
mAudioManager.prepareAudio();
return false;
}
});
}
/**
* 录音完成的回调
* @author asus
*
*/
public interface AudioFinishRecordListener {
void onFinsh(float seconds,String path);
}
private AudioFinishRecordListener mListener;
public void setAudioFinishRecordListener(AudioFinishRecordListener listener) {
mListener = listener;
}
private Runnable mGetAudioLevelRunnable = new Runnable() {
@Override
public void run() {
while(isRecording) {
try {
Thread.sleep(100);
mTime += 0.1f;
handler.sendEmptyMessage(MSG_VOICE_CHANGED);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
private static final int MSG_AUDIO_PREPARED = 0x110;
private static final int MSG_VOICE_CHANGED = 0x111;
private static final int MSG_DIALOG_DISMISS = 0x112;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_AUDIO_PREPARED:
// TODO end preper 后显示
mDialogManager.showDialog();
isRecording = true;
new Thread(mGetAudioLevelRunnable).start();
break;
case MSG_VOICE_CHANGED:
mDialogManager.updateVoiceLevel(mAudioManager.getVoiceLevel(7));
break;
case MSG_DIALOG_DISMISS:
break;
}
}
};
@Override
public void wellPrepared() {
handler.sendEmptyMessage(MSG_AUDIO_PREPARED);
}
public RecorderButton(Context context) {
this(context, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int x = (int) event.getX();
int y = (int) event.getY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
changeState(STATE_RECORDING);
break;
case MotionEvent.ACTION_MOVE:
if (isRecording) {
if (wantTocancel(x, y)) {
changeState(STATE_WANT_TO_CANCEL);
} else {
changeState(STATE_RECORDING);
}
}
break;
case MotionEvent.ACTION_UP:
if(!mReady) { //未唤起onLongClick
reset();
return super.onTouchEvent(event);
}
if(!isRecording || mTime < 0.6f) {
mDialogManager.tooShort();
mAudioManager.cancel();
handler.sendEmptyMessageDelayed(MSG_DIALOG_DISMISS, 1300);
}else if (mRecState == STATE_RECORDING) {//正常录制结束
mDialogManager.dismissDialog();
if(mListener != null) {
mListener.onFinsh(mTime, mAudioManager.getCurrentFilePath());
}
mAudioManager.release();
} else if (mRecState == STATE_WANT_TO_CANCEL) {
mDialogManager.dismissDialog();
mAudioManager.cancel();
}
reset();
break;
}
return super.onTouchEvent(event);
}
private void reset() {
isRecording = false;
mReady = false;
mTime = 0;
changeState(STATE_NORMAL);
}
private boolean wantTocancel(int x, int y) {
if (x < 0 || x > getWidth()) {
return true;
}
if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
return true;
}
return false;
}
private void changeState(int state) {
if (state != mRecState) {
mRecState = state;
//isRecording = true;
switch (state) {
case STATE_NORMAL:
setBackgroundResource(R.drawable.btn_recorder_normal);
setText(R.string.str_recorder_normal);
break;
case STATE_RECORDING:
setBackgroundResource(R.drawable.btn_recorder_recording);
setText(R.string.str_recorder_recording);
if (isRecording) {
mDialogManager.recording();
}
break;
case STATE_WANT_TO_CANCEL:
setBackgroundResource(R.drawable.btn_recorder_recording);
setText(R.string.str_recorder_want_cancel);
mDialogManager.wantToCancel();
break;
}
}
}
}