即时通讯里面发送语音时按钮状态的改变
做的一个项目里面有发送语音的功能,用到自定义view,自定义一个Button,有三种状态,
如下,在res/values/strings目录下添加
<resources>
<string name="app_name">IMOOC_Recording_sample</string>
<string name="str_recorder_normal">按住说话</string>
<string name="str_recorder_recording">松开结束</string>
<string name="str_recorder_want_cancle">松开手指,取消发送</string>
</resources>
在res/drawable目录下需要定义按钮的两种状态,代码如下
第一个normal状态的为
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffff"/>
<stroke
android:width="1px"
android:color="#9b9b9b"/>
<corners android:radius="3dp"/>
</shape>
第二个recording.xml状态的为
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#eeeeee"/>
<stroke
android:width="1px"
android:color="#9b9b9b"/>
<corners android:radius="3dp"/>
</shape>
布局文件如下,简单的一个listview,一个按钮,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ListView
android:id="@+id/id_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="@null"
android:dividerHeight="10dp"
android:background="#ebebeb"
>
</ListView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.administrator.imooc_recording_sample.AudioRecorderButton
android:id="@+id/id_recorder_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="7dp"
android:gravity="center"
android:minHeight="0dp"
android:background="@drawable/btn_recorder_normal"
android:padding="5dp"
android:text="@string/str_recorder_normal"
android:textColor="#727272"
>
</com.administrator.imooc_recording_sample.AudioRecorderButton>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ccc">
</View>
</FrameLayout>
</LinearLayout>
自定义按钮新建一个类buttonRecording,代码如下,只给出简单的大致框架,因为遇到的问题在前面,运行后只显示了两种状态,“松开手指,取消发送”这个状态没显示出来,查了好哒一会儿才知道原因,新建的按钮类AudioRecorderButton代码如下
`package com.administrator.imooc_recording_sample;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
/**
* Created by Administrator on 2017/4/6 0006.
*/
public class AudioRecorderButton extends Button{
private static final int DISTANCE_Y_CANCLE=50;
private static final int STATE_NORMAL=1;
private static final int STATE_RECORDING=2;
private static final int STATE_WANT_TO_CANCLE=3;
private int mCurState=STATE_NORMAL;
//已经开始录音
private boolean isRecording=false;
public AudioRecorderButton(Context context) {
this(context,null);
}
public AudioRecorderButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action=event.getAction();
int x= (int) event.getX();
int y= (int) event.getY();
System.out.println(x);
System.out.println(getWidth());
switch (action){
case MotionEvent.ACTION_DOWN:
changeState(STATE_RECORDING);
break;
case MotionEvent.ACTION_MOVE:
if (isRecording){
//根据x,y的坐标判断是否想要取消
if (wantToCancle(x,y)){
changeState(STATE_WANT_TO_CANCLE);
}else {
changeState(STATE_RECORDING);
}
}
break;
case MotionEvent.ACTION_UP:
if (mCurState==STATE_RECORDING){
//release
//callBackToAct
}else if (mCurState==STATE_WANT_TO_CANCLE){
//cancle
}
reset();
break;
default:
break;
}
return super.onTouchEvent(event);
}
//回复状态及标志位
private void reset() {
isRecording=false;
changeState(STATE_NORMAL);
}
private boolean wantToCancle(int x, int y) {
//判断手指的横坐标是否超出按钮范围
if(x<0||x>getWidth()){
return true;
}
//判断手指的纵坐标是否超出按钮范围
if (y<-DISTANCE_Y_CANCLE||y>getHeight()+DISTANCE_Y_CANCLE){
return true;
}
return false;
}
private void changeState(int state) {
if (mCurState!=state){
mCurState=state;
switch (state){
case STATE_NORMAL:
setBackgroundResource(R.drawable.btn_recorder_normal);
setText(R.string.str_recorder_normal);
break;
case STATE_RECORDING:
setBackgroundResource(R.drawable.btn_recording);
setText(R.string.str_recorder_recording);
if(isRecording){
//TODO Dialog.recording;
}
break;
case STATE_WANT_TO_CANCLE:
setBackgroundResource(R.drawable.btn_recording);
setText(R.string.str_recorder_want_cancle);
//TODO Dialog.wantCancle;
break;
}
}
}
}
运行后显示不出第三种状态,是因为判断第三种状态的代码一直没有执行,在松开手指,滑动取消之前要确保按钮被按下,即按钮状态应该为STATE_RECORDING,所以在判断手指是否移开按钮之外之前加上一句 isRecording=true;这句代码不是必须加到此处,也可以加到
case MotionEvent.ACTION_DOWN:
changeState(STATE_RECORDING);
isRecording=true;
break;
case MotionEvent.ACTION_MOVE:
if (isRecording){
//根据x,y的坐标判断是否想要取消
if (wantToCancle(x,y)){
changeState(STATE_WANT_TO_CANCLE);
}else {
changeState(STATE_RECORDING);
}
}`
最后问题解决,希望能帮助到大家,也随手记下自己碰到的问题。