AudioRecorderButton
State:STATE_NORMAL, STATE_RECORDING, STATE_WANT_TO_CANCEL
DialogManager
Style:RECORDING, WANT_TO_CANCEL, TOO_SHORT
AudioManager
prepare();
cancel();
release();
getVoiceLeval();
class AudioRecorderButton {
onTouchEvent() {
DOWN:
changeButtonState(STATE_RECORDING);
Longclick -> AudioManager.prepare() ->
end prepared -> DIalogManager.showDialog(RECORDING)
MOVE:
if (wantCancel(x, y) {
DialogManager.showDialog(WANT_TO_CANCEL)
changeButtonState(STATE_WANT_TO_CANCEL);
} else {
DialogManager.showDialog(RECORDING)
changeButtonState(STATE_RECORDING);
}
UP:
if (wantCancel == curState) {
AudioManager.cancel();
}
if (STATE_RECORDING == curState) {
AudioManager.release();
callbackToActivity(url, time);
}
}
}
实现自定义语音按钮
strings.xml
<resources>
<string name="app_name">RecorderDemo</string>
<string name="action_settings">Settings</string>
<string name="str_recorder_normal">按住 说话</string>
<string name="str_recorder_recording">松开 结束</string>
<string name="str_recorder_want_cancel">松开手指,取消发送</string>
</resources>
btn_recording_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffff"/>
<stroke android:color="#9b9b9b" android:width="1px"/>
<corners android:radius="3dp"/>
</shape>
btn_recording.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#eeeeee"/>
<stroke android:color="#9b9b9b" android:width="1px"/>
<corners android:radius="3dp"/>
</shape>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/id_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ebebeb"
android:divider="@null"
android:dividerHeight="10dp">
</ListView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.recorderdemo.view.AudioRecorderButton
android:id="@+id/id_recorder_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="7dp"
android:gravity="center"
android:padding="5dp"
android:text="@string/str_recorder_normal"
android:minHeight="0dp"
android:textColor="#727272"
android:background="@drawable/btn_recorder_normal">
</com.example.recorderdemo.view.AudioRecorderButton>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ccc">
</View>
</FrameLayout>
</LinearLayout>
AudioRecorderButton
public class AudioRecorderButton extends Button {
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 int mCurState = STATE_NORMAL;
//已经开始录音
private boolean isRecording = false;
public AudioRecorderButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AudioRecorderButton(Context context) {
this(context, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
//TODO 用于测试
isRecording = true;
chanegState(STATE_RECORDING);
break;
case MotionEvent.ACTION_MOVE:
if (isRecording) {
//根据x, y的坐标,判断是否想要取消
if (wantToCancel(x, y)) {
chanegState(STATE_WANT_TO_CANCEL);
} else {
chanegState(STATE_RECORDING);
}
}
break;
case MotionEvent.ACTION_UP:
if (mCurState == STATE_RECORDING) {
//release
//callbackToAct
} else if (mCurState == STATE_WANT_TO_CANCEL) {
//cancel
}
reset();
break;
}
return super.onTouchEvent(event);
}
/**
* 恢复状态及标志位
*/
private void reset() {
isRecording = false;
chanegState(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 chanegState(int state) {
if (mCurState != state) {
mCurState = state;
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_recording);
setText(R.string.str_recorder_recording);
if (isRecording) {
//TODO Dialog.recording();
}
break;
case STATE_WANT_TO_CANCEL:
setBackgroundResource(R.drawable.btn_recording);
setText(R.string.str_recorder_want_cancel);
//TODO Dialog.wantCancel();
break;
}
}
}
}