Android自定义UI实现微信语音
本文实例为大家分享了java获取不同路径的方法,供大家参考,具体内容如下
思路:
自定义Button
获取DialogManager、AudioManagersetOnLongClickListener长按事件--做好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
<LinearLayoutxmlns: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布局文件
<LinearLayoutxmlns: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
<RelativeLayoutxmlns: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
<stylename="Theme_AudioDialog"parent="@android:Theme.Dialog"> <itemname="android:windowBackground">@android:color/transparent</item> <itemname="android:windowFrame">@null</item> <itemname="android:windowIsFloating">true</item> <itemname="android:windowIsTranslucent">true</item> <itemname="android:backgroundDimEnabled">false</item> </style>
button_recorder_normal.xml
<?xmlversion="1.0"encoding="utf-8"?> <shapexmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solidandroid:color="#ffffff"/> <strokeandroid:width="1px"android:color="#9b9b9b"/> <cornersandroid:radius="3dp"/> </shape>
button_recorder_recording.xml
<?xmlversion="1.0"encoding="utf-8"?> <shapexmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solidandroid:color="#ffffff"/> <strokeandroid:width="1px"android:color="#eeeeee"/> <cornersandroid:radius="3dp"/> </shape>
play_anim.xml
<?xmlversion="1.0"encoding="utf-8"?> <animation-listxmlns: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
packagecom.example.imooc_recorder; importjava.util.ArrayList; importjava.util.List; importcom.example.recorder_view.AudioRecorderButton; importcom.example.recorder_view.AudioRecorderButton.AudioFinishRecorderListener; importcom.example.recorder_view.MediaManager; importandroid.app.Activity; importandroid.graphics.drawable.AnimationDrawable; importandroid.media.MediaPlayer; importandroid.os.Bundle; importandroid.view.Menu; importandroid.view.MenuItem; importandroid.view.View; importandroid.widget.AdapterView.OnItemClickListener; importandroid.widget.AdapterView; importandroid.widget.ArrayAdapter; importandroid.widget.ListView; publicclassMainActivityextendsActivity{ privateListViewmListView; privateArrayAdapter<Recorder>mAdapter; privateList<Recorder>mDatas=newArrayList<MainActivity.Recorder>(); privateAudioRecorderButtonmAudioRecorderButton; privateViewanimView; @Override protectedvoidonCreate(BundlesavedInstanceState){ 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(newAudioFinishRecorderListener(){ @Override publicvoidonFinish(floatseconds,StringfilePath){ //TODOAuto-generatedmethodstub Recorderrecorder=newRecorder(seconds,filePath); mDatas.add(recorder); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size()-1); } }); mAdapter=newRecorderAdapter(this,mDatas); mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(newOnItemClickListener(){ @Override publicvoidonItemClick(AdapterView<?>parent,Viewview, intposition,longid){ if(animView!=null){ animView.setBackgroundResource(R.drawable.adj); animView=null; } //播放动画 animView=view.findViewById(R.id.id_recorder_anim); animView.setBackgroundResource(R.drawable.play_anim); AnimationDrawableanim=(AnimationDrawable)animView.getBackground(); anim.start(); //播放音频 MediaManager.playSound(mDatas.get(position).filePath,newMediaPlayer.OnCompletionListener(){ @Override publicvoidonCompletion(MediaPlayermp){ //TODOAuto-generatedmethodstub animView.setBackgroundResource(R.drawable.adj); } }); } }); } @Override protectedvoidonPause(){ //TODOAuto-generatedmethodstub super.onPause(); MediaManager.pause(); } @Override protectedvoidonResume(){ //TODOAuto-generatedmethodstub super.onResume(); MediaManager.resume(); } @Override protectedvoidonDestroy(){ //TODOAuto-generatedmethodstub super.onDestroy(); MediaManager.release(); } /**内部类*/ classRecorder{ floattime; StringfilePath; publicRecorder(floattime,StringfilePath){ super(); this.time=time; this.filePath=filePath; } publicfloatgetTime(){ returntime; } publicvoidsetTime(floattime){ this.time=time; } publicStringgetFilePath(){ returnfilePath; } publicvoidsetFilePath(StringfilePath){ this.filePath=filePath; } } }
RecorderAdapter
packagecom.example.imooc_recorder; importjava.util.List; importcom.example.imooc_recorder.MainActivity.Recorder; importandroid.content.Context; importandroid.util.DisplayMetrics; importandroid.view.LayoutInflater; importandroid.view.View; importandroid.view.ViewGroup; importandroid.view.WindowManager; importandroid.widget.ArrayAdapter; importandroid.widget.BaseAdapter; importandroid.widget.LinearLayout; importandroid.widget.TextView; publicclassRecorderAdapterextendsArrayAdapter<Recorder>{ //privateList<Recorder>mDatas; //privateContextmContext; privateintmMinItemWidth; privateintmMaxItemWidth; privateLayoutInflatermInflater; publicRecorderAdapter(Contextcontext,List<Recorder>datas){ super(context,-1,datas); //mContext=context; //mDatas=datas; WindowManagerwm=(WindowManager)context .getSystemService(Context.WINDOW_SERVICE); DisplayMetricsoutMetrics=newDisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); mMaxItemWidth=(int)(outMetrics.widthPixels*0.7f); mMinItemWidth=(int)(outMetrics.widthPixels*0.15f); mInflater=LayoutInflater.from(context); } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ //TODOAuto-generatedmethodstub ViewHolderholder=null; if(convertView==null){ convertView=mInflater.inflate(R.layout.item_recorder,parent, false); holder=newViewHolder(); 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.LayoutParamslp=holder.length.getLayoutParams(); lp.width=(int)(mMinItemWidth+(mMaxItemWidth/60f*getItem(position).time)); returnconvertView; } privateclassViewHolder{ privateTextViewseconds; privateViewlength; } }
AudioRecorderButton
packagecom.example.recorder_view; importcom.example.imooc_recorder.R; importcom.example.recorder_view.AudioManager.AudioStateListener; importandroid.content.Context; importandroid.os.Environment; importandroid.os.Handler; importandroid.telephony.SignalStrength; importandroid.util.AttributeSet; importandroid.view.MotionEvent; importandroid.view.View; importandroid.widget.Button; publicclassAudioRecorderButtonextendsButtonimplementsAudioStateListener{ privatestaticfinalintDISTANCE_Y_CANCEL=50; /**提示框管理工具类*/ privateDialogManagermDialogManager; /**正常、松开手指取消发送、手指上滑取消发送*/ privatestaticfinalintSTATE_NORMAL=1; privatestaticfinalintSTATE_RECORDING=2; privatestaticfinalintSTATE_WANT_TO_CANCEL=3; /**初始状态:正常*/ privateintmCurState=STATE_NORMAL; /**当前是否正在录音*/ privatebooleanisRecording=false; /**录音工具类*/ privateAudioManagermAudioManager; /**录音总时间*/ privatefloatmTime; /**是否触发button*/ privatebooleanmReady; /*******************自定义Button**************************************/ publicAudioRecorderButton(Contextcontext){ super(context); } publicAudioRecorderButton(Contextcontext,AttributeSetattrs,intdefStyle){ super(context,attrs,defStyle); } publicAudioRecorderButton(Contextcontext,AttributeSetattrs){ super(context,attrs); mDialogManager=newDialogManager(getContext()); Stringdir=Environment.getExternalStorageDirectory() +"/imooc_recorder_audios"; mAudioManager=AudioManager.getInstance(dir); mAudioManager.setOnAudioStateListener(this); /**监听回调*/ setOnLongClickListener(newOnLongClickListener(){ @Override publicbooleanonLongClick(Viewv){ mReady=true; //录音准备--准备好后,有实现接口方法 mAudioManager.prepareAndio(); returnfalse; } }); } /****************************************************** *完成录音准备的回调函数 */ @Override publicvoidwellPrepared(){ //准备完毕,发送消息 mHandler.sendEmptyMessage(MSG_AUDIO_PREPARE); } privateHandlermHandler=newHandler(){ publicvoidhandleMessage(android.os.Messagemsg){ switch(msg.what){ caseMSG_AUDIO_PREPARE: mDialogManager.showRecordingDailog(); isRecording=true; newThread(newRunnable(){ @Override publicvoidrun(){ //TODOAuto-generatedmethodstub while(isRecording){ try{ Thread.sleep(100); //录音计时 mTime+=0.1f; mHandler.sendEmptyMessage(MSG_VOICE_CHANGED); }catch(InterruptedExceptione){ e.printStackTrace(); } } } }).start(); break; caseMSG_VOICE_CHANGED: mDialogManager.updateVoiceLeve(mAudioManager.getVoiceLevel(7)); break; caseMSG_DIALOG_DIMISS: mDialogManager.dimissDailog(); break; default: break; } super.handleMessage(msg); }; }; privatestaticfinalintMSG_AUDIO_PREPARE=0x110; privatestaticfinalintMSG_VOICE_CHANGED=0x111; privatestaticfinalintMSG_DIALOG_DIMISS=0x112; @Override publicbooleanonTouchEvent(MotionEventevent){ //TODOAuto-generatedmethodstub intaction=event.getAction(); intx=(int)event.getX(); inty=(int)event.getY(); switch(action){ caseMotionEvent.ACTION_DOWN: changeState(STATE_RECORDING); break; caseMotionEvent.ACTION_MOVE: if(isRecording){ //根据xy坐标。判断是否想要取消 if(wantToCancel(x,y)){ changeState(STATE_WANT_TO_CANCEL); }else{ changeState(STATE_RECORDING); } } break; caseMotionEvent.ACTION_UP: if(!mReady){ //没有触发onclick reset(); returnsuper.onTouchEvent(event); } if(!isRecording||mTime<0.6f){ //prapred没有完成已经up了 mDialogManager.tooShort(); mAudioManager.cancel(); mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS,1300); }elseif(mCurState==STATE_RECORDING){ mDialogManager.dimissDailog(); mAudioManager.release(); if(audioFinishRecorderListener!=null){ audioFinishRecorderListener.onFinish(mTime, mAudioManager.getCurrentFilePath()); } }elseif(mCurState==STATE_WANT_TO_CANCEL){ mDialogManager.dimissDailog(); mAudioManager.cancel(); } //恢复标志位 reset(); break; default: break; } returnsuper.onTouchEvent(event); } privatevoidreset(){ //TODOAuto-generatedmethodstub mReady=false; mTime=0; isRecording=false; changeState(STATE_NORMAL); } privatebooleanwantToCancel(intx,inty){ //x<0代表来到按钮的范围以外 if(x<0||x>getWidth()){ returntrue; } if(y<-DISTANCE_Y_CANCEL||y>getHeight()+DISTANCE_Y_CANCEL){ returntrue; } returnfalse; } privatevoidchangeState(intstate){ //TODOAuto-generatedmethodstub if(mCurState!=state){ mCurState=state; switch(state){ caseSTATE_NORMAL: setBackgroundResource(R.drawable.button_recorder_normal); setText(R.string.str_recorder_nomal); break; caseSTATE_RECORDING: setBackgroundResource(R.drawable.button_recorder_recording); setText(R.string.str_recorder_recording); if(isRecording){ //todo mDialogManager.recording(); } break; caseSTATE_WANT_TO_CANCEL: setBackgroundResource(R.drawable.button_recorder_recording); setText(R.string.str_recorder_want_cancel); mDialogManager.wantToCancle(); break; default: break; } } } /**完成录音回调*/ publicinterfaceAudioFinishRecorderListener{ voidonFinish(floatseconds,StringfilePath); } privateAudioFinishRecorderListeneraudioFinishRecorderListener; publicvoidsetAudioFinishRecorderListener( AudioFinishRecorderListeneraudioFinishRecorderListener){ this.audioFinishRecorderListener=audioFinishRecorderListener; } }
DialogManager
packagecom.example.recorder_view; importcom.example.imooc_recorder.R; importandroid.app.Dialog; importandroid.content.Context; importandroid.view.LayoutInflater; importandroid.view.View; importandroid.widget.ImageView; importandroid.widget.TextView; publicclassDialogManager{ privateDialogmDialog; privateImageViewmIcon; privateImageViewmVoice; privateTextViewmLabel; privateContextmContext; publicDialogManager(Contextcontext){ this.mContext=context; } publicvoidshowRecordingDailog(){ mDialog=newDialog(mContext,R.style.Theme_AudioDialog); LayoutInflaterinflater=LayoutInflater.from(mContext); Viewview=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(); } publicvoidrecording(){ if(mDialog!=null&&mDialog.isShowing()){ mIcon.setVisibility(View.VISIBLE); mVoice.setVisibility(View.VISIBLE); mLabel.setVisibility(View.VISIBLE); mIcon.setImageResource(R.drawable.recorder); mLabel.setText("手指上滑,取消发送"); } } publicvoidwantToCancle(){ if(mDialog!=null&&mDialog.isShowing()){ mIcon.setVisibility(View.VISIBLE); mVoice.setVisibility(View.GONE); mLabel.setVisibility(View.VISIBLE); mIcon.setImageResource(R.drawable.cancel); mLabel.setText("松开手指,取消发送"); } } publicvoidtooShort(){ 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("录音时间过短"); } } publicvoiddimissDailog(){ if(mDialog!=null&&mDialog.isShowing()){ mDialog.dismiss(); mDialog=null; } } publicvoidupdateVoiceLeve(intlevel){ if(mDialog!=null&&mDialog.isShowing()){ //mIcon.setVisibility(View.VISIBLE); //mVoice.setVisibility(View.VISIBLE); //mLabel.setVisibility(View.VISIBLE); //通过方法名字,找到资源 intresId=mContext.getResources().getIdentifier("v"+level, "drawable",mContext.getPackageName()); mVoice.setImageResource(resId); } } }
AudioManager
packagecom.example.recorder_view; importjava.io.File; importjava.io.IOException; importjava.util.UUID; importjavax.security.auth.PrivateCredentialPermission; importandroid.R.integer; importandroid.media.MediaRecorder; publicclassAudioManager{ privateMediaRecordermMediaRecorder; privateStringmDir; privateStringmCurrentFilepath; privatestaticAudioManagermInstance; privatebooleanisPrepare; /**接口回调*/ publicinterfaceAudioStateListener{ voidwellPrepared(); } publicAudioStateListenermAudioStateListener; publicvoidsetOnAudioStateListener(AudioStateListeneraudioStateListener){ mAudioStateListener=audioStateListener; } privateAudioManager(Stringdir){ this.mDir=dir; } publicstaticAudioManagergetInstance(Stringdir){ if(mInstance==null){ synchronized(AudioManager.class){ if(mInstance==null){ mInstance=newAudioManager(dir); } } } returnmInstance; } publicvoidprepareAndio(){ isPrepare=false; Filedir=newFile(mDir); if(!dir.exists()){ dir.mkdirs(); } StringfileName=geneFileName(); Filefile=newFile(dir,fileName); mCurrentFilepath=file.getAbsolutePath(); mMediaRecorder=newMediaRecorder(); //设置输出文件 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(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } privateStringgeneFileName(){ returnUUID.randomUUID().toString()+".amr"; } publicintgetVoiceLevel(intmaxLevel){ if(isPrepare){ try{ //mMediaRecorder.getMaxAmplitude()1~32767 //returnmaxlevel*mMediaRecorder.getMaxAmplitude()/32768+1; returnmaxLevel*newMediaRecorder().getMaxAmplitude()/32768 +1; }catch(Exceptione){ } } return1; } publicvoidrelease(){ mMediaRecorder.release(); mMediaRecorder=null; } publicvoidcancel(){ release(); if(mCurrentFilepath!=null){ Filefile=newFile(mCurrentFilepath); file.delete(); mCurrentFilepath=null; } } publicStringgetCurrentFilePath(){ //TODOAuto-generatedmethodstub returnmCurrentFilepath; } }
MediaManager
packagecom.example.recorder_view; importjava.io.IOException; importandroid.media.AudioManager; importandroid.media.MediaPlayer; importandroid.media.MediaPlayer.OnCompletionListener; importandroid.media.MediaPlayer.OnErrorListener; publicclassMediaManager{ privatestaticMediaPlayermediaPlayer; privatestaticbooleanisPause; publicstaticvoidplaySound(StringfilePath, OnCompletionListeneronCompletionListener){ if(mediaPlayer==null){ mediaPlayer=newMediaPlayer(); mediaPlayer.setOnErrorListener(newOnErrorListener(){ @Override publicbooleanonError(MediaPlayermp,intwhat,intextra){ mediaPlayer.reset(); returnfalse; } }); }else{ mediaPlayer.reset(); } try{ mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setOnCompletionListener(onCompletionListener); mediaPlayer.setDataSource(filePath); mediaPlayer.prepare(); }catch(Exceptione){ e.printStackTrace(); } mediaPlayer.start(); } publicstaticvoidpause(){ if(mediaPlayer!=null&&mediaPlayer.isPlaying()){ mediaPlayer.pause(); isPause=true; } } publicstaticvoidresume(){ if(mediaPlayer!=null&&isPause){ mediaPlayer.start(); isPause=false; } } publicstaticvoidrelease(){ if(mediaPlayer!=null){ mediaPlayer.release(); mediaPlayer=null; } } }
本文已被整理到了《Android微信开发教程汇总》,欢迎大家学习阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。