zoukankan      html  css  js  c++  java
  • 模仿微信语音聊天功能(1)项目介绍及自定义按钮实现

     前言

          这几天学习了慕课网上的高仿微信语音聊天功能的课程,自己动手实现了一下。在这里将其实现的过程以及代码分享下来。由于我是android的初学者,里面有不成熟的地方欢迎大家指正。

         项目中所用的图片可以在这个地方下载:

    http://pan.baidu.com/disk/home

    项目简单介绍

          首先我们来看最终实现的几张效果图吧。如下:

            

                                

            我们长安按钮,就会开始录音,并且会同时弹出一个麦克风的对话框提示正在录音。如果在录音的过程中手指上滑,则会将录音取消。而如果是录音时间太短,则会提示录音时间太短,完成录音。正常录音后,会显示在按钮上方。

            从图中,不难看出在整个界面里,上方是是一个 ListView用来显示录音,而下面就是一个按钮。按钮有三种状态,即正常录音,取消录音和无操作时的默认状态。与按钮对应,对话框也有三种状态,即正常录音,录音取消,录音时间太短这三种状态。因此完成这个小项目,需要我们具备ListView的基本知识,熟悉自定义按钮和自定义对话框。同时对android提供的录音器类和音频播放的类也要基本了解。

             我打算将这个小项目分成以下几步来做:

     (1)完成按钮的交互设计。

    (2)完成对话框的设计。

    (3)完成录音时的代码部分,并集成到之前的代码里。

    (4)完成播放设置,项目也从此结束。

            上面只是我为了学习知识,简单实现的UI。并不是很好看,读者有要求,可以自己耐心调一调,让界面好看一点。在这里我不打算讲解所涉及的android中的基础知识,而是直接写项目的代码。好了,我们开始第一步,完成按钮的设计,即实现按钮的三种状态。

    按钮的实现

             首先把主界面给搭建起来,即上方是LisetView,下面是一个我们自定义的按钮。新建activity_main.xml,代码如下:

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="vertical">
     6     
     7     <ListView 
     8         android:id="@+id/rec_listview"
     9         android:layout_width="match_parent"
    10         android:layout_height="0dp"
    11         android:layout_weight="1"/>
    12     
    13     <FrameLayout 
    14         android:layout_width="match_parent"
    15         android:layout_height="wrap_content"
    16         >
    17         
    18         <com.fuly.util.RecoderButton
    19             android:id="@+id/btn_recoder"
    20             android:layout_width="120dp"
    21             android:layout_height="wrap_content"
    22             android:background="@drawable/btn_bg"
    23             android:layout_marginTop="5dp"
    24             android:layout_marginBottom="3dp"
    25             android:text="@string/btn_normal"
    26             android:layout_gravity="center"/>
    27         <View 
    28             android:layout_width="match_parent"
    29             android:layout_height="2dp"
    30             android:background="@color/black"/>
    31         
    32     </FrameLayout>
    33         
    34 
    35    
    36 
    37 </LinearLayout>

              接下来,在res文件下新建文件夹drawable,然后在里面新建btn_bg.xml。这是为自定义的按钮提供不同状态下的按钮背景图片。代码如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <selector
     3     xmlns:android="http://schemas.android.com/apk/res/android">
     4     <!-- 没有触摸时的图片 -->
     5     <item 
     6          android:state_focused="true"
     7          android:state_enabled="true"
     8          android:state_pressed="false" 
     9          android:drawable="@drawable/btn_normal"/>
    10         <!-- 触摸时的图片 -->
    11      <item 
    12         android:state_enabled="true"
    13         android:state_pressed="true"
    14         android:drawable="@drawable/btn_press"/>
    15        <item 
    16         android:state_enabled="true"
    17         android:state_checked="true"
    18         android:drawable="@drawable/btn_press"/>
    19      
    20      
    21      <!-- 默认时的背景图片-->
    22      <item 
    23       
    24          android:drawable="@drawable/btn_normal"/>
    25     
    26 </selector>

              然后在res下的values文件夹下的strings里面,定义按钮需要显示的文本,如下:

     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     
    10 
    11 </resources>

       接来准备工作都做的差不多了。然后实现我们的自定义按钮。新建类RecoderButton,该类继承自Button。具体代码如下:

      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 public class RecoderButton extends Button{
     13     
     14     //按钮的三个状态
     15     
     16     private static final int STATE_NORMAL = 1;//正常
     17     private static final int STATE_RECODING = 2;//录音状态
     18     private static final int STATE_CACLE = 3;//取消状态
     19     
     20     private int mCurState = STATE_NORMAL;//记录当前按钮状态
     21     
     22     private int Y = 50;//限定手指移动的上下宽度
     23     
     24     
     25     
     26 
     27     public RecoderButton(Context context, AttributeSet attrs) {
     28         super(context, attrs);
     29     
     30     }
     31     
     32     
     33     
     34     //捕捉按钮点击事件
     35     public boolean onTouchEvent(MotionEvent event) {
     36         
     37         int x = (int) event.getX();
     38         int y =(int)event.getY();
     39         
     40         switch(event.getAction()){
     41         
     42         
     43         case MotionEvent.ACTION_DOWN:
     44             
     45             changeState(STATE_RECODING);//按下按钮,改变按钮状态
     46             
     47             break;
     48         case MotionEvent.ACTION_MOVE:
     49             
     50             if(wantCancel(x,y)){ //如果检测到取消,则改变按钮状态为取消
     51                 
     52             changeState(STATE_CACLE);
     53             
     54             }else{
     55                 changeState(STATE_RECODING);
     56             }
     57             
     58             break;
     59         case MotionEvent.ACTION_UP:
     60             
     61             reset();//各种设置复位
     62             
     63             break;
     64             default:
     65                 break;
     66         }
     67         
     68         return super.onTouchEvent(event);
     69     }
     70 
     71 
     72 
     73     //复位
     74     private void reset() {
     75         
     76         mCurState = STATE_NORMAL;
     77         changeState(STATE_NORMAL);
     78         
     79     }
     80 
     81 
     82 
     83     //检查手指移动范围,从而确定用户是否想取消录音
     84     private boolean wantCancel(int x, int y) {
     85         
     86         if(x<0||x>getWidth()){
     87             
     88             return true;
     89         }
     90         
     91         if(y<0||y>getHeight()+Y){
     92             return true;
     93         }
     94         return false;
     95     }
     96 
     97 
     98     
     99     //改变状态,包括按钮等操作
    100     private void changeState(int state) {
    101         
    102         if(mCurState != state){
    103             
    104             mCurState = state;
    105             
    106         }
    107         
    108         switch(mCurState){
    109               
    110         case STATE_NORMAL:
    111             
    112             setText(R.string.btn_normal);
    113             
    114             break;
    115         case STATE_RECODING:
    116             
    117             setText(R.string.btn_recoding);
    118             
    119             break;
    120         case STATE_CACLE:
    121             
    122             setText(R.string.btn_cancel);
    123             
    124             break;
    125             default:
    126                 break;
    127         
    128         }
    129         
    130     }
    131     
    132     
    133 
    134 }

           最后,我们在主类中加载activity_main布局。如下:

     1 package com.fuly.irecoder;
     2 
     3 import android.os.Bundle;
     4 import android.app.Activity;
     5 import android.view.Menu;
     6 
     7 public class MainActivity extends Activity {
     8 
     9   
    10     protected void onCreate(Bundle savedInstanceState) {
    11         super.onCreate(savedInstanceState);
    12         setContentView(R.layout.activity_main);
    13     }
    14 
    15 
    16     @Override
    17     public boolean onCreateOptionsMenu(Menu menu) {
    18         // Inflate the menu; this adds items to the action bar if it is present.
    19         getMenuInflater().inflate(R.menu.main, menu);
    20         return true;
    21     }
    22     
    23 }

        然后我们运行这个android项目即可。就会发现随着我们手指的移动,按钮呈现出我们想要的状态。

    当然了,为了好看,我们在AndroidManifest文件里让app全屏显示。只需要加上这么一句即可:

    1  android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" 

         好了,我们的第一步总算迈出去了。主要就是一个自定义按钮的实现。下一文章中我们将会实现对话框。

           

            

  • 相关阅读:
    点击退出 防止回退
    AngularJS select中ngOptions用法详解
    git hub
    .ashx datatable转excel
    写日志 log 到文件夹
    easyui layout 布局title
    easyui tree 折叠节点
    转json using指令
    Qt QWindow转QWidget
    CEF 重写弹窗事件
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4836042.html
Copyright © 2011-2022 走看看