android仿微信聊天界面 语音录制功能

本例为模仿微信聊天界面UI设计,文字发送以及语言录制UI。

1先看效果图:

第一:chat.xml设计

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:background="@drawable/chat_bg_default" > 

  <!-- 标题栏 -->
  <RelativeLayout
    android:id="@+id/rl_layout"
    android:layout_width="fill_parent"
    android:layout_height="45dp"
    android:background="@drawable/title_bar"
    android:gravity="center_vertical" > 

    <Button
      android:id="@+id/btn_back"
      android:layout_width="70dp"
      android:layout_height="wrap_content"
      android:layout_centerVertical="true"
      android:background="@drawable/title_btn_back"
      android:onClick="chat_back"
      android:text="返回"
      android:textColor="#fff"
      android:textSize="14sp" /> 

    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:text="白富美"
      android:textColor="#ffffff"
      android:textSize="20sp" /> 

    <ImageButton
      android:id="@+id/right_btn"
      android:layout_width="67dp"
      android:layout_height="wrap_content"
      android:layout_alignParentRight="true"
      android:layout_centerVertical="true"
      android:layout_marginRight="5dp"
      android:background="@drawable/title_btn_right"
      android:src="@drawable/mm_title_btn_contact_normal" />
  </RelativeLayout> 

  <!-- 底部按钮以及 编辑框 -->
  <RelativeLayout
    android:id="@+id/rl_bottom"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="@drawable/chat_footer_bg" > 

    <ImageView
      android:id="@+id/ivPopUp"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentLeft="true"
      android:layout_centerVertical="true"
      android:layout_marginLeft="10dip"
      android:src="@drawable/chatting_setmode_msg_btn" /> 

    <RelativeLayout
      android:id="@+id/btn_bottom"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_alignParentRight="true"
      android:layout_centerVertical="true"
      android:layout_toRightOf="@+id/ivPopUp" > 

      <Button
        android:id="@+id/btn_send"
        android:layout_width="60dp"
        android:layout_height="40dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dp"
        android:background="@drawable/chat_send_btn"
        android:text="发送" /> 

      <EditText
        android:id="@+id/et_sendmessage"
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_toLeftOf="@id/btn_send"
        android:background="@drawable/login_edit_normal"
        android:singleLine="true"
        android:textSize="18sp" />
    </RelativeLayout> 

    <TextView
      android:id="@+id/btn_rcd"
      android:layout_width="fill_parent"
      android:layout_height="40dp"
      android:layout_alignParentRight="true"
      android:layout_centerVertical="true"
      android:layout_marginLeft="10dp"
      android:layout_marginRight="10dp"
      android:layout_toRightOf="@+id/ivPopUp"
      android:background="@drawable/chat_send_btn"
      android:gravity="center"
      android:text="按住说话"
      android:visibility="gone" />
  </RelativeLayout> 

  <!-- 聊天内容 listview -->
  <ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@id/rl_bottom"
    android:layout_below="@id/rl_layout"
    android:cacheColorHint="#0000"
    android:divider="@null"
    android:dividerHeight="5dp"
    android:scrollbarStyle="outsideOverlay"
    android:stackFromBottom="true" /> 

  <!-- 录音显示UI层 -->
  <LinearLayout
    android:id="@+id/rcChat_popup"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:visibility="gone" > 

    <include
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      layout="@layout/voice_rcd_hint_window" />
  </LinearLayout> 

</RelativeLayout>

第二:语音录制类封装SoundMeter.java

package com.example.voice_rcd; 

import java.io.IOException; 

import android.media.MediaRecorder;
import android.os.Environment; 

public class SoundMeter {
  static final private double EMA_FILTER = 0.6; 

  private MediaRecorder mRecorder = null;
  private double mEMA = 0.0; 

  public void start(String name) {
    if (!Environment.getExternalStorageState().equals(
        android.os.Environment.MEDIA_MOUNTED)) {
      return;
    }
    if (mRecorder == null) {
      mRecorder = new MediaRecorder();
      mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
      mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
      mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
      mRecorder.setOutputFile(android.os.Environment.getExternalStorageDirectory()+"/"+name);
      try {
        mRecorder.prepare();
        mRecorder.start(); 

        mEMA = 0.0;
      } catch (IllegalStateException e) {
        System.out.print(e.getMessage());
      } catch (IOException e) {
        System.out.print(e.getMessage());
      } 

    }
  } 

  public void stop() {
    if (mRecorder != null) {
      mRecorder.stop();
      mRecorder.release();
      mRecorder = null;
    }
  } 

  public void pause() {
    if (mRecorder != null) {
      mRecorder.stop();
    }
  } 

  public void start() {
    if (mRecorder != null) {
      mRecorder.start();
    }
  } 

  public double getAmplitude() {
    if (mRecorder != null)
      return (mRecorder.getMaxAmplitude() / 2700.0);
    else
      return 0; 

  } 

  public double getAmplitudeEMA() {
    double amp = getAmplitude();
    mEMA = EMA_FILTER * amp + (1.0 - EMA_FILTER) * mEMA;
    return mEMA;
  }
} 

 

第三:主界面Activity源码,没写太多解释,相对比较简单的自己研究下:

package com.example.voice_rcd; 

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; 

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; 

public class MainActivity extends Activity implements OnClickListener {
  /** Called when the activity is first created. */ 

  private Button mBtnSend;
  private TextView mBtnRcd;
  private Button mBtnBack;
  private EditText mEditTextContent;
  private RelativeLayout mBottom;
  private ListView mListView;
  private ChatMsgViewAdapter mAdapter;
  private List<ChatMsgEntity> mDataArrays = new ArrayList<ChatMsgEntity>();
  private boolean isShosrt = false;
  private LinearLayout voice_rcd_hint_loading, voice_rcd_hint_rcding,
      voice_rcd_hint_tooshort;
  private ImageView img1, sc_img1;
  private SoundMeter mSensor;
  private View rcChat_popup;
  private LinearLayout del_re;
  private ImageView chatting_mode_btn, volume;
  private boolean btn_vocie = false;
  private int flag = 1;
  private Handler mHandler = new Handler();
  private String voiceName;
  private long startVoiceT, endVoiceT; 

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.chat);
    // 启动activity时不自动弹出软键盘
    getWindow().setSoftInputMode(
        WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    initView(); 

    initData();
  } 

  public void initView() {
    mListView = (ListView) findViewById(R.id.listview);
    mBtnSend = (Button) findViewById(R.id.btn_send);
    mBtnRcd = (TextView) findViewById(R.id.btn_rcd);
    mBtnSend.setOnClickListener(this);
    mBtnBack = (Button) findViewById(R.id.btn_back);
    mBottom = (RelativeLayout) findViewById(R.id.btn_bottom);
    mBtnBack.setOnClickListener(this);
    chatting_mode_btn = (ImageView) this.findViewById(R.id.ivPopUp);
    volume = (ImageView) this.findViewById(R.id.volume);
    rcChat_popup = this.findViewById(R.id.rcChat_popup);
    img1 = (ImageView) this.findViewById(R.id.img1);
    sc_img1 = (ImageView) this.findViewById(R.id.sc_img1);
    del_re = (LinearLayout) this.findViewById(R.id.del_re);
    voice_rcd_hint_rcding = (LinearLayout) this
        .findViewById(R.id.voice_rcd_hint_rcding);
    voice_rcd_hint_loading = (LinearLayout) this
        .findViewById(R.id.voice_rcd_hint_loading);
    voice_rcd_hint_tooshort = (LinearLayout) this
        .findViewById(R.id.voice_rcd_hint_tooshort);
    mSensor = new SoundMeter();
    mEditTextContent = (EditText) findViewById(R.id.et_sendmessage); 

    //语音文字切换按钮
    chatting_mode_btn.setOnClickListener(new OnClickListener() { 

      public void onClick(View v) { 

        if (btn_vocie) {
          mBtnRcd.setVisibility(View.GONE);
          mBottom.setVisibility(View.VISIBLE);
          btn_vocie = false;
          chatting_mode_btn
              .setImageResource(R.drawable.chatting_setmode_msg_btn); 

        } else {
          mBtnRcd.setVisibility(View.VISIBLE);
          mBottom.setVisibility(View.GONE);
          chatting_mode_btn
              .setImageResource(R.drawable.chatting_setmode_voice_btn);
          btn_vocie = true;
        }
      }
    });
    mBtnRcd.setOnTouchListener(new OnTouchListener() { 

      public boolean onTouch(View v, MotionEvent event) {
        //按下语音录制按钮时返回false执行父类OnTouch
        return false;
      }
    });
  } 

  private String[] msgArray = new String[] { "有人就有恩怨","有恩怨就有江湖","人就是江湖","你怎么退出? ","生命中充满了巧合","两条平行线也会有相交的一天。"}; 

  private String[] dataArray = new String[] { "2012-10-31 18:00",
      "2012-10-31 18:10", "2012-10-31 18:11", "2012-10-31 18:20",
      "2012-10-31 18:30", "2012-10-31 18:35"};
  private final static int COUNT = 6; 

  public void initData() {
    for (int i = 0; i < COUNT; i++) {
      ChatMsgEntity entity = new ChatMsgEntity();
      entity.setDate(dataArray[i]);
      if (i % 2 == 0) {
        entity.setName("白富美");
        entity.setMsgType(true);
      } else {
        entity.setName("高富帅");
        entity.setMsgType(false);
      } 

      entity.setText(msgArray[i]);
      mDataArrays.add(entity);
    } 

    mAdapter = new ChatMsgViewAdapter(this, mDataArrays);
    mListView.setAdapter(mAdapter); 

  } 

  public void onClick(View v) {
    // TODO Auto-generated method stub
    switch (v.getId()) {
    case R.id.btn_send:
      send();
      break;
    case R.id.btn_back:
      finish();
      break;
    }
  } 

  private void send() {
    String contString = mEditTextContent.getText().toString();
    if (contString.length() > 0) {
      ChatMsgEntity entity = new ChatMsgEntity();
      entity.setDate(getDate());
      entity.setName("高富帅");
      entity.setMsgType(false);
      entity.setText(contString); 

      mDataArrays.add(entity);
      mAdapter.notifyDataSetChanged(); 

      mEditTextContent.setText(""); 

      mListView.setSelection(mListView.getCount() - 1);
    }
  } 

  private String getDate() {
    Calendar c = Calendar.getInstance(); 

    String year = String.valueOf(c.get(Calendar.YEAR));
    String month = String.valueOf(c.get(Calendar.MONTH));
    String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH) + 1);
    String hour = String.valueOf(c.get(Calendar.HOUR_OF_DAY));
    String mins = String.valueOf(c.get(Calendar.MINUTE)); 

    StringBuffer sbBuffer = new StringBuffer();
    sbBuffer.append(year + "-" + month + "-" + day + " " + hour + ":"
        + mins); 

    return sbBuffer.toString();
  } 

  //按下语音录制按钮时
  @Override
  public boolean onTouchEvent(MotionEvent event) { 

    if (!Environment.getExternalStorageDirectory().exists()) {
      Toast.makeText(this, "No SDCard", Toast.LENGTH_LONG).show();
      return false;
    } 

    if (btn_vocie) {
      System.out.println("1");
      int[] location = new int[2];
      mBtnRcd.getLocationInWindow(location); // 获取在当前窗口内的绝对坐标
      int btn_rc_Y = location[1];
      int btn_rc_X = location[0];
      int[] del_location = new int[2];
      del_re.getLocationInWindow(del_location);
      int del_Y = del_location[1];
      int del_x = del_location[0];
      if (event.getAction() == MotionEvent.ACTION_DOWN && flag == 1) {
        if (!Environment.getExternalStorageDirectory().exists()) {
          Toast.makeText(this, "No SDCard", Toast.LENGTH_LONG).show();
          return false;
        }
        System.out.println("2");
        if (event.getY() > btn_rc_Y && event.getX() > btn_rc_X) {//判断手势按下的位置是否是语音录制按钮的范围内
          System.out.println("3");
          mBtnRcd.setBackgroundResource(R.drawable.voice_rcd_btn_pressed);
          rcChat_popup.setVisibility(View.VISIBLE);
          voice_rcd_hint_loading.setVisibility(View.VISIBLE);
          voice_rcd_hint_rcding.setVisibility(View.GONE);
          voice_rcd_hint_tooshort.setVisibility(View.GONE);
          mHandler.postDelayed(new Runnable() {
            public void run() {
              if (!isShosrt) {
                voice_rcd_hint_loading.setVisibility(View.GONE);
                voice_rcd_hint_rcding
                    .setVisibility(View.VISIBLE);
              }
            }
          }, 300);
          img1.setVisibility(View.VISIBLE);
          del_re.setVisibility(View.GONE);
          startVoiceT = SystemClock.currentThreadTimeMillis();
          voiceName = startVoiceT + ".amr";
          start(voiceName);
          flag = 2;
        }
      } else if (event.getAction() == MotionEvent.ACTION_UP && flag == 2) {//松开手势时执行录制完成
        System.out.println("4");
        mBtnRcd.setBackgroundResource(R.drawable.voice_rcd_btn_nor);
        if (event.getY() >= del_Y
            && event.getY() <= del_Y + del_re.getHeight()
            && event.getX() >= del_x
            && event.getX() <= del_x + del_re.getWidth()) {
          rcChat_popup.setVisibility(View.GONE);
          img1.setVisibility(View.VISIBLE);
          del_re.setVisibility(View.GONE);
          stop();
          flag = 1;
          File file = new File(android.os.Environment.getExternalStorageDirectory()+"/"
                  + voiceName);
          if (file.exists()) {
            file.delete();
          }
        } else { 

          voice_rcd_hint_rcding.setVisibility(View.GONE);
          stop();
          endVoiceT = SystemClock.currentThreadTimeMillis();
          flag = 1;
          int time = (int) ((endVoiceT - startVoiceT) / 1000);
          if (time < 1) {
            isShosrt = true;
            voice_rcd_hint_loading.setVisibility(View.GONE);
            voice_rcd_hint_rcding.setVisibility(View.GONE);
            voice_rcd_hint_tooshort.setVisibility(View.VISIBLE);
            mHandler.postDelayed(new Runnable() {
              public void run() {
                voice_rcd_hint_tooshort
                    .setVisibility(View.GONE);
                rcChat_popup.setVisibility(View.GONE);
                isShosrt = false;
              }
            }, 500);
            return false;
          }
          ChatMsgEntity entity = new ChatMsgEntity();
          entity.setDate(getDate());
          entity.setName("高富帅");
          entity.setMsgType(false);
          entity.setTime(time+"\"");
          entity.setText(voiceName);
          mDataArrays.add(entity);
          mAdapter.notifyDataSetChanged();
          mListView.setSelection(mListView.getCount() - 1);
          rcChat_popup.setVisibility(View.GONE); 

        }
      }
      if (event.getY() < btn_rc_Y) {//手势按下的位置不在语音录制按钮的范围内
        System.out.println("5");
        Animation mLitteAnimation = AnimationUtils.loadAnimation(this,
            R.anim.cancel_rc);
        Animation mBigAnimation = AnimationUtils.loadAnimation(this,
            R.anim.cancel_rc2);
        img1.setVisibility(View.GONE);
        del_re.setVisibility(View.VISIBLE);
        del_re.setBackgroundResource(R.drawable.voice_rcd_cancel_bg);
        if (event.getY() >= del_Y
            && event.getY() <= del_Y + del_re.getHeight()
            && event.getX() >= del_x
            && event.getX() <= del_x + del_re.getWidth()) {
          del_re.setBackgroundResource(R.drawable.voice_rcd_cancel_bg_focused);
          sc_img1.startAnimation(mLitteAnimation);
          sc_img1.startAnimation(mBigAnimation);
        }
      } else { 

        img1.setVisibility(View.VISIBLE);
        del_re.setVisibility(View.GONE);
        del_re.setBackgroundResource(0);
      }
    }
    return super.onTouchEvent(event);
  } 

  private static final int POLL_INTERVAL = 300; 

  private Runnable mSleepTask = new Runnable() {
    public void run() {
      stop();
    }
  };
  private Runnable mPollTask = new Runnable() {
    public void run() {
      double amp = mSensor.getAmplitude();
      updateDisplay(amp);
      mHandler.postDelayed(mPollTask, POLL_INTERVAL); 

    }
  }; 

  private void start(String name) {
    mSensor.start(name);
    mHandler.postDelayed(mPollTask, POLL_INTERVAL);
  } 

  private void stop() {
    mHandler.removeCallbacks(mSleepTask);
    mHandler.removeCallbacks(mPollTask);
    mSensor.stop();
    volume.setImageResource(R.drawable.amp1);
  } 

  private void updateDisplay(double signalEMA) { 

    switch ((int) signalEMA) {
    case 0:
    case 1:
      volume.setImageResource(R.drawable.amp1);
      break;
    case 2:
    case 3:
      volume.setImageResource(R.drawable.amp2); 

      break;
    case 4:
    case 5:
      volume.setImageResource(R.drawable.amp3);
      break;
    case 6:
    case 7:
      volume.setImageResource(R.drawable.amp4);
      break;
    case 8:
    case 9:
      volume.setImageResource(R.drawable.amp5);
      break;
    case 10:
    case 11:
      volume.setImageResource(R.drawable.amp6);
      break;
    default:
      volume.setImageResource(R.drawable.amp7);
      break;
    }
  } 

  public void head_xiaohei(View v) { // 标题栏 返回按钮 

  }
}

第四:自定义的显示适配器:

package com.example.voice_rcd; 

import java.util.List; 

import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; 

public class ChatMsgViewAdapter extends BaseAdapter { 

  public static interface IMsgViewType {
    int IMVT_COM_MSG = 0;
    int IMVT_TO_MSG = 1;
  } 

  private static final String TAG = ChatMsgViewAdapter.class.getSimpleName(); 

  private List<ChatMsgEntity> coll; 

  private Context ctx; 

  private LayoutInflater mInflater;
  private MediaPlayer mMediaPlayer = new MediaPlayer(); 

  public ChatMsgViewAdapter(Context context, List<ChatMsgEntity> coll) {
    ctx = context;
    this.coll = coll;
    mInflater = LayoutInflater.from(context);
  } 

  public int getCount() {
    return coll.size();
  } 

  public Object getItem(int position) {
    return coll.get(position);
  } 

  public long getItemId(int position) {
    return position;
  } 

  public int getItemViewType(int position) {
    // TODO Auto-generated method stub
    ChatMsgEntity entity = coll.get(position); 

    if (entity.getMsgType()) {
      return IMsgViewType.IMVT_COM_MSG;
    } else {
      return IMsgViewType.IMVT_TO_MSG;
    } 

  } 

  public int getViewTypeCount() {
    // TODO Auto-generated method stub
    return 2;
  } 

  public View getView(int position, View convertView, ViewGroup parent) { 

    final ChatMsgEntity entity = coll.get(position);
    boolean isComMsg = entity.getMsgType(); 

    ViewHolder viewHolder = null;
    if (convertView == null) {
      if (isComMsg) {
        convertView = mInflater.inflate(
            R.layout.chatting_item_msg_text_left, null);
      } else {
        convertView = mInflater.inflate(
            R.layout.chatting_item_msg_text_right, null);
      } 

      viewHolder = new ViewHolder();
      viewHolder.tvSendTime = (TextView) convertView
          .findViewById(R.id.tv_sendtime);
      viewHolder.tvUserName = (TextView) convertView
          .findViewById(R.id.tv_username);
      viewHolder.tvContent = (TextView) convertView
          .findViewById(R.id.tv_chatcontent);
      viewHolder.tvTime = (TextView) convertView
          .findViewById(R.id.tv_time);
      viewHolder.isComMsg = isComMsg; 

      convertView.setTag(viewHolder);
    } else {
      viewHolder = (ViewHolder) convertView.getTag();
    } 

    viewHolder.tvSendTime.setText(entity.getDate()); 

    if (entity.getText().contains(".amr")) {
      viewHolder.tvContent.setText("");
      viewHolder.tvContent.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.chatto_voice_playing, 0);
      viewHolder.tvTime.setText(entity.getTime());
    } else {
      viewHolder.tvContent.setText(entity.getText());
      viewHolder.tvContent.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
      viewHolder.tvTime.setText("");
    }
    viewHolder.tvContent.setOnClickListener(new OnClickListener() { 

      public void onClick(View v) {
        if (entity.getText().contains(".amr")) {
          playMusic(android.os.Environment.getExternalStorageDirectory()+"/"+entity.getText()) ;
        }
      }
    });
    viewHolder.tvUserName.setText(entity.getName()); 

    return convertView;
  } 

  static class ViewHolder {
    public TextView tvSendTime;
    public TextView tvUserName;
    public TextView tvContent;
    public TextView tvTime;
    public boolean isComMsg = true;
  } 

  /**
   * @Description
   * @param name
   */
  private void playMusic(String name) {
    try {
      if (mMediaPlayer.isPlaying()) {
        mMediaPlayer.stop();
      }
      mMediaPlayer.reset();
      mMediaPlayer.setDataSource(name);
      mMediaPlayer.prepare();
      mMediaPlayer.start();
      mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
        public void onCompletion(MediaPlayer mp) { 

        }
      }); 

    } catch (Exception e) {
      e.printStackTrace();
    } 

  } 

  private void stop() { 

  } 

}

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

时间: 2016-11-14

Android仿微信语音消息的录制和播放功能

一.简述 效果: 实现功能: 长按Button时改变Button显示文字,弹出Dialog(动态更新音量),动态生成录音文件,开始录音: 监听手指动作,规定区域.录音状态下手指划出规定区域取消录音,删除生成的录音文件: 监听手指动作.当手指抬起时,判断是否开始录音,录音时长是否过短,符合条件则提示录音时长过短:正常结束时通过回调返回该次录音的文件路径和时长. 4.点击录音列表的item时,播放动画,播放对应的音频文件. 主要用到4个核心类: 自定义录音按钮(AudioRecordButton):

Android仿微信语音聊天功能

本文实例讲述了Android仿微信语音聊天功能代码.分享给大家供大家参考.具体如下: 项目效果如下: 具体代码如下: AudioManager.java package com.xuliugen.weichat; import java.io.File; import java.io.IOException; import java.util.UUID; import android.media.MediaRecorder; public class AudioManager { private

Android仿微信发送语音消息的功能及示例代码

微信的发送语音是有一个向上取消的,我们使用onTouchListener来监听手势,然后做出相应的操作就行了. 直接上代码: //语音操作对象 private MediaPlayer mPlayer = null; private MediaRecorder mRecorder = null; //语音文件保存路径 private String FileName = null; FileName = Environment.getExternalStorageDirectory().getAbs

Android仿微信语音聊天界面设计

有段时间没有看视频了,昨天晚上抽了点空时间,又看了下鸿洋大神的视频教程,又抽时间写了个学习记录.代码和老师讲的基本一样,网上也有很多相同的博客.我只是在AndroidStudio环境下写的. --主界面代码-- public class MainActivity extends Activity { private ListView mListView; private ArrayAdapter<Recorder> mAdapter; private List<Recorder>

Android 高仿微信语音聊天页面高斯模糊(毛玻璃效果)

目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高斯模糊,并把它作为整个页面的背景色. 关于Android如何快速实现高斯模糊(毛玻璃效果),网上一堆相关介绍,可参考下面文章一种快速毛玻璃虚化效果实现–Android. 下面直接给出模糊化工具类(已验证可行): import android.graphics.Bitmap; /** * 快速模糊化工

Android自定义UI实现微信语音

本文实例为大家分享了java获取不同路径的方法,供大家参考,具体内容如下 思路: 自定义Button 获取DialogManager.AudioManager setOnLongClickListener长按事件--做好AudioManager的录音准备工作 AudioManager.setOnAudioStateListener(this)实现录音准备完毕的接口回调方法,方法中去发送MSG_AUDIO_PREPARE消息代表录音准备工作完毕 在mHandler中接收消息,开始开启线程录音,并且

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

前言 因为最近的项目需要使用录音功能,开始的想法是Button+OnTouchListener+Dialog实现,在大部分手机中都没问题,只有MI8会偶尔无法触发MotionEvent.ACTION_UP,导致程序异常.所以就自己写了个自定义View来实现,主要也是通过监听 OnTouchListener+Dialog来实现.这里只实现了自定义View,并不涉及录音和播放.效果图如下: 代码 代码并不复杂,配合注释应该很容易理解. /** * Author : BlackHao * Time :

Android自定义UI手势密码改进版源码下载

在之前文章的铺垫下,再为大家分享一篇:Android手势密码,附源码下载,不要错过. 源码下载:http://xiazai.jb51.net/201610/yuanma/androidLock(jb51.net).rar 先看第一张图片的布局文件 activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://sc

Android自定义TextView仿微信朋友圈文字展开全文功能

Android自定义TextView仿微信朋友圈文字信息,展开全文功能 代码及注释如下: 首先写一个xml文件 showmore.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical

Android 自定义view仿微信相机单击拍照长按录视频按钮

Android仿微信相机的拍照按钮单击拍照,长按录视频.先上效果图. 项目地址:https://github.com/c786909486/PhotoButton2/tree/v1.0 添加依赖 allprojects { repositories { ... maven { url 'https://jitpack.io' } } } dependencies { compile compile 'com.github.c786909486:PhotoButton2:v1.1' } 长按效果分

Android自定义UI之粒子效果

本文实例为大家分享了Android自定义UI之粒子效果的具体代码,供大家参考,具体内容如下 1.爆炸实体类 public class Ball { public int color;//颜色 public float x;//圆心x坐标 public float y;//圆心y坐标 public float r;//粒子半径 public float vX;//粒子水平方向速度 public float vY;//粒子y方向速度 public float aX;//粒子水平方向加速度 publi

android自定义popupwindow仿微信右上角弹出菜单效果

微信右上角的操作菜单看起来很好用,就照着仿了一下,不过是旧版微信的,手里刚好有一些旧版微信的资源图标,给大家分享一下. 不知道微信是用什么实现的,我使用popupwindow来实现,主要分为几块内容: 1.窗口布局文件:popwin_share.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com

Android自定义UI手势密码改进版

接着第一个Android UI手势密码设计的基础上继续改进,效果图如下 activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layo

Android自定义View实现微信支付密码输入框

本文实例为大家分享了Android实现微信支付密码输入框的具体代码,供大家参考,具体内容如下 效果图 项目中使用到了支付密码功能,其实这类界面是比较常用的,涉及支付密码的输入的一般都会用到对的,所以单独地把这部分抽取出来,有需要的朋友可以拿去用哈! 效果就是支付,弹出密码框,输入密码,这个过程密码不可见,并且提供一个输入完毕的监听! 这个弹出层呢,其实就是一个DialogFragment,逻辑封装在其内部 一.弹出层进出动画 (anim文件) push_bottom_in.xml <?xml v

Android自定义view仿微信刷新旋转小风车

本文实例为大家分享了Android仿微信刷新旋转小风车 具体代码,供大家参考,具体内容如下 不太会录像,没办法,智能截图了 不多说了,直接上代码 package com.shipneg.demoysp.demo; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.