安卓模仿微信语音通话 模仿微信语音聊天通话
在本篇文章里,我们做第二步,也就是实现几种状态的对话框:录音状态的对话框,取消录音状态下的对话框,录音时间太短下的对话框。然后将对话框集成到我们点击时的按钮操作中。
首先我们需要自定义一个对话框的布局。不难想出,布局中的上方需要并排放置两张图片,下方是一个用来提示状态的文本。如果对话框切换到录音时的状态,我们就让其中的一张图片显示,另外一张不显示即可。所以整体的布局是这样的,名称为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程序,看看有什么新的效果呢?
上一篇: 仿微信语音呼叫蓝牙将 Android 微信语音转为蓝牙
下一篇: uniapp 微信小程序 多人语音