Android仿微信、录制音频并发送功能



1.首先是主页面的布局

    布局采用线性布局,上面使用的一个ListView,下面使用的是一个自定义的Button(会在下面进行介绍)

[java]  view plain  copy

1.首先是主页面的布局

    布局采用线性布局,上面使用的一个ListView,下面使用的是一个自定义的Button(会在下面进行介绍)

  1. <span style="font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:app="http://schemas.android.com/apk/res-auto"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical"  
  7.     tools:context="com.bwie.liaotian_test2.MainActivity">  
  8.   
  9.   
  10.     <ListView  
  11.         android:id="@+id/lv"  
  12.         android:dividerHeight="10dp"  
  13.         android:divider="@null"  
  14.         android:background="#ebebeb"  
  15.         android:layout_weight="1"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="0dp"></ListView>  
  18.   
  19.     <FrameLayout  
  20.         android:background="#fff"  
  21.         android:id="@+id/frame"  
  22.         android:layout_width="match_parent"  
  23.         android:layout_height="wrap_content">  
  24.   
  25.         <com.bwie.liaotian_test2.View.AudioRecorderButton  
  26.             android:minHeight="0dp"  
  27.             android:id="@+id/audio_button"  
  28.             android:layout_marginRight="50dp"  
  29.             android:layout_marginLeft="50dp"  
  30.             android:layout_marginTop="6dp"  
  31.             android:layout_marginBottom="7dp"  
  32.             android:layout_width="match_parent"  
  33.             android:gravity="center"  
  34.             android:padding="6dp"  
  35.             android:textSize="20sp"  
  36.             android:textColor="#727272"  
  37.             android:background="@drawable/btn_normal"  
  38.             android:text="@string/str_recorder_normal"  
  39.             android:layout_height="wrap_content" />  
  40.   
  41.         <View  
  42.             android:background="#ccc"  
  43.             android:layout_width="match_parent"  
  44.             android:layout_height="1dp"/>  
  45.     </FrameLayout>  
  46. </LinearLayout></span>  
btn_normal
[java]  view plain  copy
  1. <span style="font-size:18px;"><shape xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:shape="rectangle">  
  3.   
  4.     <solid android:color="#ffffff"/>  
  5.     <stroke android:color="#9b9b9b" android:width="1px"/>  
  6.     <corners android:radius="3dp"/>  
  7. </shape></span>  
btn_recording
[java]  view plain  copy
  1. <span style="font-size:18px;"><shape xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:shape="rectangle">  
  3.   
  4.     <solid android:color="#bbcc00"/>  
  5.     <stroke android:color="#9b9b9b" android:width="1px"/>  
  6.     <corners android:radius="3dp"/>  
  7. </shape></span>  
2.自定义button ---AudioRecorderButton
[java]  view plain  copy
  1. <span style="font-size:18px;">public class AudioRecorderButton extends android.support.v7.widget.AppCompatButton implements AudioManager.AudioStateListener {  
  2.     private static final int STATE_NORMAL = 1;//正常状态  
  3.     private static final int STATE_RECORDING = 2;//录音状态  
  4.     private static final int STATE_WANT_TO_CANCEL = 3;//取消状态  
  5.     private int mCurState = STATE_NORMAL;//当前状态  
  6.     private boolean isRecording = false;//是否正在录音  
  7.     private static final int DISTANXE_Y_CANCEL = 50;  
  8.     private AudioManager mAudioManager;  
  9.     private DialogManager mDialogManger;  
  10.     private boolean mReady = false;//是否触发longClick  
  11.     private float mTime;//计时  
  12.     public AudioRecorderButton(Context context) {  
  13.         super(context,null);  
  14.     }  
  15.   
  16.     public AudioRecorderButton(Context context, AttributeSet attrs) {  
  17.         super(context, attrs);  
  18.         String dir = Environment.getExternalStorageDirectory() + "/my_recorder_audios";  
  19.         mAudioManager = AudioManager.getmInstance(dir);  
  20.         mAudioManager.setAudioStateListener(this);  
  21.         mDialogManger=new DialogManager(context);  
  22.         setOnLongClickListener(new OnLongClickListener() {  
  23.             @Override  
  24.             public boolean onLongClick(View v) {  
  25.                 mAudioManager.prepareAudio();  
  26.                 mReady = true;  
  27.                 return false;  
  28.             }  
  29.         });  
  30.     }  
  31.   
  32.     @Override  
  33.     public boolean onTouchEvent(MotionEvent event) {  
  34.         int action = event.getAction();  
  35.         int x= (int) event.getX();  
  36.         int y= (int) event.getY();  
  37.         switch (action){  
  38.             case MotionEvent.ACTION_DOWN:  
  39.                 changeSate(STATE_RECORDING);  
  40.                 break;  
  41.             case MotionEvent.ACTION_MOVE:  
  42.                 if (isRecording) {  
  43.                     if (isCancelRecorder(x, y)) {  
  44.                         changeSate(STATE_WANT_TO_CANCEL);  
  45.                     } else {  
  46.                         changeSate(STATE_RECORDING);  
  47.                     }  
  48.                 }  
  49.                 break;  
  50.             case MotionEvent.ACTION_UP:  
  51.                 if(!mReady){  
  52.                     reset();  
  53.                     return super.onTouchEvent(event);  
  54.                 }  
  55.                 if (!isRecording || mTime < 0.6f) {  
  56.                     mDialogManger.tooShort();  
  57.                     mAudioManager.cancel();  
  58.                     mHandler.sendEmptyMessageDelayed(MSG_LODING_DISMISS, 1000);  
  59.                 } else if (mCurState == STATE_RECORDING) {//正常录制结束  
  60.                     mDialogManger.dimissDialog();  
  61.                     mAudioManager.release();  
  62.                     if (mListener != null) {  
  63.                         mListener.onFinish(mTime, mAudioManager.getmCurrentFilePath());  
  64.                     }  
  65.                 } else if (mCurState == STATE_WANT_TO_CANCEL) {  
  66.                     mDialogManger.dimissDialog();  
  67.                     mAudioManager.cancel();  
  68.                 }  
  69.                 reset();  
  70.                 break;  
  71.         }  
  72.         return super.onTouchEvent(event);  
  73.     }  
  74.     /** 
  75.      * 根据移动后的位置,判断是否取消录音 
  76.      */  
  77.     private boolean isCancelRecorder(int x, int y) {  
  78.          if(x<0||x>getWidth()){  
  79.              return true;  
  80.          }  
  81.          if(y<-DISTANXE_Y_CANCEL||y>getHeight()+DISTANXE_Y_CANCEL){  
  82.              return true;  
  83.          }  
  84.         return false;  
  85.     }  
  86.     /** 
  87.      * 根据不同状态,更改不同的文字和显示的背景 
  88.      */  
  89.     private void changeSate(int state) {  
  90.         if (mCurState != state) {  
  91.             mCurState = state;  
  92.             switch (state) {  
  93.                 case STATE_NORMAL:  
  94.                     setBackgroundResource(R.drawable.btn_normal);  
  95.                     setText(R.string.str_recorder_normal);  
  96.                     break;  
  97.   
  98.                 case STATE_RECORDING:  
  99.                     setBackgroundResource(R.drawable.btn_recording);  
  100.                     setText(R.string.str_recorder_recording);  
  101.                     if (isRecording) {  
  102.                         mDialogManger.recording();  
  103.                     }  
  104.                     break;  
  105.   
  106.                 case STATE_WANT_TO_CANCEL:  
  107.                     setBackgroundResource(R.drawable.btn_recording);  
  108.                     setText(R.string.str_recorder_want_cancel);  
  109.                        mDialogManger.wantToCancel();  
  110.                     break;  
  111.             }  
  112.         }  
  113.     }  
  114.   
  115.     /** 
  116.      * 重置标识位 
  117.      */  
  118.     private void reset() {  
  119.         changeSate(STATE_NORMAL);  
  120.         isRecording = false;  
  121.         mReady = false;  
  122.         mTime = 0;  
  123.     }  
  124.     /** 
  125.      * 开始播放时回调此方法 
  126.      */  
  127.     @Override  
  128.     public void wellPrepared() {  
  129.         mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);  
  130.     }  
  131.   
  132.     private static final int MSG_AUDIO_PREPARED = 0x110;  
  133.     private static final int MSG_VOICE_CHAGE = 0x111;  
  134.     private static final int MSG_LODING_DISMISS = 0x112;  
  135.   
  136.     private Handler mHandler = new Handler() {  
  137.         @Override  
  138.         public void handleMessage(Message msg) {  
  139.             super.handleMessage(msg);  
  140.             switch (msg.what) {  
  141.                 case MSG_AUDIO_PREPARED:  
  142.                     mDialogManger.showRecordeingDialog();  
  143.                     isRecording = true;  
  144.                     new Thread(mGetVoiceLevelRunnable).start();  
  145.                     break;  
  146.   
  147.                 case MSG_VOICE_CHAGE:  
  148.                     mDialogManger.updateVoiceLevel(mAudioManager.getVoiceLevel(7));  
  149.                     break;  
  150.   
  151.                 case MSG_LODING_DISMISS:  
  152.                     mDialogManger.dimissDialog();  
  153.                     break;  
  154.             }  
  155.         }  
  156.     };  
  157.   
  158.   
  159.     /** 
  160.      * 获取音量大小,并计时 
  161.      */  
  162.     private Runnable mGetVoiceLevelRunnable = new Runnable() {  
  163.         @Override  
  164.         public void run() {  
  165.             while (isRecording) {  
  166.                 SystemClock.sleep(100);  
  167.                 mTime += 0.1f;  
  168.                 mHandler.sendEmptyMessage(MSG_VOICE_CHAGE);  
  169.             }  
  170.         }  
  171.     };  
  172.   
  173.     /** 
  174.      * 完成录制后的回调接口 
  175.      */  
  176.     public interface AudioFinishRecorderListener {  
  177.         void onFinish(float time, String filePath);  
  178.     }  
  179.   
  180.     private AudioFinishRecorderListener mListener;  
  181.   
  182.     public void setAudioFinishRecorderListener(AudioFinishRecorderListener listener) {  
  183.         mListener = listener;  
  184.     }  
  185. }</span>  
相关使用的string值(需要添加到value/string中)
[java]  view plain  copy
  1. <span style="font-size:18px;"><string name="str_recorder_normal">按住说话</string>  
  2.     <string name="str_recorder_recording">松开结束</string>  
  3.     <string name="str_recorder_want_cancel">松开手指,取消发送</string>  
  4.     <string name="ss">手指上滑,取消发送</string></span>  
3.Dialog的实现
dialog.xml  
[java]  view plain  copy
  1. <span style="font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="wrap_content"  
  3.     android:orientation="vertical"  
  4.     android:padding="20dp"  
  5.     android:gravity="center"  
  6.     android:background="@drawable/dialog_loading_bg"  
  7.     android:layout_height="wrap_content">  
  8.   
  9.     <LinearLayout  
  10.         android:orientation="horizontal"  
  11.         android:layout_width="wrap_content"  
  12.         android:layout_height="wrap_content">  
  13.   
  14.         <ImageView  
  15.             android:id="@+id/iv1"  
  16.             android:visibility="visible"  
  17.             android:src="@drawable/recorder"  
  18.             android:layout_width="wrap_content"  
  19.             android:layout_height="wrap_content" />  
  20.         <ImageView  
  21.             android:id="@+id/iv2"  
  22.             android:visibility="visible"  
  23.             android:src="@drawable/v1"  
  24.             android:layout_width="wrap_content"  
  25.             android:layout_height="wrap_content" />  
  26.     </LinearLayout>  
  27.   
  28.     <TextView  
  29.         android:id="@+id/tv"  
  30.         android:textColor="#ffff"  
  31.         android:text="@string/ss"  
  32.         android:layout_marginTop="5dp"  
  33.         android:layout_width="wrap_content"  
  34.         android:layout_height="wrap_content" />  
  35. </LinearLayout></span>  
Dialog的样式Theme_AudioDialog,需要在values/styles.xml中定义
[java]  view plain  copy
  1. <span style="font-size:18px;"><style name="Theme_AudioDialog">  
  2.         <item name="android:windowBackground">@android:color/transparent</item>  
  3.         <item name="android:windowFrame">@null</item>  
  4.         <item name="android:windowIsFloating">true</item>  
  5.         <item name="android:windowIsTranslucent">true</item>  
  6.         <item name="android:backgroundDimEnabled">false</item>  
  7.     </style></span>  
DialogManager
[java]  view plain  copy
  1. <span style="font-size:18px;">public class DialogManager {  
  2.     private Dialog mDialog;  
  3.     private ImageView mIcon;  
  4.     private ImageView mVoice;  
  5.     private TextView mLabel;  
  6.   
  7.     private Context mContext;  
  8.   
  9.     public DialogManager(Context mContext) {  
  10.         this.mContext = mContext;  
  11.     }  
  12.     /** 
  13.      * 显示对话框 
  14.      */  
  15.     public void  showRecordeingDialog(){  
  16.         mDialog = new Dialog(mContext, R.style.Theme_AudioDialog);  
  17.         LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);  
  18.         View view = inflater.inflate(R.layout.dialog, null);  
  19.         mDialog.setContentView(view);  
  20.         //获取控件  
  21.         mIcon = (ImageView) mDialog.findViewById(R.id.iv1);  
  22.         mVoice = (ImageView) mDialog.findViewById(R.id.iv2);  
  23.         mLabel = (TextView) mDialog.findViewById(R.id.tv);  
  24.         //显示  
  25.         mDialog.show();  
  26.     }  
  27.     /** 
  28.      * 正在录制提示 
  29.      */  
  30.     public void recording() {  
  31.         if (mDialog != null && mDialog.isShowing()) {  
  32.             mIcon.setVisibility(View.VISIBLE);  
  33.             mVoice.setVisibility(View.VISIBLE);  
  34.             mLabel.setVisibility(View.VISIBLE);  
  35.             mIcon.setImageResource(R.drawable.recorder);  
  36.             mLabel.setText(R.string.ss);  
  37.         }  
  38.     }  
  39.     /** 
  40.      * 取消录制对话框提示 
  41.      */  
  42.     public void wantToCancel(){  
  43.         if (mDialog != null && mDialog.isShowing()) {  
  44.             mIcon.setVisibility(View.VISIBLE);  
  45.             mVoice.setVisibility(View.GONE);  
  46.             mLabel.setVisibility(View.VISIBLE);  
  47.             mIcon.setImageResource(R.drawable.cancel);  
  48.             mLabel.setText("松开手指,取消发送");  
  49.         }  
  50.     }  
  51.     /** 
  52.      * 录音时间过短提示 
  53.      */  
  54.     public void tooShort(){  
  55.         if (mDialog != null && mDialog.isShowing()) {  
  56.             mIcon.setVisibility(View.VISIBLE);  
  57.             mVoice.setVisibility(View.GONE);  
  58.             mLabel.setVisibility(View.VISIBLE);  
  59.             mIcon.setImageResource(R.drawable.voice_to_short);  
  60.             mLabel.setText("录音时间过短");  
  61.         }  
  62.     }  
  63.     /** 
  64.      * 取消对话框 
  65.      */  
  66.     public void dimissDialog(){  
  67.         if (mDialog != null && mDialog.isShowing()) {  
  68.            mDialog.dismiss();  
  69.            mDialog=null;  
  70.         }  
  71.     }  
  72.     /** 
  73.      * 显示音量大小 
  74.      */  
  75.     public void updateVoiceLevel(int level){  
  76.         if (mDialog != null && mDialog.isShowing()) {  
  77.             int resId = mContext.getResources().getIdentifier("v" + level, "drawable", mContext.getPackageName());  
  78.             mVoice.setImageResource(resId);  
  79.         }  
  80.     }  
  81. }</span>  
4.当手指按住Button时,便开始录音,所以我们还需要定义一个录音的管理类AudioManager
来控制录制状态。
------AudioManager
[java]  view plain  copy
  1. <span style="font-size:18px;">public class AudioManager {  
  2.   
  3.     private MediaRecorder mMediaRecorder;  
  4.     private String mDir;// 保存的目录  
  5.     private String mCurrentFilePath;// 保存音频文件的全路径  
  6.     private boolean isPrepared = false;// 是否准备完毕  
  7.     private static AudioManager mInstance;  
  8.   
  9.     private AudioManager(String dir) {  
  10.         mDir = dir;  
  11.     }  
  12.     public static AudioManager getmInstance(String mDir) {  
  13.         if (mInstance == null) {  
  14.             synchronized (AudioManager.class) {  
  15.                 if (mInstance == null) {  
  16.                     mInstance = new AudioManager(mDir);  
  17.                 }  
  18.             }  
  19.         }  
  20.         return mInstance;  
  21.     }  
  22.   
  23.     /** 
  24.      * 准备完毕的回调 
  25.      */  
  26.     public interface AudioStateListener {  
  27.         void wellPrepared();  
  28.     }  
  29.   
  30.     private AudioStateListener mListener;  
  31.   
  32.     public void setAudioStateListener(AudioStateListener listener) {  
  33.         mListener = listener;  
  34.     }  
  35.     /** 准备录制 */  
  36.     public void prepareAudio() {  
  37.         try {  
  38.             isPrepared = false;  
  39.             File dir = new File(mDir);  
  40.             if (!dir.exists()) {  
  41.                 dir.mkdirs();  
  42.             }  
  43.   
  44.             String fileName = generateName();  
  45.             File file = new File(dir, fileName);  
  46.             mCurrentFilePath = file.getAbsolutePath();  
  47.             mMediaRecorder = new MediaRecorder();  
  48.             // 设置输出文件  
  49.             mMediaRecorder.setOutputFile(mCurrentFilePath);  
  50.             // 设置音频源为麦克风  
  51.             mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  
  52.             // 设置音频格式  
  53.             mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);  
  54.             // 设置音频编码  
  55.             mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  
  56.   
  57.             mMediaRecorder.prepare();  
  58.             mMediaRecorder.start();  
  59.   
  60.             isPrepared = true;  
  61.             if (mListener != null) {  
  62.                 mListener.wellPrepared();  
  63.             }  
  64.         } catch (Exception e) {  
  65.             e.printStackTrace();  
  66.         }  
  67.     }  
  68.   
  69.     /** 获取音量大小 */  
  70.     public int getVoiceLevel(int maxLevel) {  
  71.         if (isPrepared) {  
  72.             try {  
  73.                 //mMediaRecorder.getMaxAmplitude() 1-32767  
  74.                 //注意此处mMediaRecorder.getMaxAmplitude 只能取一次,如果前面取了一次,后边再取就为0了  
  75.                 return ((mMediaRecorder.getMaxAmplitude() * maxLevel) / 32768) + 1;  
  76.             } catch (Exception e) {  
  77.             }  
  78.   
  79.         }  
  80.         return 1;  
  81.     }  
  82.   
  83.     /** 保存录音,释放资源 */  
  84.     public void release() {  
  85.         if(mMediaRecorder != null) {  
  86.             mMediaRecorder.stop();  
  87.             mMediaRecorder.release();  
  88.             mMediaRecorder = null;  
  89.         }  
  90.     }  
  91.   
  92.     /** 取消录制 */  
  93.     public void cancel() {  
  94.         release();  
  95.         if(mCurrentFilePath != null) {  
  96.             File file = new File(mCurrentFilePath);  
  97.             if(file.exists()) {  
  98.                 file.delete();  
  99.                 mCurrentFilePath = null;  
  100.             }  
  101.         }  
  102.     }  
  103.   
  104.     /** 获取录制音频的总路径 */  
  105.     public String getmCurrentFilePath(){  
  106.         return mCurrentFilePath;  
  107.     }  
  108.   
  109.     /** 
  110.      * 生成一个随机名字 
  111.      */  
  112.     private String generateName() {  
  113.         return UUID.randomUUID().toString() + ".amr";  
  114.     }  
  115. }</span>  
5.listview子布局和适配器
5.1 bean
[java]  view plain  copy
  1. <span style="font-size:18px;">public class Recorder {  
  2.     private float time;  
  3.     private String filePath;  
  4.   
  5.     public Recorder(float time, String filePath) {  
  6.         this.time = time;  
  7.         this.filePath = filePath;  
  8.     }  
  9.   
  10.     public float getTime() {  
  11.         return time;  
  12.     }  
  13.   
  14.     public void setTime(float time) {  
  15.         this.time = time;  
  16.     }  
  17.   
  18.     public String getFilePath() {  
  19.         return filePath;  
  20.     }  
  21.   
  22.     public void setFilePath(String filePath) {  
  23.         this.filePath = filePath;  
  24.     }  
  25. }  
  26. </span>  
//子布局 item_re.xml
[java]  view plain  copy
  1. <span style="font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="match_parent"  
  3.     android:layout_marginTop="5dp"  
  4.     android:layout_height="60dp">  
  5.   
  6.     <ImageView  
  7.         android:src="@drawable/icon"  
  8.         android:layout_alignParentRight="true"  
  9.         android:layout_centerVertical="true"  
  10.         android:layout_marginRight="5dp"  
  11.         android:id="@+id/icon_iv"  
  12.         android:layout_width="40dp"  
  13.         android:layout_height="40dp" />  
  14.   
  15.   
  16.     <FrameLayout  
  17.         android:layout_toLeftOf="@+id/icon_iv"  
  18.         android:layout_centerVertical="true"  
  19.         android:id="@+id/fragme"  
  20.         android:layout_width="wrap_content"  
  21.         android:layout_height="50dp"  
  22.         android:background="@drawable/chatto_bg_focused">  
  23.   
  24.         <View  
  25.             android:background="@drawable/adj"  
  26.             android:layout_gravity="center_vertical|right"  
  27.             android:id="@+id/icon_v"  
  28.             android:layout_width="25dp"  
  29.             android:layout_height="25dp"/>  
  30.     </FrameLayout>  
  31.   
  32.     <TextView  
  33.         android:textColor="#ff777777"  
  34.         android:layout_marginRight="3dp"  
  35.         android:layout_toLeftOf="@+id/fragme"  
  36.         android:layout_centerVertical="true"  
  37.         android:id="@+id/icon_time"  
  38.         android:textSize="18sp"  
  39.         android:layout_width="wrap_content"  
  40.         android:layout_height="wrap_content" />  
  41. </RelativeLayout>  
  42. </span>  
//适配器
[java]  view plain  copy
  1. <span style="font-size:18px;">public class RecorderAdapter extends ArrayAdapter<Recorder> {  
  2.   
  3.     private List<Recorder> mDatas;  
  4.     private Context mContext;  
  5.     private int mMinItemWidhth;  
  6.     private int mMaxItemWidhth;  
  7.     public RecorderAdapter(Context context, List<Recorder> datas) {  
  8.         super(context, -1, datas);  
  9.         mDatas = datas;  
  10.         mContext = context;  
  11.         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  
  12.         DisplayMetrics outMetrics = new DisplayMetrics();  
  13.         wm.getDefaultDisplay().getMetrics(outMetrics);  
  14.   
  15.         mMaxItemWidhth = (int) (outMetrics.widthPixels * 0.7f);  
  16.         mMinItemWidhth = (int) (outMetrics.widthPixels * 0.15f);  
  17.     }  
  18.   
  19.     @Override  
  20.     public View getView(int position, View convertView, ViewGroup parent) {  
  21.         ViewHolder holder=null;  
  22.         if(holder==null) {  
  23.             holder=new ViewHolder();  
  24.             if (convertView == null) {  
  25.                 convertView = View.inflate(mContext,R.layout.item_re, null);  
  26.                 holder.length=convertView.findViewById(R.id.fragme);  
  27.                 holder.time=convertView.findViewById(R.id.icon_time);  
  28.                 convertView.setTag(holder);  
  29.             }else{  
  30.                 holder= (ViewHolder) convertView.getTag();  
  31.             }  
  32.         }  
  33.         holder.time.setText(Math.round(getItem(position).getTime())+ "\"");  
  34.         ViewGroup.LayoutParams layoutParams = holder.length.getLayoutParams();  
  35.         layoutParams.width = (int) (mMinItemWidhth + (mMaxItemWidhth / 60f * getItem(position).getTime()));  
  36.         return convertView;  
  37.     }  
  38.   
  39.     private class ViewHolder{  
  40.        public TextView time;  
  41.        private View length;  
  42.   
  43.         public TextView getTime() {  
  44.             return time;  
  45.         }  
  46.   
  47.         public void setTime(TextView time) {  
  48.             this.time = time;  
  49.         }  
  50.   
  51.         public View getLength() {  
  52.             return length;  
  53.         }  
  54.   
  55.         public void setLength(View length) {  
  56.             this.length = length;  
  57.         }  
  58.     }  
  59. }</span>  
6.定义MediaManger,用于播放音频
[java]  view plain  copy
  1. <span style="font-size:18px;">public class MediaManager {  
  2.     private static MediaPlayer mMediaPlayer;  
  3.   
  4.     private static boolean isPause = false;//是否是暂停  
  5.   
  6.     /** 
  7.      * 播放音频 
  8.      */  
  9.     public static void playSound(String filePath, MediaPlayer.OnCompletionListener onCompletionListener) {  
  10.         if (mMediaPlayer == null) {  
  11.             mMediaPlayer = new MediaPlayer();  
  12.             mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {  
  13.                 @Override  
  14.                 public boolean onError(MediaPlayer mp, int what, int extra) {  
  15.                     mMediaPlayer.reset();  
  16.                     return false;  
  17.                 }  
  18.             });  
  19.         } else {  
  20.             mMediaPlayer.reset();  
  21.         }  
  22.   
  23.         try {  
  24.             mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
  25.             mMediaPlayer.setOnCompletionListener(onCompletionListener);  
  26.             mMediaPlayer.setDataSource(filePath);  
  27.             mMediaPlayer.prepare();  
  28.             mMediaPlayer.start();  
  29.         } catch (Exception e) {  
  30.             e.printStackTrace();  
  31.         }  
  32.     }  
  33.   
  34.     /** 
  35.      * 暂停 
  36.      */  
  37.     public static void pause() {  
  38.         if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {  
  39.             mMediaPlayer.pause();  
  40.             isPause = true;  
  41.         }  
  42.     }  
  43.   
  44.     /** 
  45.      * 继续 
  46.      */  
  47.     public static void resume() {  
  48.         if (mMediaPlayer != null && isPause) {  
  49.             mMediaPlayer.start();  
  50.             isPause = false;  
  51.         }  
  52.     }  
  53.   
  54.     /** 
  55.      * 释放资源 
  56.      */  
  57.     public static void release() {  
  58.         if (mMediaPlayer != null) {  
  59.             mMediaPlayer.release();  
  60.             mMediaPlayer = null;  
  61.         }  
  62.     }  
  63.   
  64. }</span>  
//main
[java]  view plain  copy
  1. <span style="font-size:18px;">public class MainActivity extends AppCompatActivity {  
  2.   
  3.     private ListView lv;  
  4.     private ArrayAdapter<Recorder> mAdapter;  
  5.     private List<Recorder> list=new ArrayList<>();  
  6.     private AudioRecorderButton audioRecorderButton;  
  7.     private View animView;  
  8.   
  9.     @Override  
  10.     protected void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.activity_main);  
  13.         lv = findViewById(R.id.lv);  
  14.         audioRecorderButton=findViewById(R.id.audio_button);  
  15.         audioRecorderButton.setAudioFinishRecorderListener(new AudioRecorderButton.AudioFinishRecorderListener() {  
  16.             @Override  
  17.             public void onFinish(float time, String filePath) {  
  18.                 Recorder recorder=new Recorder(time,filePath);  
  19.                 list.add(recorder);  
  20.                 mAdapter.notifyDataSetChanged();  
  21.                 lv.setSelection(list.size()-1);  
  22.             }  
  23.         });  
  24.   
  25.         mAdapter=new RecorderAdapter(this,list);  
  26.         lv.setAdapter(mAdapter);  
  27.         lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {  
  28.             @Override  
  29.             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
  30.                    if(animView!=null){  
  31.                        animView.setBackgroundResource(R.drawable.adj);  
  32.                        animView=null;  
  33.                    }  
  34.                   //播放动画  
  35.                   animView = view.findViewById(R.id.icon_v);  
  36.                   animView.setBackgroundResource(R.drawable.play_anim);  
  37.                   AnimationDrawable anim= (AnimationDrawable) animView.getBackground();  
  38.                   anim.start();  
  39.                   // 播放音频  
  40.                 MediaManager.playSound(list.get(position).getFilePath(), new MediaPlayer.OnCompletionListener() {  
  41.                     @Override  
  42.                     public void onCompletion(MediaPlayer mp) {  
  43.                         animView.setBackgroundResource(R.drawable.adj);  
  44.                     }  
  45.                 });  
  46.             }  
  47.         });  
  48.     }  
  49.   
  50.     @Override  
  51.     protected void onPause() {  
  52.         MediaManager.pause();  
  53.         super.onPause();  
  54.     }  
  55.   
  56.     @Override  
  57.     protected void onResume() {  
  58.         MediaManager.resume();  
  59.         super.onResume();  
  60.     }  
  61.   
  62.     @Override  
  63.     protected void onDestroy() {  
  64.         MediaManager.release();  
  65.         super.onDestroy();  
  66.     }  
  67. }</span>  
帧动画play_anim定义在drawable下
[java]  view plain  copy
  1. <span style="font-size:18px;"><animation-list xmlns:android="http://schemas.android.com/apk/res/android"    
  2.  >    
  3.  <item    
  4.   android:drawable="@mipmap/v_anim1"    
  5.   android:duration="300"/>    
  6.  <item    
  7.   android:drawable="@mipmap/v_anim2"    
  8.   android:duration="300"/>    
  9.  <item    
  10.   android:drawable="@mipmap/v_anim3"    
  11.   android:duration="300"/>    
  12. </animation-list>  </span>  
//权限
[java]  view plain  copy
  1. <span style="font-size:18px;">    <uses-permission android:name="android.permission.RECORD_AUDIO"/>    
  2.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    
  3.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  </span>  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值