效果

屏幕錄制2021-02-01 下午5.gif
庫(kù)文件
使用到的庫(kù)有react-native-audio,teaset兩第三方庫(kù),react-native-audio用來(lái)錄音,teaset中使用Toast展示錄音效果圖。
首先
主要說(shuō)明一下這個(gè)效果,錄音功能最后說(shuō),向上代碼
export default class RecordView extends React.Component {
static key = null;
static show(text) {
let showIcon;
if (RecordView.key) RecordView.hide()
if (text == '松開(kāi)手指取消發(fā)送') {
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個(gè)方法,一個(gè)顯示一個(gè)隱藏。里面包含兩張圖片icCancel和icMic, 用來(lái)展示。
其次
接下來(lái)就是如何調(diào)用這個(gè)方法來(lái), 包括什么時(shí)機(jī)調(diào)用
this.Gesture = {
onStartShouldSetResponder: (evt) => true,
onMoveShouldSetResponder: (evt) => true,
onResponderGrant: (evt) => {
// console.log(evt);
this.setState(
{
isRecord: true,
recordTitle: '手指上滑動(dòng),取消發(fā)送',
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 == '手指上滑動(dòng),取消發(fā)送'
) {
this.setState(
{
recordTitle: '松開(kāi)手指取消發(fā)送',
isCancel: true,
},
() => {
RecordToast.show(this.state.recordTitle);
},
);
}
} else if (evt.nativeEvent.pageY - this.state.currentPageY > 5) {
if (
this.state.isRecord &&
this.state.recordTitle == '松開(kāi)手指取消發(fā)送'
) {
this.setState(
{
recordTitle: '手指上滑動(dòng),取消發(fā)送',
isCancel: false,
},
() => {
RecordToast.show(this.state.recordTitle);
},
);
}
} else {
if (!this.state.isRecord) {
this.setState(
{
isRecord: true,
recordTitle: '手指上滑動(dòng),取消發(fā)送',
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方法中,初始化手勢(shì)識(shí)別代碼,復(fù)制給觸發(fā)事件的組件,
用來(lái)展示錄音圖片和取消圖片
<View
{...this.Gesture}
</View>
最后
進(jìn)行錄音,引入頭文件
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: '手指上滑動(dòng),取消發(fā)送',
},
() => {
RecordToast.hide();
Alert.alert('錄制時(shí)間不能超過(guò)60秒');
this._cancel(false);
this.props.onScroll(true);
},
);
} else {
this.setState({
currentTime: temp,
});
}
};
AudioRecorder.onFinished = (data) => {
};
進(jìn)行堅(jiān)挺錄音和結(jié)束的方法
錄音開(kāi)始錄音
_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',
});
};
這個(gè)地方需要注意一下,因?yàn)榇嬖诼窂降膯?wèn)題, AudioUtils.CachesDirectoryPath是iOS的緩存路徑,在真機(jī)和模擬器上都可以找到,如果遇到無(wú)法錄音的情況,看下log大部分都是無(wú)法創(chuàng)建datafile之類(lèi)的,說(shuō)明路徑不對(duì)。
如果遇到android上傳不了文件的問(wèn)題,注意看下log和路徑。一般都是類(lèi)似這類(lèi)問(wèn)題
停止錄音和取消錄音
_cancel = (canceled) => {
this._stop();
if (canceled) return;
if (this.state.currentTime < 1) {
Alert.alert('錄制時(shí)間太短了');
setTimeout(() => {
RecordToast.hide();
}, 300);
return;
}
this.setState({currentTime: null});
setTimeout(() => {
// 上傳音頻文件,操作
}, 500);
};
_stop = async () => {
try {
const filePath = await AudioRecorder.stopRecording();
return filePath;
} catch (error) {}
};
到此大功告成。