上一篇文章里,我们介绍了整个项目以及实现了按钮功能。没有读的可以点击一下链接:
http://www.cnblogs.com/fuly550871915/p/4836042.html
在本篇文章里,我们做第二步,也就是实现几种状态的对话框:录音状态的对话框,取消录音状态下的对话框,录音时间太短下的对话框。然后将对话框集成到我们点击时的按钮操作中。
首先我们需要自定义一个对话框的布局。不难想出,布局中的上方需要并排放置两张图片,下方是一个用来提示状态的文本。如果对话框切换到录音时的状态,我们就让其中的一张图片显示,另外一张不显示即可。所以整体的布局是这样的,名称为dialog.xml:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="wrap_content" 4 android:layout_height="wrap_content" 5 android:orientation="vertical" 6 android:background="@drawable/dialog_loading_bg"> 7 8 <LinearLayout 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content"> 11 12 <ImageView 13 android:id="@+id/img_recoder" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:src="@drawable/recorder" 17 android:visibility="visible"/> 18 <ImageView 19 android:id="@+id/img_voice" 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:src="@drawable/v1" 23 android:visibility="visible"/> 24 </LinearLayout> 25 26 <TextView 27 android:id="@+id/tv_dialog_txt" 28 android:layout_width="wrap_content" 29 android:layout_height="wrap_content" 30 android:text="@string/dialog_recoding" 31 android:textColor="@color/red" 32 android:layout_gravity="center" 33 android:textSize="20dip"/> 34 35 36 37 38 </LinearLayout>
接下来我们定义一下对话框的样式,在这里关键是要求对话框弹出时,不要屏幕掉屏幕,也就是屏幕的其他部分仍然是点击有效的。在res的values下的styles下,加入一下代码:
1 <style name = "dialogStyle"> 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>
然后我们实现对话框这个类,代码如下:
1 package com.fuly.util; 2 3 import com.fuly.irecoder.R; 4 5 import android.app.Dialog; 6 import android.content.Context; 7 import android.view.LayoutInflater; 8 import android.view.View; 9 import android.widget.ImageView; 10 import android.widget.TextView; 11 12 //对话框管理类 13 14 public class DialogManager { 15 16 17 private Dialog dialog; 18 19 private ImageView imgDialogRecoder; 20 private ImageView imgVoice; 21 private TextView tvDialog; 22 23 private Context mContext; 24 25 public DialogManager(Context context){ 26 27 mContext = context; 28 29 30 } 31 32 33 public void dialogShow(){ 34 35 //此时我们选择我们自己的对话框样式 36 dialog = new Dialog(mContext, R.style.dialogStyle); 37 View view = LayoutInflater.from(mContext).inflate(R.layout.dialog, null); 38 dialog.setContentView(view); 39 dialog.show(); 40 41 //获取控件,用来在下面的代码中改变他们的状态 42 imgDialogRecoder = (ImageView) dialog.findViewById(R.id.img_recoder); 43 imgVoice = (ImageView) dialog.findViewById(R.id.img_voice); 44 tvDialog = (TextView) dialog.findViewById(R.id.tv_dialog_txt); 45 46 } 47 48 49 //录音时的对话框状态 50 public void dialogRecoding(){ 51 52 imgDialogRecoder.setVisibility(View.VISIBLE); 53 imgVoice.setVisibility(View.VISIBLE); 54 55 imgDialogRecoder.setImageResource(R.drawable.recorder); 56 imgVoice.setImageResource(R.drawable.v1); 57 58 tvDialog.setText(R.string.dialog_recoding); 59 60 } 61 62 63 64 //录音时,要更新声音等级,即让imgVoice动起来 65 public void updateVoiceLevel(int level){ 66 67 //根据字符串和包名来获得所对应的资源文件,在这里获取的R.drawable下的文件 68 int resId = mContext.getResources().getIdentifier("v"+level,"drawable",mContext.getPackageName()); 69 70 imgVoice.setImageResource(resId); 71 } 72 73 74 75 76 77 78 79 //录音取消时的对话框状态 80 public void dialogRecoderCancel(){ 81 82 83 imgDialogRecoder.setVisibility(View.VISIBLE); 84 imgVoice.setVisibility(View.GONE); 85 86 imgDialogRecoder.setImageResource(R.drawable.cancel); 87 tvDialog.setText(R.string.dialog_cacel); 88 89 } 90 91 92 public void tooShort(){ 93 94 imgDialogRecoder.setVisibility(View.VISIBLE); 95 imgVoice.setVisibility(View.GONE); 96 97 imgDialogRecoder.setImageResource(R.drawable.voice_to_short); 98 tvDialog.setText(R.string.too_short); 99 100 } 101 102 //取消对话框 103 public void dialogDismiss(){ 104 105 if(dialog != null){ 106 dialog.dismiss(); 107 } 108 } 109 110 111 }
然后修改strings.xml文件。为什么所有的文字我们非得这么麻烦的放在这个文件里引用的。答案是:这样子做可以有效的防止你的app的内存占用。所以要养成良好的编程习惯。不多说了,代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <string name="app_name">irecoder</string> 5 <string name="action_settings">Settings</string> 6 <string name="btn_normal">按住 录音</string> 7 <string name="btn_recoding">松开 结束</string> 8 <string name="btn_cancel">手指上滑,取消录音 </string> 9 <string name="dialog_recoding">手指上滑,取消录音 </string> 10 <string name="dialog_cacel">松开手指 取消发送</string> 11 12 13 </resources>
然后我们要配置颜色了,在res下的values文件夹下的color.xml(如果没有你就新建一个)里面写上下面的代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <color name="black">#000000</color> 5 <color name="red">#CC0000</color> 6 <color name="white">#ffffff</color> 7 8 </resources>
好了,关于对话框的工作我们基本上算是完成了。下面将其集成到按钮中,我们打开RecoderButton类,修改其中的代码如下:
1 package com.fuly.util; 2 3 4 import com.fuly.irecoder.R; 5 6 import android.content.Context; 7 import android.util.AttributeSet; 8 import android.view.MotionEvent; 9 import android.widget.Button; 10 11 12 //定义我们自己的录音按钮 13 public class RecoderButton extends Button{ 14 15 //按钮的三个状态 16 17 private static final int STATE_NORMAL = 1;//正常 18 private static final int STATE_RECODING = 2;//录音状态 19 private static final int STATE_CACLE = 3;//取消状态 20 21 private int mCurState = STATE_NORMAL;//记录当前按钮状态 22 23 private int Y = 50;//限定手指移动的上下宽度 24 25 private DialogManager mDialogManager;//对话框管理类 26 27 28 29 30 public RecoderButton(Context context, AttributeSet attrs) { 31 super(context, attrs); 32 33 mDialogManager = new DialogManager(context);//实例化对话框管理类 34 35 } 36 37 38 39 //捕捉按钮点击事件 40 public boolean onTouchEvent(MotionEvent event) { 41 42 int x = (int) event.getX(); 43 int y =(int)event.getY(); 44 45 switch(event.getAction()){ 46 47 48 case MotionEvent.ACTION_DOWN: 49 50 mDialogManager.dialogShow();//按下按钮的同时将对话框显示出来 51 changeState(STATE_RECODING);//按下按钮,改变按钮状态 52 53 54 break; 55 case MotionEvent.ACTION_MOVE: 56 57 if(wantCancel(x,y)){ //如果检测到取消,则改变按钮状态为取消 58 59 changeState(STATE_CACLE); 60 61 }else{ 62 changeState(STATE_RECODING); 63 } 64 65 break; 66 case MotionEvent.ACTION_UP: 67 68 mDialogManager.dialogDismiss(); 69 70 reset();//各种设置复位 71 72 break; 73 default: 74 break; 75 } 76 77 return super.onTouchEvent(event); 78 } 79 80 81 82 //复位 83 private void reset() { 84 85 mCurState = STATE_NORMAL; 86 changeState(STATE_NORMAL); 87 88 } 89 90 91 92 //检查手指移动范围,从而确定用户是否想取消录音 93 private boolean wantCancel(int x, int y) { 94 95 if(x<0||x>getWidth()){ 96 97 return true; 98 } 99 100 if(y<0||y>getHeight()+Y){ 101 return true; 102 } 103 return false; 104 } 105 106 107 108 //改变状态,包括按钮等操作 109 private void changeState(int state) { 110 111 if(mCurState != state){ 112 113 mCurState = state; 114 115 } 116 117 switch(mCurState){ 118 119 case STATE_NORMAL: 120 121 setText(R.string.btn_normal); 122 123 break; 124 case STATE_RECODING: 125 126 setText(R.string.btn_recoding); 127 128 mDialogManager.dialogRecoding(); 129 130 break; 131 case STATE_CACLE: 132 133 setText(R.string.btn_cancel); 134 135 mDialogManager.dialogRecoderCancel();//此时也要将对话框的状态显示出来 136 137 break; 138 default: 139 break; 140 141 } 142 143 } 144 145 146 147 }
行了,至此,我们这一阶段的工作算是完成了。下面赶紧运行以下android程序,看看有什么新的效果呢?