1. 程式人生 > 程式設計 >Android自定義View實現微信語音介面

Android自定義View實現微信語音介面

前言

因為最近的專案需要使用錄音功能,開始的想法是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,getWidth(),getHeight());
    if (!isPressed) {
      setBackgroundResource(normalRes);
      drawTextOnRect(canvas,rect,normalText);
    } else {
      setBackgroundResource(pressedRes);
      drawTextOnRect(canvas,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地址:仿微信語音介面

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。