package com.diandi.demo.ui.activity; import android.annotation.SuppressLint; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.MediaStore; import android.support.v4.view.ViewPager; import android.text.Editable; import android.text.Selection; import android.text.Spannable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; 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.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.diandi.demo.R; import com.diandi.demo.adapter.ChatAdapter; import com.diandi.demo.adapter.EmoViewPagerAdapter; import com.diandi.demo.adapter.EmoteAdapter; import com.diandi.demo.adapter.NewRecordPlayClickListener; import com.diandi.demo.receiver.MyMessageReceiver; import com.diandi.demo.config.Constant; import com.diandi.demo.model.diandi.FaceText; import com.diandi.demo.util.CommonUtils; import com.diandi.demo.util.FaceTextUtils; import com.diandi.demo.widget.EmoticonsEditText; import com.diandi.demo.widget.HeaderLayout; import com.diandi.demo.widget.dialog.DialogTips; import com.diandi.demo.widget.xlist.XListView; import com.diandi.demo.widget.xlist.XListView.IXListViewListener; import java.io.File; import java.util.ArrayList; import java.util.List; import cn.bmob.im.BmobChatManager; import cn.bmob.im.BmobNotifyManager; import cn.bmob.im.BmobRecordManager; import cn.bmob.im.bean.BmobChatUser; import cn.bmob.im.bean.BmobInvitation; import cn.bmob.im.bean.BmobMsg; import cn.bmob.im.config.BmobConfig; import cn.bmob.im.db.BmobDB; import cn.bmob.im.inteface.EventListener; import cn.bmob.im.inteface.OnRecordChangeListener; import cn.bmob.im.inteface.UploadListener; import cn.bmob.im.util.BmobLog; import cn.bmob.v3.listener.PushListener; /** * ******************************************************************************* * ********* Author : klob(kloblic@gmail.com) . * ********* Date : 2014-11-29 . * ********* Time : 11:46 . * ********* Project name : Diandi1.18 . * ********* Version : 1.0 * ********* Copyright @ 2014, klob, All Rights Reserved * ******************************************************************************* */ public class ChatActivity extends ActivityBase implements OnClickListener, IXListViewListener, EventListener { public static final int NEW_MESSAGE = 0x001;// 收到消息 private static int MsgPagerNum; XListView mListView; EmoticonsEditText edit_user_comment; String targetId = ""; @SuppressLint("HandlerLeak") private Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == NEW_MESSAGE) { BmobMsg message = (BmobMsg) msg.obj; String uid = message.getBelongId(); if (!uid.equals(targetId))// 如果不是当前正在聊天对象的消息,不处理 return; mAdapter.add(message); // 在聊天页面收到的消息均是已读状态 message.setIsReaded(BmobConfig.STATE_READED); // 保存接收到的消息-并发送已读回执给对方 BmobChatManager.getInstance(ChatActivity.this) .saveReceiveMessage(true, message); // 定位 mListView.setSelection(mAdapter.getCount() - 1); } } }; BmobChatUser targetUser; // 语音有关 RelativeLayout layout_record; TextView tv_voice_tips; ImageView iv_record; BmobRecordManager recordManager; Toast toast; List<FaceText> emos; ChatAdapter mAdapter; private Button btn_chat_emo, btn_chat_send, btn_chat_add, btn_chat_keyboard, btn_speak, btn_chat_voice; private LinearLayout layout_more, layout_emo, layout_add; private ViewPager pager_emo; private TextView tv_picture, tv_camera, tv_location; private Drawable[] drawable_Anims;// 话筒动画 private String localCameraPath = "";// 拍照后得到的图片地址 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); mChatManager = BmobChatManager.getInstance(this); MsgPagerNum = 0; // 组装聊天对象 targetUser = (BmobChatUser) getIntent().getSerializableExtra("user"); targetId = targetUser.getObjectId(); BmobLog.i("聊天对象:" + targetUser.getUsername() + ",targetId = " + targetId); initView(); } private void initRecordManager() { // 语音相关管理器 recordManager = BmobRecordManager.getInstance(this); // 设置音量大小监听--在这里开发者可以自己实现:当剩余10秒情况下的给用户的提示,类似微信的语音那样 recordManager.setOnRecordChangeListener(new OnRecordChangeListener() { @Override public void onVolumnChanged(int value) { iv_record.setImageDrawable(drawable_Anims[value]); } @Override public void onTimeChanged(int recordTime, String localPath) { BmobLog.i("voice", "已录音长度:" + recordTime); if (recordTime >= BmobRecordManager.MAX_RECORD_TIME) {// 1分钟结束,发送消息 // 需要重置按钮 btn_speak.setPressed(false); btn_speak.setClickable(false); // 取消录音框 layout_record.setVisibility(View.INVISIBLE); // 发送语音消息 sendVoiceMessage(localPath, recordTime); //是为了防止过了录音时间后,会多发一条语音出去的情况。 handler.postDelayed(new Runnable() { @Override public void run() { btn_speak.setClickable(true); } }, 1000); } else { } } }); } void initView() { mHeaderLayout = (HeaderLayout) findViewById(R.id.common_actionbar); mListView = (XListView) findViewById(R.id.mListView); initTopBarForLeft("与" + targetUser.getNick() + "对话"); initBottomView(); initXListView(); initVoiceView(); } /** * 初始化语音布局 * * @param * @return void * @throws * @Title: initVoiceView * @Description: TODO */ private void initVoiceView() { layout_record = (RelativeLayout) findViewById(R.id.layout_record); tv_voice_tips = (TextView) findViewById(R.id.tv_voice_tips); iv_record = (ImageView) findViewById(R.id.iv_record); btn_speak.setOnTouchListener(new VoiceTouchListen()); initVoiceAnimRes(); initRecordManager(); } /** * 发送语音消息 * * @param @param localPath * @return void * @throws * @Title: sendImageMessage */ private void sendVoiceMessage(String local, int length) { mChatManager.sendVoiceMessage(targetUser, local, length, new UploadListener() { @Override public void onStart(BmobMsg msg) { refreshMessage(msg); } @Override public void onSuccess() { mAdapter.notifyDataSetChanged(); } @Override public void onFailure(int error, String arg1) { LogE("上传语音失败 -->arg1:" + arg1); mAdapter.notifyDataSetChanged(); } } ); } /** * 显示录音时间过短的Toast * * @return void * @throws * @Title: showShortToast */ private Toast showShortToast() { if (toast == null) { toast = new Toast(this); } View view = LayoutInflater.from(this).inflate( R.layout.include_chat_voice_short, null); toast.setView(view); toast.setGravity(Gravity.CENTER, 0, 0); toast.setDuration(Toast.LENGTH_LONG); return toast; } /** * 初始化语音动画资源 * * @param * @return void * @throws * @Title: initVoiceAnimRes * @Description: TODO */ private void initVoiceAnimRes() { drawable_Anims = new Drawable[]{ getResources().getDrawable(R.drawable.chat_icon_voice2), getResources().getDrawable(R.drawable.chat_icon_voice3), getResources().getDrawable(R.drawable.chat_icon_voice4), getResources().getDrawable(R.drawable.chat_icon_voice5), getResources().getDrawable(R.drawable.chat_icon_voice6)}; } /** * 加载消息历史,从数据库中读出 */ private List<BmobMsg> initMsgData() { List<BmobMsg> list = BmobDB.create(this).queryMessages(targetId, MsgPagerNum); return list; } /** * 界面刷新 * * @param * @return void * @throws * @Title: initOrRefresh * @Description: TODO */ private void initOrRefresh() { if (mAdapter != null) { if (MyMessageReceiver.mNewNum != 0) {// 用于更新当在聊天界面锁屏期间来了消息,这时再回到聊天页面的时候需要显示新来的消息 int news = MyMessageReceiver.mNewNum;//有可能锁屏期间,来了N条消息,因此需要倒叙显示在界面上 int size = initMsgData().size(); for (int i = (news - 1); i >= 0; i--) { mAdapter.add(initMsgData().get(size - (i + 1)));// 添加最后一条消息到界面显示 } mListView.setSelection(mAdapter.getCount() - 1); } else { mAdapter.notifyDataSetChanged(); } } else { mAdapter = new ChatAdapter(this, initMsgData()); mListView.setAdapter(mAdapter); } } private void initAddView() { tv_picture = (TextView) findViewById(R.id.tv_picture); tv_camera = (TextView) findViewById(R.id.tv_camera); tv_location = (TextView) findViewById(R.id.tv_location); tv_picture.setOnClickListener(this); tv_location.setOnClickListener(this); tv_camera.setOnClickListener(this); } private void initBottomView() { // 最左边 btn_chat_add = (Button) findViewById(R.id.btn_chat_add); btn_chat_emo = (Button) findViewById(R.id.btn_chat_emo); btn_chat_add.setOnClickListener(this); btn_chat_emo.setOnClickListener(this); // 最右边 btn_chat_keyboard = (Button) findViewById(R.id.btn_chat_keyboard); btn_chat_voice = (Button) findViewById(R.id.btn_chat_voice); btn_chat_voice.setOnClickListener(this); btn_chat_keyboard.setOnClickListener(this); btn_chat_send = (Button) findViewById(R.id.btn_chat_send); btn_chat_send.setOnClickListener(this); // 最下面 layout_more = (LinearLayout) findViewById(R.id.layout_more); layout_emo = (LinearLayout) findViewById(R.id.layout_emo); layout_add = (LinearLayout) findViewById(R.id.layout_add); initAddView(); initEmoView(); // 最中间 // 语音框 btn_speak = (Button) findViewById(R.id.btn_speak); // 输入框 edit_user_comment = (EmoticonsEditText) findViewById(R.id.edit_user_comment); edit_user_comment.setOnClickListener(this); edit_user_comment.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (!TextUtils.isEmpty(s)) { btn_chat_send.setVisibility(View.VISIBLE); btn_chat_keyboard.setVisibility(View.GONE); btn_chat_voice.setVisibility(View.GONE); } else { if (btn_chat_voice.getVisibility() != View.VISIBLE) { btn_chat_voice.setVisibility(View.VISIBLE); btn_chat_send.setVisibility(View.GONE); btn_chat_keyboard.setVisibility(View.GONE); } } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); } /** * 初始化表情布局 * * @param * @return void * @throws * @Title: initEmoView * @Description: TODO */ private void initEmoView() { pager_emo = (ViewPager) findViewById(R.id.pager_emo); emos = FaceTextUtils.faceTexts; List<View> views = new ArrayList<View>(); for (int i = 0; i < 2; ++i) { views.add(getGridView(i)); } pager_emo.setAdapter(new EmoViewPagerAdapter(views)); } private View getGridView(final int i) { View view = View.inflate(this, R.layout.include_emo_gridview, null); GridView gridview = (GridView) view.findViewById(R.id.gridview); List<FaceText> list = new ArrayList<FaceText>(); if (i == 0) { list.addAll(emos.subList(0, 21)); } else if (i == 1) { list.addAll(emos.subList(21, emos.size())); } final EmoteAdapter gridAdapter = new EmoteAdapter(ChatActivity.this, list); gridview.setAdapter(gridAdapter); gridview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { FaceText name = (FaceText) gridAdapter.getItem(position); String key = name.text.toString(); try { if (edit_user_comment != null && !TextUtils.isEmpty(key)) { int start = edit_user_comment.getSelectionStart(); CharSequence content = edit_user_comment.getText() .insert(start, key); edit_user_comment.setText(content); // 定位光标位置 CharSequence info = edit_user_comment.getText(); if (info instanceof Spannable) { Spannable spanText = (Spannable) info; Selection.setSelection(spanText, start + key.length()); } } } catch (Exception e) { } } }); return view; } private void initXListView() { // 首先不允许加载更多 mListView.setPullLoadEnable(false); // 允许下拉 mListView.setPullRefreshEnable(true); // 设置监听器 mListView.setXListViewListener(this); mListView.pullRefreshing(); mListView.setDividerHeight(0); // 加载数据 initOrRefresh(); mListView.setSelection(mAdapter.getCount() - 1); mListView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent arg1) { hideSoftInputView(); layout_more.setVisibility(View.GONE); layout_add.setVisibility(View.GONE); btn_chat_voice.setVisibility(View.VISIBLE); btn_chat_keyboard.setVisibility(View.GONE); btn_chat_send.setVisibility(View.GONE); return false; } }); // 重发按钮的点击事件 mAdapter.setOnInViewClickListener(R.id.iv_fail_resend, new ChatAdapter.onInternalClickListener() { @Override public void OnClickListener(View parentV, View v, Integer position, Object values) { // 重发消息 showResendDialog(parentV, v, values); } } ); } /** * 显示重发按钮 showResendDialog * * @param @param recent * @return void * @throws * @Title: showResendDialog * @Description: TODO */ public void showResendDialog(final View parentV, View v, final Object values) { DialogTips dialog = new DialogTips(this, "确定重发该消息", "确定", "取消", "提示", true); // 设置成功事件 dialog.SetOnSuccessListener(new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int userId) { if (((BmobMsg) values).getMsgType() == BmobConfig.TYPE_IMAGE || ((BmobMsg) values).getMsgType() == BmobConfig.TYPE_VOICE) {// 图片和语音类型的采用 resendFileMsg(parentV, values); } else { resendTextMsg(parentV, values); } dialogInterface.dismiss(); } }); // 显示确认对话框 dialog.show(); dialog = null; } /** * 重发文本消息 */ private void resendTextMsg(final View parentV, final Object values) { BmobChatManager.getInstance(ChatActivity.this).resendTextMessage( targetUser, (BmobMsg) values, new PushListener() { @Override public void onSuccess() { LogE("发送成功"); ((BmobMsg) values) .setStatus(BmobConfig.STATUS_SEND_SUCCESS); parentV.findViewById(R.id.progress_load).setVisibility( View.INVISIBLE); parentV.findViewById(R.id.iv_fail_resend) .setVisibility(View.INVISIBLE); parentV.findViewById(R.id.tv_send_status) .setVisibility(View.VISIBLE); ((TextView) parentV.findViewById(R.id.tv_send_status)) .setText("已发送"); } @Override public void onFailure(int arg0, String arg1) { LogE("发送失败:" + arg1); ((BmobMsg) values) .setStatus(BmobConfig.STATUS_SEND_FAIL); parentV.findViewById(R.id.progress_load).setVisibility( View.INVISIBLE); parentV.findViewById(R.id.iv_fail_resend) .setVisibility(View.VISIBLE); parentV.findViewById(R.id.tv_send_status) .setVisibility(View.INVISIBLE); } } ); mAdapter.notifyDataSetChanged(); } /** * 重发图片消息 * * @param @param parentV * @param @param values * @return void * @throws * @Title: resendImageMsg * @Description: TODO */ private void resendFileMsg(final View parentV, final Object values) { BmobChatManager.getInstance(ChatActivity.this).resendFileMessage( targetUser, (BmobMsg) values, new UploadListener() { @Override public void onStart(BmobMsg msg) { } @Override public void onSuccess() { ((BmobMsg) values) .setStatus(BmobConfig.STATUS_SEND_SUCCESS); parentV.findViewById(R.id.progress_load).setVisibility( View.INVISIBLE); parentV.findViewById(R.id.iv_fail_resend) .setVisibility(View.INVISIBLE); if (((BmobMsg) values).getMsgType() == BmobConfig.TYPE_VOICE) { parentV.findViewById(R.id.tv_send_status) .setVisibility(View.GONE); parentV.findViewById(R.id.tv_voice_length) .setVisibility(View.VISIBLE); } else { parentV.findViewById(R.id.tv_send_status) .setVisibility(View.VISIBLE); ((TextView) parentV .findViewById(R.id.tv_send_status)) .setText("已发送"); } } @Override public void onFailure(int arg0, String arg1) { ((BmobMsg) values) .setStatus(BmobConfig.STATUS_SEND_FAIL); parentV.findViewById(R.id.progress_load).setVisibility( View.INVISIBLE); parentV.findViewById(R.id.iv_fail_resend) .setVisibility(View.VISIBLE); parentV.findViewById(R.id.tv_send_status) .setVisibility(View.INVISIBLE); } } ); mAdapter.notifyDataSetChanged(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.edit_user_comment:// 点击文本输入框 mListView.setSelection(mListView.getCount() - 1); if (layout_more.getVisibility() == View.VISIBLE) { layout_add.setVisibility(View.GONE); layout_emo.setVisibility(View.GONE); layout_more.setVisibility(View.GONE); } break; case R.id.btn_chat_emo:// 点击笑脸图标 if (layout_more.getVisibility() == View.GONE) { showEditState(true); } else { if (layout_add.getVisibility() == View.VISIBLE) { layout_add.setVisibility(View.GONE); layout_emo.setVisibility(View.VISIBLE); } else { layout_more.setVisibility(View.GONE); } } break; case R.id.btn_chat_add:// 添加按钮-显示图片、拍照、位置 if (layout_more.getVisibility() == View.GONE) { layout_more.setVisibility(View.VISIBLE); layout_add.setVisibility(View.VISIBLE); layout_emo.setVisibility(View.GONE); hideSoftInputView(); } else { if (layout_emo.getVisibility() == View.VISIBLE) { layout_emo.setVisibility(View.GONE); layout_add.setVisibility(View.VISIBLE); } else { layout_more.setVisibility(View.GONE); } } break; case R.id.btn_chat_voice:// 语音按钮 edit_user_comment.setVisibility(View.GONE); layout_more.setVisibility(View.GONE); btn_chat_voice.setVisibility(View.GONE); btn_chat_keyboard.setVisibility(View.VISIBLE); btn_speak.setVisibility(View.VISIBLE); hideSoftInputView(); break; case R.id.btn_chat_keyboard:// 键盘按钮,点击就弹出键盘并隐藏掉声音按钮 showEditState(false); break; case R.id.btn_chat_send:// 发送文本 final String msg = edit_user_comment.getText().toString(); if (msg.equals("")) { ShowToast("请输入发送消息!"); return; } boolean isNetConnected = CommonUtils.isNetworkAvailable(this); if (!isNetConnected) { ShowToast(R.string.network_tips); // return; } // 组装BmobMessage对象 BmobMsg message = BmobMsg.createTextSendMsg(this, targetId, msg); // 默认发送完成,将数据保存到本地消息表和最近会话表中 mChatManager.sendTextMessage(targetUser, message); // 刷新界面 refreshMessage(message); break; case R.id.tv_camera:// 拍照 selectImageFromCamera(); break; case R.id.tv_picture:// 图片 selectImageFromLocal(); break; case R.id.tv_location:// 位置 selectLocationFromMap(); break; default: break; } } /** * 启动地图 * * @param * @return void * @throws * @Title: selectLocationFromMap * @Description: TODO */ private void selectLocationFromMap() { Intent intent = new Intent(this, LocationActivity.class); intent.putExtra("type", "select"); startActivityForResult(intent, Constant.REQUESTCODE_TAKE_LOCATION); } /** * 启动相机拍照 startCamera * * @throws * @Title: startCamera */ public void selectImageFromCamera() { Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File dir = new File(Constant.BMOB_PICTURE_PATH); if (!dir.exists()) { dir.mkdirs(); } File file = new File(dir, String.valueOf(System.currentTimeMillis()) + ".jpg"); localCameraPath = file.getPath(); Uri imageUri = Uri.fromFile(file); openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(openCameraIntent, Constant.REQUESTCODE_TAKE_CAMERA); } /** * 选择图片 * * @param * @return void * @throws * @Title: selectImage * @Description: TODO */ public void selectImageFromLocal() { Intent intent; if (Build.VERSION.SDK_INT < 19) { intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); } else { intent = new Intent( Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); } startActivityForResult(intent, Constant.REQUESTCODE_TAKE_LOCAL); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { case Constant.REQUESTCODE_TAKE_CAMERA:// 当取到值的时候才上传path路径下的图片到服务器 LogE("本地图片的地址:" + localCameraPath); sendImageMessage(localCameraPath); break; case Constant.REQUESTCODE_TAKE_LOCAL: if (data != null) { Uri selectedImage = data.getData(); if (selectedImage != null) { Cursor cursor = getContentResolver().query( selectedImage, null, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex("_data"); String localSelectPath = cursor.getString(columnIndex); cursor.close(); if (localSelectPath == null || localSelectPath.equals("null")) { ShowToast("找不到您想要的图片"); return; } sendImageMessage(localSelectPath); } } break; case Constant.REQUESTCODE_TAKE_LOCATION:// 地理位置 double latitude = data.getDoubleExtra("x", 0);// 维度 double longtitude = data.getDoubleExtra("y", 0);// 经度 String address = data.getStringExtra("address"); if (address != null && !address.equals("")) { sendLocationMessage(address, latitude, longtitude); } else { ShowToast("无法获取到您的位置信息!"); } break; } } } /** * 发送位置信息 * * @param @param address * @param @param latitude * @param @param longtitude * @return void * @throws * @Title: sendLocationMessage * @Description: TODO */ private void sendLocationMessage(String address, double latitude, double longtitude) { if (layout_more.getVisibility() == View.VISIBLE) { layout_more.setVisibility(View.GONE); layout_add.setVisibility(View.GONE); layout_emo.setVisibility(View.GONE); } // 组装BmobMessage对象 BmobMsg message = BmobMsg.createLocationSendMsg(this, targetId, address, latitude, longtitude); // 默认发送完成,将数据保存到本地消息表和最近会话表中 mChatManager.sendTextMessage(targetUser, message); // 刷新界面 refreshMessage(message); } /** * 默认先上传本地图片,之后才显示出来 sendImageMessage * * @param @param localPath * @return void * @throws * @Title: sendImageMessage * @Description: TODO */ private void sendImageMessage(String local) { if (layout_more.getVisibility() == View.VISIBLE) { layout_more.setVisibility(View.GONE); layout_add.setVisibility(View.GONE); layout_emo.setVisibility(View.GONE); } mChatManager.sendImageMessage(targetUser, local, new UploadListener() { @Override public void onStart(BmobMsg msg) { LogE("开始上传onStart:" + msg.getContent() + ",状态:" + msg.getStatus()); refreshMessage(msg); } @Override public void onSuccess() { mAdapter.notifyDataSetChanged(); } @Override public void onFailure(int error, String arg1) { LogE("上传失败 -->arg1:" + arg1); mAdapter.notifyDataSetChanged(); } }); } /** * 刷新界面 * * @param @param message * @return void * @throws * @Title: refreshMessage * @Description: TODO */ private void refreshMessage(BmobMsg msg) { // 更新界面 mAdapter.add(msg); mListView.setSelection(mAdapter.getCount() - 1); edit_user_comment.setText(""); } /** * 根据是否点击笑脸来显示文本输入框的状态 * * @param @param isEmo: 用于区分文字和表情 * @return void * @throws * @Title: showEditState * @Description: TODO */ private void showEditState(boolean isEmo) { edit_user_comment.setVisibility(View.VISIBLE); btn_chat_keyboard.setVisibility(View.GONE); btn_chat_voice.setVisibility(View.VISIBLE); btn_speak.setVisibility(View.GONE); edit_user_comment.requestFocus(); if (isEmo) { layout_more.setVisibility(View.VISIBLE); layout_more.setVisibility(View.VISIBLE); layout_emo.setVisibility(View.VISIBLE); layout_add.setVisibility(View.GONE); hideSoftInputView(); } else { layout_more.setVisibility(View.GONE); showSoftInputView(); } } // 显示软键盘 public void showSoftInputView() { if (getWindow().getAttributes().softInputMode == WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) { if (getCurrentFocus() != null) ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) .showSoftInput(edit_user_comment, 0); } } @Override protected void onResume() { super.onResume(); // 新消息到达,重新刷新界面 initOrRefresh(); MyMessageReceiver.ehList.add(this);// 监听推送的消息 // 有可能锁屏期间,在聊天界面出现通知栏,这时候需要清除通知和清空未读消息数 BmobNotifyManager.getInstance(this).cancelNotify(); BmobDB.create(this).resetUnread(targetId); //清空消息未读数-这个要在刷新之后 MyMessageReceiver.mNewNum = 0; } @Override protected void onPause() { super.onPause(); MyMessageReceiver.ehList.remove(this);// 监听推送的消息 // 停止录音 if (recordManager.isRecording()) { recordManager.cancelRecording(); layout_record.setVisibility(View.GONE); } // 停止播放录音 if (NewRecordPlayClickListener.isPlaying && NewRecordPlayClickListener.currentPlayListener != null) { NewRecordPlayClickListener.currentPlayListener.stopPlayRecord(); } } @Override public void onMessage(BmobMsg message) { Message handlerMsg = handler.obtainMessage(NEW_MESSAGE); handlerMsg.obj = message; handler.sendMessage(handlerMsg); } @Override public void onNetChange(boolean isNetConnected) { if (!isNetConnected) { ShowToast(R.string.network_tips); } } @Override public void onAddUser(BmobInvitation invite) { } @Override public void onOffline() { showOfflineDialog(this); } @Override public void onReaded(String conversionId, String msgTime) { // 此处应该过滤掉不是和当前用户的聊天的回执消息界面的刷新 if (conversionId.split("&")[1].equals(targetId)) { // 修改界面上指定消息的阅读状态 for (BmobMsg msg : mAdapter.getList()) { if (msg.getConversationId().equals(conversionId) && msg.getMsgTime().equals(msgTime)) { msg.setStatus(BmobConfig.STATUS_SEND_RECEIVERED); } mAdapter.notifyDataSetChanged(); } } } public void onRefresh() { handler.postDelayed(new Runnable() { @Override public void run() { MsgPagerNum++; int total = BmobDB.create(ChatActivity.this) .queryChatTotalCount(targetId); BmobLog.i("记录总数:" + total); int currents = mAdapter.getCount(); if (total <= currents) { ShowToast("聊天记录加载完了哦!"); } else { List<BmobMsg> msgList = initMsgData(); mAdapter.setList(msgList); mListView.setSelection(mAdapter.getCount() - currents - 1); } mListView.stopRefresh(); } }, 1000); } @Override public void onLoadMore() { } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (layout_more.getVisibility() == View.VISIBLE) { layout_more.setVisibility(View.GONE); return false; } else { return super.onKeyDown(keyCode, event); } } else { return super.onKeyDown(keyCode, event); } } @Override protected void onDestroy() { super.onDestroy(); hideSoftInputView(); } /** * 长按说话 * * @author smile * @ClassName: VoiceTouchListen * @date 2014-7-1 下午6:10:16 */ class VoiceTouchListen implements View.OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (!CommonUtils.checkSdCard()) { ShowToast("发送语音需要sdcard支持!"); return false; } try { v.setPressed(true); layout_record.setVisibility(View.VISIBLE); tv_voice_tips.setText(getString(R.string.voice_cancel_tips)); // 开始录音 recordManager.startRecording(targetId); } catch (Exception e) { e.printStackTrace(); } return true; case MotionEvent.ACTION_MOVE: { if (event.getY() < 0) { tv_voice_tips .setText(getString(R.string.voice_cancel_tips)); tv_voice_tips.setTextColor(Color.RED); } else { tv_voice_tips.setText(getString(R.string.voice_up_tips)); tv_voice_tips.setTextColor(Color.WHITE); } return true; } case MotionEvent.ACTION_UP: v.setPressed(false); layout_record.setVisibility(View.INVISIBLE); try { if (event.getY() < 0) {// 放弃录音 recordManager.cancelRecording(); BmobLog.i("voice", "放弃发送语音"); } else { int recordTime = recordManager.stopRecording(); if (recordTime > 1) { // 发送语音文件 BmobLog.i("voice", "发送语音"); sendVoiceMessage( recordManager.getRecordFilePath(targetId), recordTime); } else {// 录音时间过短,则提示录音过短的提示 layout_record.setVisibility(View.GONE); showShortToast().show(); } } } catch (Exception e) { } return true; default: return false; } } } }