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() { 

  } 

}

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

(0)

相关推荐

  • Android自定义UI实现微信语音

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

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

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

  • 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仿微信语音消息的录制和播放功能

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

  • 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" andro

  • Android仿微信主界面的实现方法

    本文实例为大家分享了Android模仿微信主界面展示的具体代码,供大家参考,具体内容如下 先看一下效果图 实现的原理: ViewPager+FragmentPagerAdapter 主界面可分为三部分: top标题栏就是一个TextView 中间的ViewPager作为显示的容器,填充Fragment bottom是一个RadioGroup 这里为了布局的优化,将top和bottom抽取出来 ,然后用include将其导入主布局,如下 <LinearLayout xmlns:android=&quo

  • Android高仿微信聊天界面代码分享

    微信聊天现在非常火,是因其界面漂亮吗,哈哈,也许吧.微信每条消息都带有一个气泡,非常迷人,看起来感觉实现起来非常难,其实并不难.下面小编给大家分享实现代码. 先给大家展示下实现效果图: OK,下面我们来看一下整个小项目的主体结构: 下面是Activity的代码: package com.way.demo; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import jav

  • Android仿微信通讯录滑动快速定位功能

    先给大家展示下效果图: 实现代码如下: 下面简单说下实现原理. public class IndexBar extends LinearLayout implements View.OnTouchListener { private static final String[] INDEXES = new String[]{"#", "A", "B", "C", "D", "E", &qu

  • react+redux仿微信聊天界面

    一.项目概况 基于react+react-dom+react-router-dom+redux+react-redux+webpack2.0+react-photoswipe+swiper等技术混合开发的手机端仿微信界面聊天室--reactChatRoom,实现了聊天记录下拉刷新.发送消息.表情(动图),图片.视频预览,打赏.红包等功能. 二.技术栈MVVM框架: react / react-dom状态管理:redux / react-redux页面路由:react-router-dom弹窗插件

  • Android 仿微信聊天时间格式化显示功能

    本文给大家分享android仿微信聊天时间格式化显示功能. 在同一年的显示规则: 如果是当天显示格式为 HH:mm 例:14:45 如果是昨天,显示格式为 昨天 HH:mm 例:昨天 13:12 如果是在同一周 显示格式为 周一 HH:mm 例:周一14:05 如果不是同一周则显示格式为 M月d日 早上或者其它 HH:mm 例: 2月5日 早上10:10 不在同一年的显示规则: 显示格式为 yyyy年M月d日 晚上或者其它 HH:mm 例:2016年2月5日 晚上18:05 代码中如果有误,请留

  • 详解微信小程序实现仿微信聊天界面(各种细节处理)

    本文介绍了微信小程序实现仿微信聊天界面,分享给大家,具体如下: 下面先来看看效果 为实现这样的效果,首先要解决两个问题: 1.点击输入框弹出软键盘后,将已有的少许聊天内容弹出,导致看不到的问题: 2.键盘弹出或收起时,聊天消息没有自动滚到最底部. 首先解决第二个问题,自动滚动到最底部,这很简单,这里提供三种方法(推荐第三种): 1.计算每条消息的最大高度,设置scroll-top=(单条msg最大高度 * msg条数)px. 2.用 将展示msg的目标scroll-view包裹, 通过js获取到

  • Android仿微信之界面导航篇(1)

    微信是现在比较流行的应用了,在各大安卓市场几乎都是名列前茅了. 说实话不得不羡慕腾讯庞大的用户群体,只要腾讯敢做,就会有很多人去用. 废话不多说,下面就开始说一下如何实现微信的第一次启动程序的用户导航,ViewPager相信大家都不陌生了,是google放出的一个安卓低版本的兼容包android-support-v4.jar,里面有很多类我们可以去使用.那这个导航就是使用这个类来辅助完成的,在每一个View里放置一个图片,当我们使用ViewPager滑动界面的时候,就会看到一张张图片,从而实现这

  • Android ListView仿微信聊天界面

    Android ListView仿聊天界面效果图的具体代码,供大家参考,具体内容如下 1.首先页面总布局(ListView + LinearLayout(TextView+Button)) <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="

  • Android仿微信主界面设计

    先来一张效果图 一.ActionBar的设计 首先是main.xml,先定义这些菜单,界面稍后在调整 <menu xmlns:android="http://schemas.android.com/apk/res/android" tools:context=".MainActivity"> <item android:id="@+id/action_search" android:actionViewClass="a

随机推荐