Android自定义View实现微信语音界面
程序员文章站
2023-12-27 13:30:27
前言
因为最近的项目需要使用录音功能,开始的想法是button+ontouchlistener+dialog实现,在大部分手机中都没问题,只有mi8会偶尔无法触发motioneven...
前言
因为最近的项目需要使用录音功能,开始的想法是button+ontouchlistener+dialog实现,在大部分手机中都没问题,只有mi8会偶尔无法触发motionevent.action_up,导致程序异常。所以就自己写了个自定义view来实现,主要也是通过监听
ontouchlistener+dialog来实现。这里只实现了自定义view,并不涉及录音和播放。效果图如下:
代码
代码并不复杂,配合注释应该很容易理解。
/** * author : blackhao * time : 2019/4/18 14:03 * description : 自定义录音按钮布局界面 */ public class pressedview extends view implements view.ontouchlistener { private int normalres; private string normaltext = ""; private int pressedres; private string pressedtext = ""; // private paint paint; private rect rect; //当前是否是按下状态 private boolean ispressed = false; // private presscallback callback; //按下的位置y坐标 private int pressedy = 0; //当前是否是outsize private boolean isoutsize = false; //字体dp大小 private static int text_size = 20; //对话框相关 private dialog soundvolumedialog = null; //音量图片 private imageview soundvolumeimg = null; //对话框背景 private relativelayout soundvolumelayout = null; public pressedview(context context) { super(context); init(); } public pressedview(context context, @nullable attributeset attrs) { super(context, attrs); init(); } public pressedview(context context, @nullable attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); init(); } private void init() { // paint = new paint(); paint.setantialias(true); paint.settextsize(densityutil.dip2px(getcontext(), text_size)); paint.setcolor(color.white); rect = new rect(); // normalres = r.drawable.blue_btn_bk; normaltext = "按住 说话"; pressedres = r.drawable.red_btn_bk; pressedtext = "松开 结束"; // setontouchlistener(this); // initsoundvolumedlg(); } @override protected void ondraw(canvas canvas) { super.ondraw(canvas); rect.set(0, 0, getwidth(), getheight()); if (!ispressed) { setbackgroundresource(normalres); drawtextonrect(canvas, rect, normaltext); } else { setbackgroundresource(pressedres); drawtextonrect(canvas, rect, pressedtext); } } @override public boolean ontouch(view v, motionevent event) { switch (event.getaction()) { case motionevent.action_down: pressedy = (int) event.getrawy(); isoutsize = false; if (!ispressed) { ispressed = true; postinvalidate(); if (callback != null) { //回调 callback.onstartrecord(); //按下,弹出对话框 soundvolumeimg.setimageresource(r.mipmap.sound_volume_01); soundvolumeimg.setvisibility(view.visible); soundvolumelayout.setbackgroundresource(r.mipmap.sound_volume_default_bk); soundvolumedialog.show(); } } break; case motionevent.action_up: if (ispressed) { ispressed = false; postinvalidate(); if (callback != null) { int upy = (int) event.getrawy(); if (pressedy - upy < getheight()) { //录音结束 if (soundvolumedialog.isshowing()) { soundvolumedialog.dismiss(); } callback.onstoprecord(); } else { //录音取消 if (soundvolumedialog.isshowing()) { soundvolumedialog.dismiss(); } callback.oncancelrecord(); } } } break; case motionevent.action_move: if (ispressed && callback != null) { int upy = (int) event.getrawy(); if (pressedy - upy < getheight()) { if (isoutsize) { isoutsize = false; soundvolumelayout.setbackgroundresource(r.mipmap.sound_volume_default_bk); } } else { if (!isoutsize) { isoutsize = true; soundvolumelayout.setbackgroundresource(r.mipmap.sound_volume_cancel_bk); } } } break; } return true; } public void setcallback(presscallback callback) { this.callback = callback; } public interface presscallback { //开始录音 void onstartrecord(); //停止录音 void onstoprecord(); //取消录音 void oncancelrecord(); } /** * 在指定矩形中间drawtext * * @param canvas 画布 * @param targetrect 指定矩形 * @param text 需要绘制的text */ private void drawtextonrect(canvas canvas, rect targetrect, string text) { paint.fontmetricsint fontmetrics = paint.getfontmetricsint(); // 获取baseline int baseline = targetrect.top + (targetrect.bottom - targetrect.top - fontmetrics.bottom + fontmetrics.top) / 2 - fontmetrics.top; // 下面这行是实现水平居中,drawtext对应改为传入targetrect.centerx() paint.settextalign(paint.align.center); canvas.drawtext(text, targetrect.centerx(), baseline, paint); } /** * 初始化音量信息对话框 */ private void initsoundvolumedlg() { soundvolumedialog = new dialog(getcontext(), r.style.soundvolumestyle); soundvolumedialog.requestwindowfeature(window.feature_no_title); soundvolumedialog.getwindow().setflags(windowmanager.layoutparams.flag_fullscreen, windowmanager.layoutparams.flag_fullscreen); soundvolumedialog.setcontentview(r.layout.tt_sound_volume_dialog); soundvolumedialog.setcanceledontouchoutside(true); soundvolumeimg = (imageview) soundvolumedialog.findviewbyid(r.id.sound_volume_img); soundvolumelayout = (relativelayout) soundvolumedialog.findviewbyid(r.id.sound_volume_bk); } /** * 根据分贝值设置录音时的音量动画 */ public void setvolume(int voicevalue) { if (voicevalue < 200.0) { soundvolumeimg.setimageresource(r.mipmap.sound_volume_01); } else if (voicevalue > 200.0 && voicevalue < 600) { soundvolumeimg.setimageresource(r.mipmap.sound_volume_02); } else if (voicevalue > 600.0 && voicevalue < 1200) { soundvolumeimg.setimageresource(r.mipmap.sound_volume_03); } else if (voicevalue > 1200.0 && voicevalue < 2400) { soundvolumeimg.setimageresource(r.mipmap.sound_volume_04); } else if (voicevalue > 2400.0 && voicevalue < 10000) { soundvolumeimg.setimageresource(r.mipmap.sound_volume_05); } else if (voicevalue > 10000.0 && voicevalue < 28000.0) { soundvolumeimg.setimageresource(r.mipmap.sound_volume_06); } else if (voicevalue > 28000.0) { soundvolumeimg.setimageresource(r.mipmap.sound_volume_07); } } }
结语
源码github地址:仿微信语音界面
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。