效果
屏幕錄制2021-02-01 下午5.gif
庫文件
使用到的庫有react-native-audio,teaset兩第三方庫,react-native-audio用來錄音,teaset中使用Toast展示錄音效果圖。
首先
主要說明一下這個效果,錄音功能最后說,向上代碼
export default class RecordView extends React.Component {
static key = null;
static show(text) {
let showIcon;
if (RecordView.key) RecordView.hide()
if (text == '松開手指取消發送') {
showIcon = (<Image source={icCancel} style={{ width: 100, height: 100 }} />)
} else {
showIcon = (
<Image source={icMic} style={{ width: 100, height: 100 }} />
);
}
RecordView.key = Toast.show({
text: (
<Text style={{ fontSize: 13, color: 'white' }}>
{text}
</Text>
),
icon: showIcon,
position: 'center',
duration: 1000000,
});
}
static hide() {
if (!RecordView.key) return;
Toast.hide(RecordView.key);
RecordView.key = null;
}
}
清晰明了,2個方法,一個顯示一個隱藏。里面包含兩張圖片icCancel和icMic, 用來展示。
其次
接下來就是如何調用這個方法來, 包括什么時機調用
this.Gesture = {
onStartShouldSetResponder: (evt) => true,
onMoveShouldSetResponder: (evt) => true,
onResponderGrant: (evt) => {
// console.log(evt);
this.setState(
{
isRecord: true,
recordTitle: '手指上滑動,取消發送',
isCancel: false,
currentPageY: evt.nativeEvent.pageY,
},
() => {
RecordToast.show(this.state.recordTitle);
this._record();
this.props.onScroll(false);
},
);
},
onResponderMove: (evt) => {
// console.log(evt);
if (evt.nativeEvent.pageY - this.state.currentPageY < -5) {
if (
this.state.isRecord &&
this.state.recordTitle == '手指上滑動,取消發送'
) {
this.setState(
{
recordTitle: '松開手指取消發送',
isCancel: true,
},
() => {
RecordToast.show(this.state.recordTitle);
},
);
}
} else if (evt.nativeEvent.pageY - this.state.currentPageY > 5) {
if (
this.state.isRecord &&
this.state.recordTitle == '松開手指取消發送'
) {
this.setState(
{
recordTitle: '手指上滑動,取消發送',
isCancel: false,
},
() => {
RecordToast.show(this.state.recordTitle);
},
);
}
} else {
if (!this.state.isRecord) {
this.setState(
{
isRecord: true,
recordTitle: '手指上滑動,取消發送',
isCancel: false,
},
() => {
RecordToast.show(this.state.recordTitle);
this._record();
this.props.onScroll(false);
},
);
}
}
},
onResponderRelease: (evt) => {
console.log('3333');
this.setState(
{
isRecord: false,
},
() => {
RecordToast.hide();
this._cancel(this.state.isCancel);
this.props.onScroll(true);
},
);
},
onResponderTerminationRequest: (evt) => false,
};
在componentDidMount方法中,初始化手勢識別代碼,復制給觸發事件的組件,
用來展示錄音圖片和取消圖片
<View
{...this.Gesture}
</View>
最后
進行錄音,引入頭文件
import {AudioRecorder, AudioUtils} from 'react-native-audio';
緊接著在componentDidMount方法中
AudioRecorder.onProgress = (data) => {
let temp = Math.floor(data.currentTime);
if (temp >= 60) {
this.setState(
{
isRecord: false,
recordTitle: '手指上滑動,取消發送',
},
() => {
RecordToast.hide();
Alert.alert('錄制時間不能超過60秒');
this._cancel(false);
this.props.onScroll(true);
},
);
} else {
this.setState({
currentTime: temp,
});
}
};
AudioRecorder.onFinished = (data) => {
};
進行堅挺錄音和結束的方法
錄音開始錄音
_record = async () => {
if(CommonUtils.ios) {
this.audioPath =
AudioUtils.CachesDirectoryPath + `${new Date().getTime()}.aac`;
} else {
this.audioPath = AudioUtils.DocumentDirectoryPath + `${new Date().getTime()}.aac`;
}
this.prepareRecordingPath(this.audioPath);
try {
const filePath = await AudioRecorder.startRecording();
return filePath;
} catch (error) {
console.log(error);
}
};
prepareRecordingPath = (audioPath) => {
AudioRecorder.prepareRecordingAtPath(audioPath, {
SampleRate: 22050,
Channels: 1,
AudioQuality: 'Low',
AudioEncoding: 'aac',
OutputFormat: 'aac_adts',
});
};
這個地方需要注意一下,因為存在路徑的問題, AudioUtils.CachesDirectoryPath是iOS的緩存路徑,在真機和模擬器上都可以找到,如果遇到無法錄音的情況,看下log大部分都是無法創建datafile之類的,說明路徑不對。
如果遇到android上傳不了文件的問題,注意看下log和路徑。一般都是類似這類問題
停止錄音和取消錄音
_cancel = (canceled) => {
this._stop();
if (canceled) return;
if (this.state.currentTime < 1) {
Alert.alert('錄制時間太短了');
setTimeout(() => {
RecordToast.hide();
}, 300);
return;
}
this.setState({currentTime: null});
setTimeout(() => {
// 上傳音頻文件,操作
}, 500);
};
_stop = async () => {
try {
const filePath = await AudioRecorder.stopRecording();
return filePath;
} catch (error) {}
};
到此大功告成。