欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义View实现微信语音界面

程序员文章站 2023-10-31 09:17:10
前言 因为最近的项目需要使用录音功能,开始的想法是button+ontouchlistener+dialog实现,在大部分手机中都没问题,只有mi8会偶尔无法触发motioneven...

前言

因为最近的项目需要使用录音功能,开始的想法是button+ontouchlistener+dialog实现,在大部分手机中都没问题,只有mi8会偶尔无法触发motionevent.action_up,导致程序异常。所以就自己写了个自定义view来实现,主要也是通过监听
ontouchlistener+dialog来实现。这里只实现了自定义view,并不涉及录音和播放。效果图如下:

Android自定义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地址:仿微信语音界面

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。