实现语音聊天播放自定义View
来源:互联网 发布:光伏电站数据采集器 编辑:程序博客网 时间:2024/05/16 09:33
当我们需要实现一个聊天功能的时候必然要涉及语音聊天功能,语音播放时候像QQ、微信都有语音播放的View,这里我们就开始自己来实现一个这么一个View,效果如下:
这里我们使用了两种方式实现
1、通过自定义View的方式
2、通过帧动画的方式
两种方式各有各的优缺点自己根据需求选择
一、通过自定义View的方式
自定View主要使用两个类来完成
/** * 基础方法、及动画时长控制类 */public abstract class BaseLoading extends LinearLayout{ private static final int DEFAULT_DURATION_TIME=300; private static final int MAX_DURATION_TIME=1000; private int duration; private Context context; public BaseLoading(Context context) { super(context); init(context,null); } public BaseLoading(Context context, AttributeSet attrs) { super(context, attrs); init(context,attrs); } public BaseLoading(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context,attrs); } private void init(Context context, AttributeSet attrs){ this.context=context; TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.BasicLoading); int duration = ta.getInt(R.styleable.BasicLoading_duration, DEFAULT_DURATION_TIME); setDuration(duration); ta.recycle(); } private void setDuration(int duration){ this.duration=duration; if(this.duration<0||this.duration>MAX_DURATION_TIME){ this.duration=DEFAULT_DURATION_TIME; } } public int getDuration(){ return this.duration; } public Context getViewContext(){ return this.context; } protected abstract void start(); protected abstract void stop(); protected abstract void handle(Message msg); protected Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { handle(msg); } };}
/** * 循环播放图片组自定义View */public class CycleLoading extends BaseLoading{ private Drawable startBg; private Drawable endBg; private ImageView switcher; private Drawable[] resources=null; private boolean isStarted=false; private boolean isExist=false; private int index=-1; private TaskThread thread; public CycleLoading(Context context) { super(context); init(context,null); } public CycleLoading(Context context, AttributeSet attrs) { super(context, attrs); init(context,attrs); } public CycleLoading(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context,attrs); } @Override public void start() { if(isStarted){ return; } isExist=false; switcher.setImageDrawable(startBg); if(this.resources==null){ throw new NullPointerException("resource array is null"); } thread=new TaskThread(); thread.start(); isStarted=true; } @Override public void stop() { isExist=true; if(thread!=null){ thread.interrupt(); thread=null; } } @Override protected void handle(Message msg) { if(!isExist){ switch (msg.what){ case 1: switcher.setImageDrawable(endBg); break; case 0: if(index==this.resources.length-1){ index=-1; } index++; switcher.setImageDrawable(resources[index]); break; } }else{ switcher.setImageDrawable(endBg); } } private void init(Context context, AttributeSet attrs){ TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.CycleLoading); startBg=ta.getDrawable(R.styleable.CycleLoading_startBg); endBg=ta.getDrawable(R.styleable.CycleLoading_endBg); initImageView(); ta.recycle(); } private void initImageView(){ switcher=new ImageView(getViewContext()); switcher.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)); switcher.setPadding(0,0,0,0); switcher.setImageDrawable(startBg); addView(switcher); } public void setStartDrawable(int resId){ Drawable start=getResources().getDrawable(resId); if(start==null){ throw new RuntimeException("not found resource for this resId"); } this.startBg=start; switcher.setImageDrawable(startBg); } public void setStartDrawable(Drawable drawable){ if(drawable==null){ throw new RuntimeException("not found resource for this drawable"); } this.startBg=drawable; switcher.setImageDrawable(startBg); } public Drawable getStartDrawable(){ return this.startBg; } public void setEndDrawable(int resId){ Drawable end=getResources().getDrawable(resId); if(end==null){ throw new RuntimeException("not found resource for this resId"); } this.endBg=end; } public void setEndDrawable(Drawable drawable){ if(drawable==null){ throw new RuntimeException("not found resource for this drawable"); } } public Drawable getEndDrawable(){ return this.endBg; } public void setDrawable(Drawable[] resources){ this.resources=resources; } public Drawable[] getDrawable(){ return this.resources; } class TaskThread extends Thread{ @Override public void run() { super.run(); while (!isExist){ try { Thread.sleep(getDuration()); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(0); } isStarted=false; handler.sendEmptyMessage(1); } }}
自定义属性
<!-- BasicLoading --> <declare-styleable name="BasicLoading"> <attr name="duration" format="integer" /> </declare-styleable> <!-- CycleLoading --> <declare-styleable name="CycleLoading"> <attr name="startBg" format="reference" /> <attr name="endBg" format="reference" /> </declare-styleable>
二、通过帧动画的方式
注意android studio中anim文件夹中不支持animation-list,需要把这个文件建在drawable下
<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:duration="300" android:drawable="@drawable/chatfrom_voice_playing_f1"/> <item android:duration="300" android:drawable="@drawable/chatfrom_voice_playing_f2"/> <item android:duration="300" android:drawable="@drawable/chatfrom_voice_playing_f3"/></animation-list>
三、具体使用
public class MainActivity extends AppCompatActivity { private LinearLayout audioReceive; private CycleLoading audioReceiveCycle; private LinearLayout audioSend; private CycleLoading audioSendCycle; private LinearLayout audioReceiveAnim; private ImageView audioReceiveAnimImg; private LinearLayout audioSendAnim; private ImageView audioSendAnimImg; private Drawable[] audioReceiveDrawable; private Drawable[] audioSendDrawable; private AnimationDrawable animationDrawableReceive; private AnimationDrawable animationDrawableSend; private boolean receiveIsStart=false; private boolean sendIsStart=false; private boolean receiveAnimIsStart=false; private boolean sendAnimIsStart=false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); initEvent(); } private void initView() { audioReceive = (LinearLayout) findViewById(R.id.audioReceive); audioReceiveCycle = (CycleLoading) findViewById(R.id.audioReceiveCycle); audioSend = (LinearLayout) findViewById(R.id.audioSend); audioSendCycle = (CycleLoading) findViewById(R.id.audioSendCycle); audioReceiveAnim= (LinearLayout) findViewById(R.id.audioReceiveAnim); audioReceiveAnimImg= (ImageView) findViewById(R.id.audioReceiveAnimImg); audioSendAnim= (LinearLayout) findViewById(R.id.audioSendAnim); audioSendAnimImg= (ImageView) findViewById(R.id.audioSendAnimImg); } private void initData() { //初始化资源 audioReceiveDrawable=new Drawable[]{getResources().getDrawable(R.drawable.chatfrom_voice_playing_f1), getResources().getDrawable(R.drawable.chatfrom_voice_playing_f2),getResources(). getDrawable(R.drawable.chatfrom_voice_playing_f3)}; audioSendDrawable=new Drawable[]{getResources().getDrawable(R.drawable.chatto_voice_playing_f1), getResources().getDrawable(R.drawable.chatto_voice_playing_f2), getResources().getDrawable(R.drawable.chatto_voice_playing_f3)}; //初始化动画 animationDrawableReceive= (AnimationDrawable) audioReceiveAnimImg.getDrawable(); animationDrawableSend= (AnimationDrawable) audioSendAnimImg.getDrawable(); } private void initEvent() { //自定义View接收 audioReceive.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(!receiveIsStart){ audioReceiveCycle.setDrawable(audioReceiveDrawable); audioReceiveCycle.start(); receiveIsStart=true; }else{ audioReceiveCycle.stop(); receiveIsStart=false; } } }); //自定义View发送 audioSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(!sendIsStart){ audioSendCycle.setDrawable(audioSendDrawable); audioSendCycle.start(); sendIsStart=true; }else{ audioSendCycle.stop(); sendIsStart=false; } } }); //帧动画接收 audioReceiveAnim.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(!receiveAnimIsStart){ animationDrawableReceive.start(); receiveAnimIsStart=true; }else{ animationDrawableReceive.stop(); receiveAnimIsStart=false; } } }); //帧动画发送 audioSendAnim.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(!sendAnimIsStart){ animationDrawableSend.start(); sendAnimIsStart=true; }else{ animationDrawableSend.stop(); sendAnimIsStart=false; } } }); }}
源码下载:
源码AudioChatView
1 0
- 实现语音聊天播放自定义View
- Unity5.x实现简易语音聊天(二) 录音与播放
- 语音聊天实现(Delphi)
- 实现语音聊天
- C++实现语音聊天
- IOS语音聊天实现
- android 语音聊天播放动画的问题
- Iphone实现播放语音
- Iphone实现播放语音
- 关于语音聊天(wave系列函数播放文件、网络音频)的实现方法
- Android自定义View 闹钟唤起播放闹钟铃声实现
- Android自定义view,实现多画面播放器
- 实现语音播放的API
- 04环信聊天界面 - 播放语音消息
- Android播放聊天语音消息帧动画问题
- 语音聊天程序实现(INDY, ACM, DELPHI)
- iPhone蓝牙编程之实现语音聊天
- iPhone蓝牙编程之实现语音聊天 .
- javaScript实现计时器
- HBase设计与开发性能优化
- Swift 字符串拼接
- SecureCRT显示中文
- 特大好消息,免费申请一年期正版Parallesl Desktop 12激活密钥
- 实现语音聊天播放自定义View
- Android WebView的使用笔记(上)
- Cache总容量计算与写回法联合使用
- Java时间判断:判断一个时间是否在一个时间段内
- PBOCEMV交易流程详解-POS与卡片的数据交互进行分析
- 设计模式--Builder模式
- Ubuntu 16.04安装Hadoop及Spark
- wempserver apache启动不了,图标显示为黄色
- ubuntu下Qt安装qwt出现的问题