首页 > 系统 > Android > 正文

Android自定义UI实现微信语音

2019-12-12 04:51:17
字体:
来源:转载
供稿:网友

本文实例为大家分享了java获取不同路径的方法,供大家参考,具体内容如下

思路:
自定义Button
获取DialogManager、AudioManager setOnLongClickListener长按事件--做好AudioManager的录音准备工作
AudioManager.setOnAudioStateListener(this)实现录音准备完毕的接口回调方法,方法中去发送MSG_AUDIO_PREPARE消息代表录音准备工作完毕
在mHandler中接收消息,开始开启线程录音,并且计时,计时的过程中,去发送MSG_VOICE_CHANGED消息,去updateVoiceLeve更新音量图标,另外在MotionEvent.ACTION_UP事件中,去定义audioFinishRecorderListener.onFinish接口方法,方法是录音完毕的回调方法,在MainActivity中,mAudioRecorderButton.setAudioFinishRecorderListener实现录音完毕回调方法去更新listViewUi界面

点击listViewItem条目播放动画, MediaManager.playSound并且播放音频

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical"  tools:context="com.example.imooc_recorder.MainActivity" >   <ListView  android:id="@+id/id_listview"  android:layout_width="fill_parent"  android:layout_height="0dp"  android:layout_weight="1"  android:background="#ebebeb"  android:divider="@null"  android:dividerHeight="10dp" >  </ListView>   <FrameLayout  android:layout_width="fill_parent"  android:layout_height="wrap_content" >  <View   android:background="#ccc"   android:layout_width="fill_parent"   android:layout_height="1dp" />   <com.example.recorder_view.AudioRecorderButton   android:id="@+id/id_recorder_button"   android:layout_width="fill_parent"   android:layout_height="wrap_content"   android:layout_marginBottom="7dp"   android:layout_marginLeft="50dp"   android:layout_marginRight="50dp"   android:layout_marginTop="6dp"   android:background="@drawable/button_recorder_normal"   android:gravity="center"   android:minHeight="0dp"   android:padding="5dp"   android:text="@string/str_recorder_nomal"   android:textColor="#727272" >  </com.example.recorder_view.AudioRecorderButton>   </FrameLayout>  </LinearLayout> 

dialog_recorder.xml---dialog布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="@drawable/dialog_loading_bg"  android:gravity="center"  android:orientation="vertical"  android:padding="20dp" >   <LinearLayout  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:orientation="horizontal" >   <ImageView   android:id="@+id/id_recorder_dialog_icon"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:src="@drawable/recorder"   android:visibility="visible" />   <ImageView   android:id="@+id/id_recorder_dialog_voice"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:src="@drawable/v1"   android:visibility="visible" />  </LinearLayout>   <TextView  android:id="@+id/id_recorder_dialog_label"  android:layout_marginTop="5dp"  android:text="手指上滑,取消发送"  android:textColor="#ffffff"  android:layout_width="wrap_content"  android:layout_height="wrap_content"/>  </LinearLayout> 

item_recorder.xml--listview中的每个item

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:background="#eeeeee"  android:layout_height="60dp"  android:layout_marginTop="5dp" >   <ImageView  android:id="@+id/id_icon"  android:layout_width="40dp"  android:layout_height="40dp"  android:layout_alignParentRight="true"  android:layout_centerVertical="true"  android:layout_marginRight="5dp"  android:src="@drawable/icon" />   <FrameLayout  android:id="@+id/id_recorder_length"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_centerVertical="true"  android:layout_toLeftOf="@id/id_icon"  android:background="@drawable/chatto_bg_focused" >   <View   android:id="@+id/id_recorder_anim"   android:layout_width="25dp"   android:layout_height="25dp"   android:layout_gravity="center_vertical|right"   android:background="@drawable/adj" />  </FrameLayout>   <TextView  android:id="@+id/id_recorder_time"  android:layout_centerVertical="true"  android:layout_toLeftOf="@id/id_recorder_length"  android:layout_marginRight="3dp"  android:textColor="#ff777777"  android:text=""  android:layout_width="wrap_content"  android:layout_height="wrap_content" />  </RelativeLayout> 

styles.xml

<style name="Theme_AudioDialog" parent="@android:Theme.Dialog">  <item name="android:windowBackground">@android:color/transparent</item>  <item name="android:windowFrame">@null</item>  <item name="android:windowIsFloating">true</item>   <item name="android:windowIsTranslucent">true</item>   <item name="android:backgroundDimEnabled">false</item>   </style> 

button_recorder_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:width="1px" android:color="#9b9b9b"/>  <corners android:radius="3dp"/> </shape> 

button_recorder_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="#ffffff"/>  <stroke android:width="1px" android:color="#eeeeee"/>  <corners android:radius="3dp"/> </shape> 

play_anim.xml

<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" >   <item  android:drawable="@drawable/v_anim1"  android:duration="300">  </item>  <item  android:drawable="@drawable/v_anim2"  android:duration="300">  </item>   <item  android:drawable="@drawable/v_anim3"  android:duration="300">  </item>   </animation-list> 

MainActivity

package com.example.imooc_recorder;  import java.util.ArrayList; import java.util.List;  import com.example.recorder_view.AudioRecorderButton; import com.example.recorder_view.AudioRecorderButton.AudioFinishRecorderListener; import com.example.recorder_view.MediaManager;  import android.app.Activity; import android.graphics.drawable.AnimationDrawable; import android.media.MediaPlayer; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView;  public class MainActivity extends Activity {   private ListView mListView;  private ArrayAdapter<Recorder> mAdapter;  private List<Recorder> mDatas = new ArrayList<MainActivity.Recorder>();  private AudioRecorderButton mAudioRecorderButton;  private View animView;  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  mListView = (ListView) findViewById(R.id.id_listview);  mAudioRecorderButton = (AudioRecorderButton) findViewById(R.id.id_recorder_button);  //录音完毕,回调  mAudioRecorderButton.setAudioFinishRecorderListener(new AudioFinishRecorderListener() {     @Override   public void onFinish(float seconds, String filePath) {   // TODO Auto-generated method stub   Recorder recorder = new Recorder(seconds, filePath);   mDatas.add(recorder);   mAdapter.notifyDataSetChanged();   mListView.setSelection(mDatas.size()-1);   }  });  mAdapter = new RecorderAdapter(this, mDatas);  mListView.setAdapter(mAdapter);    mListView.setOnItemClickListener(new OnItemClickListener() {   @Override   public void onItemClick(AdapterView<?> parent, View view,    int position, long id) {   if (animView !=null) {    animView.setBackgroundResource(R.drawable.adj);    animView = null;       }   //播放动画   animView = view.findViewById(R.id.id_recorder_anim);   animView.setBackgroundResource(R.drawable.play_anim);   AnimationDrawable anim = (AnimationDrawable) animView.getBackground();   anim.start();   //播放音频   MediaManager.playSound(mDatas.get(position).filePath,new MediaPlayer.OnCompletionListener() {       @Override    public void onCompletion(MediaPlayer mp) {    // TODO Auto-generated method stub    animView.setBackgroundResource(R.drawable.adj);    }   });   }  });  }   @Override  protected void onPause() {  // TODO Auto-generated method stub  super.onPause();  MediaManager.pause();  }  @Override  protected void onResume() {  // TODO Auto-generated method stub  super.onResume();  MediaManager.resume();  }  @Override  protected void onDestroy() {  // TODO Auto-generated method stub  super.onDestroy();  MediaManager.release();  }  /**内部类*/  class Recorder{  float time;  String filePath;  public Recorder(float time, String filePath) {   super();   this.time = time;   this.filePath = filePath;  }  public float getTime() {   return time;  }  public void setTime(float time) {   this.time = time;  }  public String getFilePath() {   return filePath;  }  public void setFilePath(String filePath) {   this.filePath = filePath;  }    } } 

RecorderAdapter

package com.example.imooc_recorder;  import java.util.List;  import com.example.imooc_recorder.MainActivity.Recorder;  import android.content.Context; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.TextView;  public class RecorderAdapter extends ArrayAdapter<Recorder> {  // private List<Recorder> mDatas; // private Context mContext;  private int mMinItemWidth;  private int mMaxItemWidth;  private LayoutInflater mInflater;   public RecorderAdapter(Context context, List<Recorder> datas) {  super(context, -1, datas); // mContext = context; // mDatas = datas;  WindowManager wm = (WindowManager) context   .getSystemService(Context.WINDOW_SERVICE);  DisplayMetrics outMetrics = new DisplayMetrics();  wm.getDefaultDisplay().getMetrics(outMetrics);   mMaxItemWidth = (int) (outMetrics.widthPixels * 0.7f);  mMinItemWidth = (int) (outMetrics.widthPixels * 0.15f);  mInflater = LayoutInflater.from(context);  }   @Override  public View getView(int position, View convertView, ViewGroup parent) {  // TODO Auto-generated method stub  ViewHolder holder = null;  if (convertView == null) {   convertView = mInflater.inflate(R.layout.item_recorder, parent,    false);   holder = new ViewHolder();   holder.seconds = (TextView) convertView.findViewById(R.id.id_recorder_time);   holder.length = convertView.findViewById(R.id.id_recorder_length);    convertView.setTag(holder);  }else {   holder = (ViewHolder) convertView.getTag();  }  holder.seconds.setText(Math.round(getItem(position).time)+"/"");  ViewGroup.LayoutParams lp = holder.length.getLayoutParams();  lp.width = (int) (mMinItemWidth +(mMaxItemWidth/60f*getItem(position).time));  return convertView;  }   private class ViewHolder {  private TextView seconds;  private View length;  } } 

AudioRecorderButton

package com.example.recorder_view;  import com.example.imooc_recorder.R; import com.example.recorder_view.AudioManager.AudioStateListener;  import android.content.Context; import android.os.Environment; import android.os.Handler; import android.telephony.SignalStrength; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.Button;  public class AudioRecorderButton extends Button implements AudioStateListener {  private static final int DISTANCE_Y_CANCEL = 50;   /** 提示框管理工具类 */  private DialogManager mDialogManager;  /** 正常、松开手指取消发送、手指上滑取消发送 */  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;   /** 录音工具类 */  private AudioManager mAudioManager;   /** 录音总时间 */  private float mTime;   /** 是否触发button */  private boolean mReady;   /** *****************自定义Button************************************* */  public AudioRecorderButton(Context context) {  super(context);  }   public AudioRecorderButton(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle);  }   public AudioRecorderButton(Context context, AttributeSet attrs) {  super(context, attrs);  mDialogManager = new DialogManager(getContext());  String dir = Environment.getExternalStorageDirectory()   + "/imooc_recorder_audios";  mAudioManager = AudioManager.getInstance(dir);  mAudioManager.setOnAudioStateListener(this);  /** 监听回调 */  setOnLongClickListener(new OnLongClickListener() {    @Override   public boolean onLongClick(View v) {   mReady = true;   // 录音准备--准备好后,有实现接口方法   mAudioManager.prepareAndio();   return false;   }  });  }   /******************************************************  * 完成录音准备的回调函数  */  @Override  public void wellPrepared() {  // 准备完毕,发送消息  mHandler.sendEmptyMessage(MSG_AUDIO_PREPARE);  }   private Handler mHandler = new Handler() {  public void handleMessage(android.os.Message msg) {   switch (msg.what) {   case MSG_AUDIO_PREPARE:   mDialogManager.showRecordingDailog();   isRecording = true;    new Thread(new Runnable() {     @Override    public void run() {     // TODO Auto-generated method stub    while (isRecording) {     try {     Thread.sleep(100);     // 录音计时     mTime += 0.1f;     mHandler.sendEmptyMessage(MSG_VOICE_CHANGED);     } catch (InterruptedException e) {     e.printStackTrace();     }     }     }   }).start();   break;   case MSG_VOICE_CHANGED:    mDialogManager.updateVoiceLeve(mAudioManager.getVoiceLevel(7));    break;   case MSG_DIALOG_DIMISS:    mDialogManager.dimissDailog();   break;    default:   break;   }   super.handleMessage(msg);  };  };   private static final int MSG_AUDIO_PREPARE = 0x110;  private static final int MSG_VOICE_CHANGED = 0x111;  private static final int MSG_DIALOG_DIMISS = 0x112;   @Override  public boolean onTouchEvent(MotionEvent event) {  // TODO Auto-generated method stub  int action = event.getAction();  int x = (int) event.getX();  int y = (int) event.getY();   switch (action) {  case MotionEvent.ACTION_DOWN:   changeState(STATE_RECORDING);   break;  case MotionEvent.ACTION_MOVE:   if (isRecording) {   // 根据xy坐标。判断是否想要取消   if (wantToCancel(x, y)) {    changeState(STATE_WANT_TO_CANCEL);   } else {    changeState(STATE_RECORDING);   }    }   break;  case MotionEvent.ACTION_UP:   if (!mReady) {   // 没有触发onclick   reset();   return super.onTouchEvent(event);    }   if (!isRecording || mTime < 0.6f) {   // prapred没有完成已经up了   mDialogManager.tooShort();   mAudioManager.cancel();   mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);    } else if (mCurState == STATE_RECORDING) {    mDialogManager.dimissDailog();   mAudioManager.release();   if (audioFinishRecorderListener != null) {    audioFinishRecorderListener.onFinish(mTime,     mAudioManager.getCurrentFilePath());   }   } else if (mCurState == STATE_WANT_TO_CANCEL) {   mDialogManager.dimissDailog();   mAudioManager.cancel();   }   // 恢复标志位   reset();   break;   default:   break;  }  return super.onTouchEvent(event);  }   private void reset() {  // TODO Auto-generated method stub  mReady = false;  mTime = 0;  isRecording = false;  changeState(STATE_NORMAL);  }   private boolean wantToCancel(int x, int y) {  // x<0代表来到按钮的范围以外  if (x < 0 || x > getWidth()) {   return true;   }  if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {   return true;   }  return false;  }   private void changeState(int state) {  // TODO Auto-generated method stub  if (mCurState != state) {   mCurState = state;    switch (state) {   case STATE_NORMAL:   setBackgroundResource(R.drawable.button_recorder_normal);   setText(R.string.str_recorder_nomal);   break;    case STATE_RECORDING:   setBackgroundResource(R.drawable.button_recorder_recording);   setText(R.string.str_recorder_recording);   if (isRecording) {    // to do    mDialogManager.recording();   }   break;    case STATE_WANT_TO_CANCEL:   setBackgroundResource(R.drawable.button_recorder_recording);   setText(R.string.str_recorder_want_cancel);   mDialogManager.wantToCancle();   break;   default:   break;   }  }  }   /** 完成录音回调 */  public interface AudioFinishRecorderListener {  void onFinish(float seconds, String filePath);  }   private AudioFinishRecorderListener audioFinishRecorderListener;   public void setAudioFinishRecorderListener(   AudioFinishRecorderListener audioFinishRecorderListener) {  this.audioFinishRecorderListener = audioFinishRecorderListener;  } } 

DialogManager

package com.example.recorder_view;  import com.example.imooc_recorder.R;  import android.app.Dialog; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView;  public class DialogManager {  private Dialog mDialog;  private ImageView mIcon;  private ImageView mVoice;  private TextView mLabel;  private Context mContext;   public DialogManager(Context context) {  this.mContext = context;  }   public void showRecordingDailog() {  mDialog = new Dialog(mContext, R.style.Theme_AudioDialog);  LayoutInflater inflater = LayoutInflater.from(mContext);  View view = inflater.inflate(R.layout.dialog_recorder, null);  mDialog.setContentView(view);   mIcon = (ImageView) mDialog.findViewById(R.id.id_recorder_dialog_icon);  mVoice = (ImageView) mDialog   .findViewById(R.id.id_recorder_dialog_voice);  mLabel = (TextView) mDialog.findViewById(R.id.id_recorder_dialog_label);   mDialog.show();  }   public void recording() {  if (mDialog != null && mDialog.isShowing()) {   mIcon.setVisibility(View.VISIBLE);   mVoice.setVisibility(View.VISIBLE);   mLabel.setVisibility(View.VISIBLE);    mIcon.setImageResource(R.drawable.recorder);   mLabel.setText("手指上滑,取消发送");   }  }   public void wantToCancle() {  if (mDialog != null && mDialog.isShowing()) {   mIcon.setVisibility(View.VISIBLE);   mVoice.setVisibility(View.GONE);   mLabel.setVisibility(View.VISIBLE);    mIcon.setImageResource(R.drawable.cancel);   mLabel.setText("松开手指,取消发送");   }  }   public void tooShort() {  if (mDialog != null && mDialog.isShowing()) {   mIcon.setVisibility(View.VISIBLE);   mVoice.setVisibility(View.GONE);   mLabel.setVisibility(View.VISIBLE);    mIcon.setImageResource(R.drawable.voice_to_short);   mLabel.setText("录音时间过短");   }   }   public void dimissDailog() {  if (mDialog != null && mDialog.isShowing()) {   mDialog.dismiss();   mDialog = null;  }  }   public void updateVoiceLeve(int level) {  if (mDialog != null && mDialog.isShowing()) { //  mIcon.setVisibility(View.VISIBLE); //  mVoice.setVisibility(View.VISIBLE); //  mLabel.setVisibility(View.VISIBLE);    // 通过方法名字,找到资源   int resId = mContext.getResources().getIdentifier("v" + level,    "drawable", mContext.getPackageName());   mVoice.setImageResource(resId);  }  }  } 

AudioManager

package com.example.recorder_view;  import java.io.File; import java.io.IOException; import java.util.UUID;  import javax.security.auth.PrivateCredentialPermission;  import android.R.integer; import android.media.MediaRecorder;  public class AudioManager {   private MediaRecorder mMediaRecorder;  private String mDir;  private String mCurrentFilepath;  private static AudioManager mInstance;   private boolean isPrepare;   /** 接口回调 */  public interface AudioStateListener {  void wellPrepared();  }   public AudioStateListener mAudioStateListener;   public void setOnAudioStateListener(AudioStateListener audioStateListener) {  mAudioStateListener = audioStateListener;   }   private AudioManager(String dir) {  this.mDir = dir;  }   public static AudioManager getInstance(String dir) {  if (mInstance == null) {   synchronized (AudioManager.class) {   if (mInstance == null) {    mInstance = new AudioManager(dir);    }    }  }  return mInstance;  }   public void prepareAndio() {  isPrepare = false;  File dir = new File(mDir);  if (!dir.exists()) {   dir.mkdirs();  }  String fileName = geneFileName();   File file = new File(dir, fileName);  mCurrentFilepath = file.getAbsolutePath();  mMediaRecorder = new MediaRecorder();  // 设置输出文件  mMediaRecorder.setOutputFile(file.getAbsolutePath());  // 音频源头  mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  // 设置音频格式  mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);  // 设置音频编码  mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  try {   mMediaRecorder.prepare();   mMediaRecorder.start();   isPrepare = true;   if (mAudioStateListener != null) {   mAudioStateListener.wellPrepared();    }  } catch (Exception e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  }   private String geneFileName() {  return UUID.randomUUID().toString() + ".amr";  }   public int getVoiceLevel(int maxLevel) {  if (isPrepare) {   try {   // mMediaRecorder.getMaxAmplitude() 1~32767   // return maxlevel*mMediaRecorder.getMaxAmplitude()/32768+1;   return maxLevel * new MediaRecorder().getMaxAmplitude() / 32768    + 1;   } catch (Exception e) {   }   }  return 1;  }   public void release() {  mMediaRecorder.release();  mMediaRecorder = null;  }   public void cancel() {  release();  if (mCurrentFilepath != null) {   File file = new File(mCurrentFilepath);   file.delete();   mCurrentFilepath = null;   }  }   public String getCurrentFilePath() {  // TODO Auto-generated method stub  return mCurrentFilepath;  }  } 

MediaManager

package com.example.recorder_view;  import java.io.IOException;  import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener;  public class MediaManager {   private static MediaPlayer mediaPlayer;  private static boolean isPause;  public static void playSound(String filePath,   OnCompletionListener onCompletionListener) {  if (mediaPlayer == null) {   mediaPlayer = new MediaPlayer();   mediaPlayer.setOnErrorListener(new OnErrorListener() {      @Override   public boolean onError(MediaPlayer mp, int what, int extra) {    mediaPlayer.reset();    return false;   }   });  }else {   mediaPlayer.reset();  }  try {   mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);   mediaPlayer.setOnCompletionListener(onCompletionListener);   mediaPlayer.setDataSource(filePath);   mediaPlayer.prepare();  } catch (Exception e) {   e.printStackTrace();  }  mediaPlayer.start();  }    public static void pause(){  if (mediaPlayer!=null && mediaPlayer.isPlaying()) {   mediaPlayer.pause();   isPause = true;  }  }  public static void resume(){  if (mediaPlayer!=null && isPause) {   mediaPlayer.start();   isPause = false;  }  }  public static void release(){  if (mediaPlayer!=null) {   mediaPlayer.release();   mediaPlayer = null;    }  } } 

本文已被整理到了《Android微信开发教程汇总》,欢迎大家学习阅读。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表