设为首页 加入收藏

TOP

Android仿微信录音功能,自定义控件的设计技巧(一)
2015-02-02 14:37:06 来源: 作者: 【 】 浏览:28
Tags:Android 录音 功能 定义 控件 设计 技巧

讲解一个比较通用的录音控件实现方法与设计技巧


最近由于需要做一个录音功能(/嘘 悄悄透露一下,千万别告诉红薯,就是新版本的OSC客户端噢),起初打算采用仿微信的录音方式,最后又改成了QQ的录音方式,之前的微信录音控件也就白写了[大哭]。之前有很多朋友在问我自定义控件应该怎么学习,遂正好拿出来讲讲喽,没来得及截效果图,大家就自己脑补一下微信发语音时的样子吧。


所谓自定义控件其实就是由于系统SDK无法完成需要的功能时,通过自己扩展系统组件达到完成所需功能做出的控件。


先看代码(篇幅有限,仅保留重要方法)


/**
?* 录音专用Button,可弹出自定义的录音dialog。需要配合{@link #RecordButtonUtil}使用
?* @author kymjs(kymjs123@gmail.com)
?*/
public class RecordButton extends Button {
? ? private static final int MIN_INTERVAL_TIME = 700; // 录音最短时间
? ? private static final int MAX_INTERVAL_TIME = 60000; // 录音最长时间
? ? private RecordButtonUtil mAudioUtil;
? ? private Handler mVolumeHandler; // 用于更新录音音量大小的图片
?
? ? public RecordButton(Context context) {
? ? ? ? super(context);
? ? ? ? mVolumeHandler = new ShowVolumeHandler(this);
? ? ? ? mAudioUtil = new RecordButtonUtil();
? ? ? ? initSavePath();
? ? }
? ? @Override
? ? public boolean onTouchEvent(MotionEvent event) {
? ? ? ? if (mAudioFile == null) {
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? switch (event.getAction()) {
? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? initlization();
? ? ? ? ? ? break;
? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? if (event.getY() < -50) {
? ? ? ? ? ? ? ? cancelRecord();
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? finishRecord();
? ? ? ? ? ? }
? ? ? ? ? ? break;
? ? ? ? case MotionEvent.ACTION_MOVE:
? ? ? ? ? //做一些UI提示
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return true;
? ? }
?
? ? /** 初始化 dialog和录音器 */
? ? private void initlization() {
? ? ? ? mStartTime = System.currentTimeMillis();
? ? ? ? if (mRecordDialog == null) {
? ? ? ? ? ? mRecordDialog = new Dialog(getContext());
? ? ? ? ? ? mRecordDialog.setOnDismissListener(onDismiss);
? ? ? ? }
? ? ? ? mRecordDialog.show();
? ? ? ? startRecording();
? ? }
?
? ? /** 录音完成(达到最长时间或用户决定录音完成) */
? ? private void finishRecord() {
? ? ? ? stopRecording();
? ? ? ? mRecordDialog.dismiss();
? ? ? ? long intervalTime = System.currentTimeMillis() - mStartTime;
? ? ? ? if (intervalTime < MIN_INTERVAL_TIME) {
? ? ? ? ? ? AppContext.showToastShort(R.string.record_sound_short);
? ? ? ? ? ? File file = new File(mAudioFile);
? ? ? ? ? ? file.delete();
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (mFinishedListerer != null) {
? ? ? ? ? ? mFinishedListerer.onFinishedRecord(mAudioFile,
? ? ? ? ? ? ? ? ? ? (int) ((System.currentTimeMillis() - mStartTime) / 1000));
? ? ? ? }
? ? }
? ? // 用户手动取消录音
? ? private void cancelRecord() {
? ? ? ? stopRecording();
? ? ? ? mRecordDialog.dismiss();
? ? ? ? File file = new File(mAudioFile);
? ? ? ? file.delete();
? ? ? ? if (mFinishedListerer != null) {
? ? ? ? ? ? mFinishedListerer.onCancleRecord();
? ? ? ? }
? ? }
?
? ? // 开始录音
? ? private void startRecording() {
? ? ? ? mAudioUtil.setAudioPath(mAudioFile);
? ? ? ? mAudioUtil.recordAudio();
? ? ? ? mThread = new ObtainDecibelThread();
? ? ? ? mThread.start();
?
? ? }
? ? // 停止录音
? ? private void stopRecording() {
? ? ? ? if (mThread != null) {
? ? ? ? ? ? mThread.exit();
? ? ? ? ? ? mThread = null;
? ? ? ? }
? ? ? ? if (mAudioUtil != null) {
? ? ? ? ? ? mAudioUtil.stopRecord();
? ? ? ? }
? ? }
?
? ? /******************************* inner class ****************************************/
? ? private class ObtainDecibelThread extends Thread {
? ? ? ? private volatile boolean running = true;
?
? ? ? ? public void exit() {
? ? ? ? ? ? running = false;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void run() {
? ? ? ? ? ? while (running) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Thread.sleep(300);
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (System.currentTimeMillis() - mStartTime >= MAX_INTERVAL_TIME) {
? ? ? ? ? ? ? ? ? ? // 如果超过最长录音时间
? ? ? ? ? ? ? ? ? ? mVolumeHandler.sendEmptyMessage(-1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (mAudioUtil !

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇为什么 C++ 成员函数指针是 16 字.. 下一篇浅谈 C++ 中的 new/delete 和 new..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: