zoukankan      html  css  js  c++  java
  • 模仿微信语音聊天功能(2)对话框的实现

         上一篇文章里,我们介绍了整个项目以及实现了按钮功能。没有读的可以点击一下链接:

    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程序,看看有什么新的效果呢?

  • 相关阅读:
    损失函数及经验风险和结构风险
    ML面试题网站及ML模型网站
    数据归一化
    逻辑回归
    什么是凸函数及如何判断一个函数是否是凸函数
    Feature Selection Can Reduce Overfitting And RF Show Feature Importance
    Python Machine Learning-Chapter4
    skywalking与pinpoint全链路追踪方案对比
    全)Java从单体到微服务打造房产销售平台 2018年慕课网 高清视频+源码
    CentOS7 通过YUM安装MySQL5.7
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4836108.html
Copyright © 2011-2022 走看看