上一篇文章里,我們介紹了整個項目以及實現了按鈕功能。沒有讀的可以點擊一下鏈接:
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程序,看看有什么新的效果呢?