Commit dd175e595daff5b537a20766b78627f028edffc5

Authored by 王琳
1 parent 7aca54d0

聊天室添加发送图片以及语音消息

Showing 32 changed files with 940 additions and 155 deletions
app/libs/libcnliveutil.jar
No preview for this file type
app/src/main/AndroidManifest.xml
... ... @@ -2,7 +2,6 @@
2 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 3 package="com.cnlive.im">
4 4  
5   -
6 5 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7 6 <uses-permission android:name="android.permission.INTERNET" />
8 7 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
... ... @@ -17,44 +16,37 @@
17 16 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
18 17  
19 18 <application
20   - android:name="com.cnlive.im.CNLiveApplication"
  19 + android:name=".CNLiveApplication"
21 20 android:allowBackup="true"
22 21 android:icon="@mipmap/ic_launcher"
23 22 android:label="@string/app_name"
24 23 android:supportsRtl="true"
25 24 android:theme="@style/AppTheme">
26   - <activity android:name="com.cnlive.im.ui.MainActivity">
  25 + <activity android:name=".ui.MainActivity">
27 26 <intent-filter>
28 27 <action android:name="android.intent.action.MAIN" />
29 28  
30 29 <category android:name="android.intent.category.LAUNCHER" />
31 30 </intent-filter>
32 31 </activity>
33   -
34   -
35 32 <activity
36   - android:name="com.cnlive.im.ui.ChatRoomActivity"
  33 + android:name=".ui.ChatRoomActivity"
37 34 android:theme="@style/Theme.AppCompat.Light.NoActionBar"
38   - android:windowSoftInputMode="adjustResize"></activity>
39   -
  35 + android:windowSoftInputMode="adjustResize" />
40 36 <activity
41   - android:name="com.cnlive.im.ui.LoGinActivity"
  37 + android:name=".ui.LoGinActivity"
42 38 android:screenOrientation="portrait" />
43   -
44 39 <activity
45 40 android:name=".ui.UserLoginActivity"
46 41 android:screenOrientation="portrait" />
47   -
48 42 <activity
49   - android:name="com.cnlive.im.ui.CommentActivity"
  43 + android:name=".ui.CommentActivity"
50 44 android:screenOrientation="portrait" />
51 45  
52   -
53 46 <service
54 47 android:name="io.rong.imlib.ipc.RongService"
55 48 android:exported="true"
56 49 android:process=":ipc" />
57   -
58 50 <service
59 51 android:name="io.rong.imlib.ReConnectService"
60 52 android:exported="true" />
... ... @@ -62,10 +54,10 @@
62 54 <receiver
63 55 android:name="io.rong.imlib.ConnectChangeReceiver"
64 56 android:exported="true" />
65   -
66 57 <receiver
67 58 android:name="io.rong.imlib.HeartbeatReceiver"
68 59 android:process=":ipc" />
  60 +
69 61 </application>
70 62  
71 63 </manifest>
72 64 \ No newline at end of file
... ...
app/src/main/java/com/cnlive/im/adapter/ChatRoomAdpter.java
1 1 package com.cnlive.im.adapter;
2 2  
3 3 import android.content.Context;
  4 +import android.database.Cursor;
4 5 import android.graphics.Color;
5 6 import android.net.Uri;
  7 +import android.provider.ContactsContract;
  8 +import android.provider.MediaStore;
6 9 import android.support.v7.widget.RecyclerView;
  10 +import android.util.Log;
7 11 import android.view.LayoutInflater;
8 12 import android.view.View;
9 13 import android.view.ViewGroup;
  14 +import android.view.WindowManager;
10 15 import android.widget.ImageView;
  16 +import android.widget.LinearLayout;
11 17 import android.widget.TextView;
12 18  
13 19 import com.bumptech.glide.Glide;
... ... @@ -18,6 +24,12 @@ import com.cnlive.im.mode.ImagMessage;
18 24 import com.cnlive.im.mode.StringMessage;
19 25 import com.cnlive.im.mode.VoiceMessage;
20 26  
  27 +import java.text.SimpleDateFormat;
  28 +import java.util.Calendar;
  29 +import java.util.Date;
  30 +import java.util.HashMap;
  31 +import java.util.Locale;
  32 +
21 33 /**
22 34 * @author 陈硕
23 35 * @time 2017/7/14 14:35
... ... @@ -100,6 +112,9 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
100 112 Object o = mItems.get(position);
101 113 ImagMessage o1 = (ImagMessage) o;
102 114 holder1.ima_user_name.setTextColor(Color.parseColor("#d61d0c"));
  115 + holder1.img_content.getLayoutParams().height = 200;
  116 + holder1.img_content.getLayoutParams().width = 200;
  117 + holder1.img_content.setLayoutParams(holder1.img_content.getLayoutParams());
103 118 Glide.with(mContext).load(o1.getCnImgMessage().getRemoteUri()).into(holder1.img_content);
104 119 holder1.ima_user_name.setText(o1.getCnImgMessage().getUserInfo().getUserName());
105 120 } else if (holder instanceof VoiceMessageHolder) {
... ... @@ -108,6 +123,8 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
108 123 VoiceMessage o1 = (VoiceMessage) o;
109 124 holder1.voice_user_name.setText(o1.getCnVoiceMessage().getUserInfo().getUserName());
110 125 final Uri voiceUri = o1.getCnVoiceMessage().getVoiceUri();
  126 + int duration = o1.getCnVoiceMessage().getVoiceTime();
  127 + holder1.voice_duration.setText(String.valueOf(duration).concat("\""));
111 128 holder1.itemView.setOnClickListener(new View.OnClickListener() {
112 129 @Override
113 130 public void onClick(View v) {
... ... @@ -146,15 +163,15 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
146 163  
147 164  
148 165 private TextView voice_user_name;
149   - private ImageView voice_content;
  166 + private TextView voice_content;
  167 + private TextView voice_duration;
150 168  
151 169 public VoiceMessageHolder(View itemView) {
152 170 super(itemView);
153 171 voice_user_name = (TextView) itemView.findViewById(R.id.voice_user_name);
154   - voice_content = (ImageView) itemView.findViewById(R.id.voice_content);
  172 + voice_content = (TextView) itemView.findViewById(R.id.voice_content);
  173 + voice_duration = (TextView) itemView.findViewById(R.id.voice_duration);
155 174 }
156 175 }
157 176  
158   -
159   -
160 177 }
... ...
app/src/main/java/com/cnlive/im/ui/ChatRoomActivity.java
... ... @@ -2,23 +2,37 @@ package com.cnlive.im.ui;
2 2  
3 3 import android.Manifest;
4 4 import android.app.Activity;
  5 +import android.content.ContentResolver;
  6 +import android.content.Context;
5 7 import android.content.Intent;
6 8 import android.content.pm.PackageManager;
  9 +import android.database.Cursor;
7 10 import android.net.Uri;
8 11 import android.os.Build;
9 12 import android.os.Bundle;
10 13 import android.os.Handler;
  14 +import android.provider.ContactsContract;
  15 +import android.provider.MediaStore;
  16 +import android.support.annotation.NonNull;
  17 +import android.support.v4.app.ActivityCompat;
11 18 import android.support.v4.content.ContextCompat;
12 19 import android.support.v7.app.AppCompatActivity;
13 20 import android.support.v7.widget.LinearLayoutManager;
14 21 import android.support.v7.widget.RecyclerView;
  22 +import android.text.Editable;
  23 +import android.text.TextUtils;
  24 +import android.text.TextWatcher;
15 25 import android.util.Log;
  26 +import android.view.Gravity;
16 27 import android.view.MotionEvent;
17 28 import android.view.View;
  29 +import android.view.inputmethod.InputMethodManager;
18 30 import android.widget.Button;
19 31 import android.widget.EditText;
  32 +import android.widget.ImageView;
20 33 import android.widget.LinearLayout;
21 34 import android.widget.RelativeLayout;
  35 +import android.widget.TextView;
22 36 import android.widget.Toast;
23 37  
24 38 import com.cnlive.im.R;
... ... @@ -27,8 +41,11 @@ import com.cnlive.im.adapter.base.VoiceItemClickListener;
27 41 import com.cnlive.im.mode.ImagMessage;
28 42 import com.cnlive.im.mode.StringMessage;
29 43 import com.cnlive.im.mode.VoiceMessage;
  44 +import com.cnlive.im.util.AudioRecordUtil;
30 45 import com.cnlive.im.util.MediaRecorderUtil;
31 46 import com.cnlive.im.util.MessageType;
  47 +import com.cnlive.im.util.PlayerUtil;
  48 +import com.cnlive.im.util.TimeUtils;
32 49 import com.cnlive.libs.util.chat.ChatUtil;
33 50 import com.cnlive.libs.util.chat.base.IChat;
34 51 import com.cnlive.libs.util.chat.model.CNImgMessage;
... ... @@ -38,15 +55,18 @@ import com.cnlive.libs.util.chat.model.CNVoiceMessage;
38 55  
39 56 import org.json.JSONException;
40 57  
  58 +import java.io.LineNumberReader;
41 59 import java.util.ArrayList;
42 60  
  61 +import static android.R.id.edit;
  62 +
43 63  
44 64 /**
45 65 * @author 陈硕
46 66 * @time 2017/3/7 14:36
47 67 * @desc ${TODD}
48 68 */
49   -public class ChatRoomActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener, VoiceItemClickListener {
  69 +public class ChatRoomActivity extends AppCompatActivity implements View.OnClickListener, VoiceItemClickListener {
50 70 private static final String TAG = "ChatRoomActivity";
51 71 private ArrayList<Object> groupChatOneListMy;
52 72 private String roomIdOne = "ChatRoom05";
... ... @@ -57,32 +77,55 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
57 77 private Button foundChatBtn;
58 78 private Handler mHandler;
59 79 private RelativeLayout re_chat;
60   - private LinearLayout lin_user;
61   - private EditText user_id, user_name;
  80 +// private LinearLayout lin_user;
  81 +// private EditText user_id, user_name;
62 82 private Button exit_chat1;
63 83 public static String user_name_string;
64 84 private boolean isUserLogin = false;
65   - private Button ima_send;
66   - private Button voice_send;
  85 + private ImageView ima_send;
  86 + private Button sendVoice;
  87 +
  88 + private Context context;
  89 + private AudioRecordUtil mAudioRecordUtil;
  90 + private PopupWindowFactory mPop;
  91 + private ImageView mImageView;
  92 + private TextView mTextView;
  93 + private ImageView keybordBtn;
  94 +
  95 + private LinearLayout sendMsgLayout;
  96 + private LinearLayout cancelSendLayout;
  97 +
  98 + private boolean isVoiceBtnVisible = false;
67 99  
68 100  
69 101 public static final int IMG_FROM_PICTURE = 0x1001;
70 102 public static final int VOICE = 0x1002;
71 103 public static final int PICTURE_REQUEST_CODE = 0x1003;
72 104 public static final int VOICE_REQUEST_CODE = 0x1004;
73   - private MediaRecorderUtil mediaRecorderUtil;
74 105 private long l;
75 106 int i;
76 107  
  108 + private String mFilePath;
  109 +
  110 + private PlayerUtil playerUtil;
  111 +
  112 + // 所需的全部权限
  113 + static final String[] PERMISSIONS = new String[]{
  114 + Manifest.permission.RECORD_AUDIO,
  115 + Manifest.permission.WRITE_EXTERNAL_STORAGE
  116 + };
  117 +
77 118 @Override
78 119 protected void onCreate(Bundle savedInstanceState) {
79 120 super.onCreate(savedInstanceState);
80 121 //取消状态栏
81 122 setContentView(R.layout.activity_groupchat);
  123 + context = this;
82 124 initUI();
  125 + mAudioRecordUtil = new AudioRecordUtil();
  126 + mAudioRecordUtil.setOnAudioStatusUpdateListener(onAudioStatusUpdateListener);
83 127 //设置监听
84 128 mHandler = new Handler();
85   - mediaRecorderUtil = new MediaRecorderUtil();
86 129 ChatUtil.setOnConnectStatusListener(connectStatusListener);
87 130 ChatUtil.setOnChatRoomActionListener(chatRoomActionListener);
88 131 ChatUtil.setOnReceiveMessageListener(receiveMessageListener);
... ... @@ -93,21 +136,30 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
93 136 if (user_name_string != null)
94 137 ChatUtil.login(new CNUserInfo(user_id_string, user_name_string, ""), connectListener);
95 138 else ChatUtil.logOut(connectListener);
  139 + requestPermission();
  140 + playerUtil = new PlayerUtil(this);
96 141  
97 142 }
98 143  
99 144  
100 145 private void initUI() {
101   - voice_send = (Button) findViewById(R.id.voice_send);
102   - ima_send = (Button) findViewById(R.id.ima_send);
  146 +
  147 + final View view = View.inflate(this, R.layout.layout_microphone, null);
  148 + mPop = new PopupWindowFactory(this, view);
  149 + mImageView = (ImageView) view.findViewById(R.id.iv_recording_icon);
  150 + mTextView = (TextView) view.findViewById(R.id.tv_recording_time);
  151 + sendMsgLayout = (LinearLayout) view.findViewById(R.id.send_layout);
  152 + cancelSendLayout = (LinearLayout) view.findViewById(R.id.cancel_send_layout);
  153 + ima_send = (ImageView) findViewById(R.id.ima_send);
103 154 exit_chat1 = (Button) findViewById(R.id.exit_chat1);
104   - user_id = (EditText) findViewById(R.id.user_ID);
105   - user_name = (EditText) findViewById(R.id.user_name);
106   - lin_user = (LinearLayout) findViewById(R.id.lin_user);
  155 +// user_id = (EditText) findViewById(R.id.user_ID);
  156 +// user_name = (EditText) findViewById(R.id.user_name);
  157 +// lin_user = (LinearLayout) findViewById(R.id.lin_user);
107 158 re_chat = (RelativeLayout) findViewById(R.id.re_chat);
108 159 foundChatBtn = (Button) findViewById(R.id.creatChat);
109 160 listViewOne = (RecyclerView) findViewById(R.id.chat_list_viewOne);
110 161 editText = (EditText) findViewById(R.id.message_content);
  162 + editText.addTextChangedListener(textWatcher);
111 163 send_messageOneBtn = (Button) findViewById(R.id.send_messageOne);
112 164 ima_send.setOnClickListener(this);
113 165 exit_chat1.setOnClickListener(this);
... ... @@ -118,7 +170,15 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
118 170 chatListAdapterOne.setonVoiceItemClickListener(this);
119 171 listViewOne.setLayoutManager(new LinearLayoutManager(ChatRoomActivity.this));
120 172 listViewOne.setAdapter(chatListAdapterOne);
121   - voice_send.setOnTouchListener(this);
  173 +
  174 + sendVoice = (Button) findViewById(R.id.send_voice);
  175 + re_chat = (RelativeLayout) findViewById(R.id.activity_chat_room);
  176 + keybordBtn = (ImageView) findViewById(R.id.keybord);
  177 + keybordBtn.setOnClickListener(this);
  178 +
  179 +
  180 + StartListener();
  181 +
122 182  
123 183 }
124 184  
... ... @@ -126,7 +186,6 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
126 186 /**
127 187 * 发送消息监听
128 188 */
129   -
130 189 private IChat.OnSendMessageListener sendMessageListener = new IChat.OnSendMessageListener() {
131 190 @Override
132 191 public void onAttached(Object o) {
... ... @@ -148,14 +207,20 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
148 207 CNVoiceMessage o1 = (CNVoiceMessage) o;
149 208 VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, true);
150 209 chatListAdapterOne.addItem(voiceMessage);
  210 + //发送成功后删除保存在本地的录制文件
  211 + mAudioRecordUtil.deleteRecordFile(mFilePath);
  212 +
151 213 }
  214 + listViewOne.smoothScrollToPosition(chatListAdapterOne.getItemCount() - 1);
152 215 }
153 216 });
154 217 }
155 218  
156 219 @Override
157 220 public void onError(Object o, int i, String s) {
  221 + if (o instanceof CNImgMessage) {
158 222  
  223 + }
159 224 }
160 225 };
161 226  
... ... @@ -186,6 +251,7 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
186 251 VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, false);
187 252 chatListAdapterOne.addItem(voiceMessage);
188 253 }
  254 + listViewOne.smoothScrollToPosition(chatListAdapterOne.getItemCount() - 1);
189 255 }
190 256 });
191 257  
... ... @@ -282,41 +348,24 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
282 348 case R.id.ima_send:
283 349 fromPicture();
284 350 break;
  351 + case R.id.keybord:
  352 + if (!isVoiceBtnVisible) {
  353 + editText.setVisibility(View.GONE);
  354 + sendVoice.setVisibility(View.VISIBLE);
  355 + keybordBtn.setImageResource(R.drawable.keybord);
  356 + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
  357 + imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
  358 + isVoiceBtnVisible = true;
  359 + } else {
  360 + sendVoice.setVisibility(View.GONE);
  361 + editText.setVisibility(View.VISIBLE);
  362 + keybordBtn.setImageResource(R.drawable.voice);
  363 + isVoiceBtnVisible = false;
  364 + }
  365 + break;
285 366 }
286 367 }
287 368  
288   - public void mediaRecorder() {
289   - if (Build.VERSION.SDK_INT >= 23) {
290   - int checkCallPhonePermission = ContextCompat.checkSelfPermission(ChatRoomActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
291   - int checkCallPhonePermission1 = ContextCompat.checkSelfPermission(ChatRoomActivity.this, Manifest.permission.RECORD_AUDIO);
292   -
293   - if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED || checkCallPhonePermission1 != PackageManager.PERMISSION_GRANTED) {
294   - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, VOICE_REQUEST_CODE);
295   - return;
296   - } else {
297   - recorder();
298   - }
299   - } else {
300   - recorder();
301   - }
302   - }
303   -
304   -
305   - public String getRecoderFile() {
306   -
307   - return mediaRecorderUtil.getRecorderFile();
308   -
309   - }
310   -
311   - public void recorder() {
312   - mediaRecorderUtil.record();
313   -
314   - }
315   -
316   - public void releaseRecord() {
317   - mediaRecorderUtil.releaseRecord();
318   -
319   - }
320 369  
321 370 public void fromPicture() {
322 371 if (Build.VERSION.SDK_INT >= 23) {
... ... @@ -336,31 +385,8 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
336 385 private void toIntentPicture() {
337 386 Intent intent = new Intent();
338 387 intent.setType("image/*");
339   - intent.setAction(Intent.ACTION_GET_CONTENT);
340   - startActivityForResult(intent, IMG_FROM_PICTURE);
341   - }
342   -
343   -
344   - @Override
345   - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
346   - super.onRequestPermissionsResult(requestCode, permissions, grantResults);
347   - switch (requestCode) {
348   - case PICTURE_REQUEST_CODE:
349   - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
350   - toIntentPicture();
351   - } else {
352   - Toast.makeText(ChatRoomActivity.this, "权限已被禁止,请打开,再使用此功能", Toast.LENGTH_LONG).show();
353   - }
354   - break;
355   -
356   - case VOICE_REQUEST_CODE:
357   - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
358   - recorder();
359   - } else {
360   - Toast.makeText(ChatRoomActivity.this, "权限已被禁止,请打开,再使用此功能", Toast.LENGTH_LONG).show();
361   - }
362   - break;
363   - }
  388 + intent.setAction(Intent.ACTION_PICK);
  389 + startActivityForResult(Intent.createChooser(intent, "Complete action using"), IMG_FROM_PICTURE);
364 390 }
365 391  
366 392  
... ... @@ -370,7 +396,19 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
370 396 if (resultCode == Activity.RESULT_OK) {
371 397 switch (requestCode) {
372 398 case IMG_FROM_PICTURE:
373   - Uri uri = data.getData();
  399 +// String localImagePath = "/sdcard/test.png";
  400 +// Uri selectedImage = Uri.parse("file://" + localImagePath);
  401 + Uri selectedImage = data.getData();
  402 + String[] filePathColumn = {MediaStore.Images.Media.DATA};
  403 +
  404 + Cursor cursor = getContentResolver().query(selectedImage,
  405 + filePathColumn, null, null, null);
  406 + cursor.moveToFirst();
  407 +
  408 + int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
  409 + final String picturePath = cursor.getString(columnIndex);
  410 +
  411 + Uri uri = Uri.parse("file://" + picturePath);
374 412 ChatUtil.sendImaMessage(IChat.CHATROOM, roomIdOne, uri, uri, sendMessageListener);
375 413 break;
376 414  
... ... @@ -406,53 +444,169 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
406 444  
407 445  
408 446 @Override
409   - public boolean onTouch(View v, MotionEvent event) {
  447 + public void onItemClick(Uri uri) {
  448 + playerUtil.start(uri);
410 449  
411   - switch (event.getAction()) {
412   - case MotionEvent.ACTION_DOWN:
413   - l = System.currentTimeMillis();
414   - mediaRecorder();
415   - break;
416   - case MotionEvent.ACTION_UP:
  450 + }
  451 +
  452 +
  453 + /**************************************************************************/
  454 +
  455 + /**
  456 + * 开启扫描之前判断权限是否打开
  457 + */
  458 + private void requestPermission() {
  459 + //判断是否开启摄像头权限
  460 + if ((ContextCompat.checkSelfPermission(context,
  461 + Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) &&
  462 + (ContextCompat.checkSelfPermission(context,
  463 + Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)
  464 + ) {
  465 + StartListener();
  466 +
  467 + //判断是否开启语音权限
  468 + } else {
  469 + //请求获取摄像头权限
  470 + ActivityCompat.requestPermissions((Activity) context,
  471 + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, VOICE_REQUEST_CODE);
  472 + }
  473 + }
417 474  
418   - if (Build.VERSION.SDK_INT >= 23) {
419   - int checkCallPhonePermission = ContextCompat.checkSelfPermission(ChatRoomActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
420   - int checkCallPhonePermission1 = ContextCompat.checkSelfPermission(ChatRoomActivity.this, Manifest.permission.RECORD_AUDIO);
  475 + @Override
  476 + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  477 + super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  478 + if (requestCode == VOICE_REQUEST_CODE) {
  479 + if ((grantResults[0] == PackageManager.PERMISSION_GRANTED) && (grantResults[1] == PackageManager.PERMISSION_GRANTED)) {
  480 + StartListener();
  481 + } else {
  482 + Toast.makeText(context, "已拒绝权限!", Toast.LENGTH_SHORT).show();
  483 + }
  484 + }
  485 + }
  486 +
  487 + float downX;
  488 + float downY;
  489 +
  490 + public void StartListener() {
  491 +
  492 + //Button的touch监听
  493 + sendVoice.setOnTouchListener(new View.OnTouchListener() {
  494 + @Override
  495 + public boolean onTouch(View v, MotionEvent event) {
  496 + if (lacksPermissions(PERMISSIONS)) {
  497 + if (lacksPermission(PERMISSIONS[0])) {
  498 + Toast.makeText(ChatRoomActivity.this, "没有麦克风权限,请前往“设置 - 应用 - 权限”中开启权限", Toast.LENGTH_SHORT).show();
  499 +
  500 + } else if (lacksPermission(PERMISSIONS[1])) {
  501 + Toast.makeText(ChatRoomActivity.this, "没有文件读写权限,请前往“设置 - 应用 - 权限”中开启权限", Toast.LENGTH_SHORT).show();
421 502  
422   - if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED || checkCallPhonePermission1 != PackageManager.PERMISSION_GRANTED) {
423   - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, VOICE_REQUEST_CODE);
424   - } else {
425   - sendVoice();
426 503 }
427 504 } else {
428   - sendVoice();
  505 +
  506 + switch (event.getAction()) {
  507 +
  508 + case MotionEvent.ACTION_DOWN:
  509 + mPop.showAtLocation(re_chat, Gravity.CENTER, 0, 0);
  510 +
  511 + sendVoice.setText("松开发送");
  512 + mAudioRecordUtil.startRecord();
  513 + downX = event.getX();
  514 + downY = event.getY();
  515 +
  516 + break;
  517 +
  518 + case MotionEvent.ACTION_UP:
  519 +
  520 + if (cancelSendLayout.getVisibility() == View.VISIBLE) {
  521 + cancelSendLayout.setVisibility(View.GONE);
  522 + sendMsgLayout.setVisibility(View.VISIBLE);
  523 + }
  524 + float moveX = Math.abs(event.getX() - downX);
  525 + float moveY = Math.abs(event.getY() - downY);
  526 + if (moveY > 100) {
  527 +// Toast.makeText(ChatRoomActivity.this, "cancel", Toast.LENGTH_SHORT).show();
  528 + mAudioRecordUtil.cancelRecord();
  529 + } else {
  530 + mAudioRecordUtil.stopRecord(); //结束录音(保存录音文件)
  531 + }
  532 + mPop.dismiss();
  533 + mTextView.setText("00:00");
  534 + sendVoice.setText("按住说话");
  535 + break;
  536 + case MotionEvent.ACTION_MOVE:
  537 + float moveXm = Math.abs(event.getX() - downX);
  538 + float moveYm = Math.abs(event.getY() - downY);
  539 + if (moveYm > 100) {
  540 +// Toast.makeText(ChatRoomActivity.this, "cancel", Toast.LENGTH_SHORT).show();
  541 + if (sendMsgLayout.getVisibility() == View.VISIBLE) {
  542 + sendMsgLayout.setVisibility(View.GONE);
  543 + cancelSendLayout.setVisibility(View.VISIBLE);
  544 + }
  545 + } else {
  546 + if (cancelSendLayout.getVisibility() == View.VISIBLE) {
  547 + cancelSendLayout.setVisibility(View.GONE);
  548 + sendMsgLayout.setVisibility(View.VISIBLE);
  549 + }
  550 + }
  551 + break;
  552 + }
429 553 }
  554 + return true;
  555 + }
  556 + });
430 557  
  558 + }
431 559  
432   - break;
  560 + // 判断权限集合
  561 + public boolean lacksPermissions(String... permissions) {
  562 + for (String permission : permissions) {
  563 + if (lacksPermission(permission)) {
  564 + return true;
  565 + }
  566 + }
  567 + return false;
  568 + }
433 569  
  570 + // 判断是否缺少权限
  571 + private boolean lacksPermission(String permission) {
  572 + return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_DENIED;
  573 + }
434 574  
  575 + private AudioRecordUtil.OnAudioStatusUpdateListener onAudioStatusUpdateListener = new AudioRecordUtil.OnAudioStatusUpdateListener() {
  576 + @Override
  577 + public void onUpdate(double db, long time) {
  578 + mImageView.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
  579 + mTextView.setText(TimeUtils.long2String(time));
435 580 }
436 581  
437   - return true;
438   - }
  582 + @Override
  583 + public void onStop(String filePath) {
  584 + i = (int) mAudioRecordUtil.getDuration();
  585 + mFilePath = filePath;
  586 + ChatUtil.sendVoiceMessage(IChat.CHATROOM, roomIdOne, Uri.parse(mFilePath), i, sendMessageListener);
  587 + }
  588 + };
439 589  
440   - private void sendVoice() {
441   - long l1 = System.currentTimeMillis();
442   - long l2 = (l1 - l) / 1000;
443   - i = (int) l2;
444   - releaseRecord();
445   - String recoderFile = getRecoderFile();
446   - ChatUtil.sendVoiceMessage(IChat.CHATROOM, roomIdOne, Uri.parse(recoderFile), i, sendMessageListener);
447   - }
  590 + private TextWatcher textWatcher = new TextWatcher() {
  591 + @Override
  592 + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
  593 + }
448 594  
449   - @Override
450   - public void onItemClick(Uri uri) {
451   - plaVoice(uri);
  595 + @Override
  596 + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
452 597  
453   - }
  598 + }
  599 +
  600 + @Override
  601 + public void afterTextChanged(Editable editable) {
  602 + if (!TextUtils.isEmpty(editable)){
  603 + ima_send.setVisibility(View.GONE);
  604 + send_messageOneBtn.setVisibility(View.VISIBLE);
  605 + }else {
  606 + send_messageOneBtn.setVisibility(View.GONE);
  607 + ima_send.setVisibility(View.VISIBLE);
  608 + }
  609 + }
  610 + };
454 611  
455   - public void plaVoice(Uri uri) {
456   - mediaRecorderUtil.plaVoice(uri, this);
457   - }
458 612 }
... ...
app/src/main/java/com/cnlive/im/ui/PopupWindowFactory.java 0 → 100644
  1 +package com.cnlive.im.ui;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.drawable.BitmapDrawable;
  5 +import android.util.Log;
  6 +import android.view.KeyEvent;
  7 +import android.view.MotionEvent;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +import android.widget.PopupWindow;
  11 +
  12 +/**
  13 + * Created by Lynn on 2017/7/21.
  14 + */
  15 +
  16 +public class PopupWindowFactory {
  17 + private Context mContext;
  18 + private PopupWindow mPop;
  19 +
  20 + /**
  21 + * @param context 上下文
  22 + * @param view PopupWindow显示的布局文件
  23 + */
  24 + public PopupWindowFactory(Context context, View view) {
  25 + this(context, view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
  26 + }
  27 +
  28 + /**
  29 + * @param context 上下文
  30 + * @param view PopupWindow显示的布局文件
  31 + * @param width PopupWindow的宽
  32 + * @param height PopupWindow的高
  33 + */
  34 + public PopupWindowFactory(Context context, View view, int width, int height) {
  35 + init(context, view, width, height);
  36 + }
  37 +
  38 +
  39 + private void init(Context context, View view, int width, int height) {
  40 + this.mContext = context;
  41 +
  42 + //下面这两个必须有
  43 + view.setFocusable(true);
  44 + view.setFocusableInTouchMode(true);
  45 +
  46 + //PopupWindow(布局,宽度、高度)
  47 + mPop = new PopupWindow(view, width, height, true);
  48 + mPop.setFocusable(true);
  49 + mPop.setOutsideTouchable(false);
  50 +
  51 + //重写onKeyListener,按返回键消失
  52 + view.setOnKeyListener(new View.OnKeyListener() {
  53 + @Override
  54 + public boolean onKey(View view, int i, KeyEvent keyEvent) {
  55 + if (i == KeyEvent.KEYCODE_BACK) {
  56 + mPop.dismiss();
  57 + return true;
  58 + }
  59 + return false;
  60 + }
  61 + });
  62 +
  63 +// 点击其他地方消失
  64 + view.setOnTouchListener(new View.OnTouchListener() {
  65 + @Override
  66 + public boolean onTouch(View view, MotionEvent motionEvent) {
  67 + if (mPop != null && mPop.isShowing()) {
  68 +// mPop.dismiss();
  69 + return true;
  70 + }
  71 + return false;
  72 + }
  73 + });
  74 +
  75 + }
  76 +
  77 + public PopupWindow getPopupWindow() {
  78 + return mPop;
  79 + }
  80 +
  81 + /**
  82 + * 以触发弹出窗的view为基准,出现在view的内部上面,弹出的pop_view左上角正对view的左上角
  83 + *
  84 + * @param parent view
  85 + * @param gravity 在view的什么位置Gravity.CENTER、Gravity.TOP......
  86 + * @param x 与控件的x坐标距离
  87 + * @param y 与控件的y坐标距离
  88 + */
  89 + public void showAtLocation(View parent, int gravity, int x, int y) {
  90 + if (mPop.isShowing()) {
  91 + return;
  92 + }
  93 + mPop.showAtLocation(parent, gravity, x, y);
  94 + }
  95 +
  96 + /**
  97 + * 以触发弹出窗的view为基准,出现在view的正下方,弹出的pop_view左上角正对view的左下角
  98 + *
  99 + * @param anchor view
  100 + */
  101 + public void showAsDropDown(View anchor) {
  102 + showAsDropDown(anchor, 0, 0);
  103 + }
  104 +
  105 + /**
  106 + * 以触发弹出窗的view为基准,出现在view的正下方,弹出的pop_view左上角正对view的左下角
  107 + *
  108 + * @param anchor view
  109 + * @param xoff 与view的x坐标距离
  110 + * @param yoff 与view的y坐标距离
  111 + */
  112 + public void showAsDropDown(View anchor, int xoff, int yoff) {
  113 + if (mPop.isShowing()) {
  114 + return;
  115 + }
  116 +
  117 + mPop.showAsDropDown(anchor, xoff, yoff);
  118 + }
  119 +
  120 + /**
  121 + * 隐藏popupwindow
  122 + */
  123 + public void dismiss() {
  124 + if (mPop.isShowing()) {
  125 + mPop.dismiss();
  126 + }
  127 + }
  128 +}
... ...
app/src/main/java/com/cnlive/im/ui/UserLoginActivity.java
... ... @@ -50,7 +50,7 @@ public class UserLoginActivity extends AppCompatActivity implements View.OnClick
50 50 doIntentChatRoom(ChatRoomActivity.class);
51 51 break;
52 52 case R.id.private_chat:
53   - // doIntentChatRoom(PrivateChatActivity.class);
  53 + doIntentChatRoom(PrivateChatActivity.class);
54 54  
55 55 break;
56 56 }
... ...
app/src/main/java/com/cnlive/im/util/AudioRecordUtil.java 0 → 100644
  1 +package com.cnlive.im.util;
  2 +
  3 +import android.media.MediaRecorder;
  4 +import android.os.Environment;
  5 +import android.os.Handler;
  6 +import android.util.Log;
  7 +
  8 +import java.io.File;
  9 +import java.io.IOException;
  10 +import java.text.SimpleDateFormat;
  11 +
  12 +/**
  13 + * Created by Lynn on 2017/7/20.
  14 + */
  15 +
  16 +public class AudioRecordUtil {
  17 + //文件路径
  18 + private String filePath;
  19 + //文件夹路径
  20 + private String FolderPath;
  21 +
  22 + private MediaRecorder mMediaRecorder;
  23 + private final String TAG = "fan";
  24 + public static final int MAX_LENGTH = 1000 * 60 * 10;// 最大录音时长1000*60*10;
  25 +
  26 + private OnAudioStatusUpdateListener audioStatusUpdateListener;
  27 +
  28 + /**
  29 + * 文件存储默认sdcard/record
  30 + */
  31 + public AudioRecordUtil() {
  32 +
  33 + //默认保存路径为/sdcard/record/下
  34 + this(Environment.getExternalStorageDirectory() + "/record/");
  35 + }
  36 +
  37 + public AudioRecordUtil(String filePath) {
  38 +
  39 + File path = new File(filePath);
  40 + if (!path.exists())
  41 + path.mkdirs();
  42 +
  43 + this.FolderPath = filePath;
  44 + }
  45 +
  46 + private long startTime;
  47 + private long endTime;
  48 +
  49 +
  50 + /**
  51 + * 开始录音 使用amr格式
  52 + * 录音文件
  53 + *
  54 + * @return
  55 + */
  56 + public void startRecord() {
  57 + // 开始录音
  58 + /* ①Initial:实例化MediaRecorder对象 */
  59 + if (mMediaRecorder == null)
  60 + mMediaRecorder = new MediaRecorder();
  61 + try {
  62 + /* ②setAudioSource/setVedioSource */
  63 + mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
  64 + /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
  65 + mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
  66 + /*
  67 + * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
  68 + * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
  69 + */
  70 + mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
  71 +
  72 + filePath = FolderPath + getCurrentTime() + ".amr";
  73 + /* ③准备 */
  74 + mMediaRecorder.setOutputFile(filePath);
  75 + mMediaRecorder.setMaxDuration(MAX_LENGTH);
  76 + mMediaRecorder.prepare();
  77 + /* ④开始 */
  78 + mMediaRecorder.start();
  79 + // AudioRecord audioRecord.
  80 + /* 获取开始时间* */
  81 + startTime = System.currentTimeMillis();
  82 + updateMicStatus();
  83 + Log.e("fan", "startTime" + startTime);
  84 + } catch (IllegalStateException e) {
  85 + Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
  86 + } catch (IOException e) {
  87 + Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
  88 + }
  89 + }
  90 +
  91 + /**
  92 + * 停止录音
  93 + */
  94 + public void stopRecord() {
  95 + if (mMediaRecorder == null)
  96 + return;
  97 + endTime = System.currentTimeMillis();
  98 +
  99 + //有一些网友反应在5.0以上在调用stop的时候会报错,翻阅了一下谷歌文档发现上面确实写的有可能会报错的情况,捕获异常清理一下就行了,感谢大家反馈!
  100 + try {
  101 + mMediaRecorder.stop();
  102 + mMediaRecorder.reset();
  103 + mMediaRecorder.release();
  104 + mMediaRecorder = null;
  105 +
  106 + audioStatusUpdateListener.onStop(filePath);
  107 + filePath = "";
  108 +
  109 + } catch (RuntimeException e) {
  110 + mMediaRecorder.reset();
  111 + mMediaRecorder.release();
  112 + mMediaRecorder = null;
  113 +
  114 + File file = new File(filePath);
  115 + if (file.exists())
  116 + file.delete();
  117 +
  118 + filePath = "";
  119 +
  120 + }
  121 +// return endTime - startTime;
  122 + }
  123 +
  124 + public long getDuration(){
  125 + return (endTime - startTime) / 1000;
  126 + }
  127 +
  128 + /**
  129 + * 取消录音
  130 + */
  131 + public void cancelRecord() {
  132 +
  133 + try {
  134 +
  135 + mMediaRecorder.stop();
  136 + mMediaRecorder.reset();
  137 + mMediaRecorder.release();
  138 + mMediaRecorder = null;
  139 +
  140 + } catch (RuntimeException e) {
  141 + mMediaRecorder.reset();
  142 + mMediaRecorder.release();
  143 + mMediaRecorder = null;
  144 + }
  145 + File file = new File(filePath);
  146 + if (file.exists())
  147 + file.delete();
  148 +
  149 + filePath = "";
  150 +
  151 + }
  152 +
  153 + private final Handler mHandler = new Handler();
  154 + private Runnable mUpdateMicStatusTimer = new Runnable() {
  155 + public void run() {
  156 + updateMicStatus();
  157 + }
  158 + };
  159 +
  160 +
  161 + private int BASE = 1;
  162 + private int SPACE = 100;// 间隔取样时间
  163 +
  164 + public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) {
  165 + this.audioStatusUpdateListener = audioStatusUpdateListener;
  166 + }
  167 +
  168 + /**
  169 + * 更新麦克状态
  170 + */
  171 + private void updateMicStatus() {
  172 +
  173 + if (mMediaRecorder != null) {
  174 + double ratio = (double) mMediaRecorder.getMaxAmplitude() / BASE;
  175 + double db = 0;// 分贝
  176 + if (ratio > 1) {
  177 + db = 20 * Math.log10(ratio);
  178 + if (null != audioStatusUpdateListener) {
  179 + audioStatusUpdateListener.onUpdate(db, System.currentTimeMillis() - startTime);
  180 + }
  181 + }
  182 + mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
  183 + }
  184 + }
  185 +
  186 + /**
  187 + * 删除本地录制的文件
  188 + * @param filePath
  189 + */
  190 + public void deleteRecordFile(String filePath) {
  191 + File file = new File(filePath);
  192 + if (file.exists())
  193 + file.delete();
  194 + }
  195 +
  196 + public interface OnAudioStatusUpdateListener {
  197 + /**
  198 + * 录音中...
  199 + *
  200 + * @param db 当前声音分贝
  201 + * @param time 录音时长
  202 + */
  203 + public void onUpdate(double db, long time);
  204 +
  205 + /**
  206 + * 停止录音
  207 + *
  208 + * @param filePath 保存路径
  209 + */
  210 + public void onStop(String filePath);
  211 + }
  212 +
  213 + private String getCurrentTime() {
  214 + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
  215 + return sdf.format(System.currentTimeMillis());
  216 + }
  217 +}
... ...
app/src/main/java/com/cnlive/im/util/IVoiceManager.java 0 → 100644
  1 +package com.cnlive.im.util;
  2 +
  3 +import android.content.Context;
  4 +import android.net.Uri;
  5 +
  6 +/**
  7 + * Created by Lynn on 2017/7/21.
  8 + */
  9 +
  10 +public interface IVoiceManager {
  11 + boolean start(Uri uri);
  12 + boolean stop();
  13 + void onDestory();
  14 +}
... ...
app/src/main/java/com/cnlive/im/util/PlayerUtil.java 0 → 100644
  1 +package com.cnlive.im.util;
  2 +
  3 +import android.content.Context;
  4 +import android.media.MediaPlayer;
  5 +import android.net.Uri;
  6 +
  7 +/**
  8 + * Created by Lynn on 2017/7/21.
  9 + */
  10 +
  11 +public class PlayerUtil implements IVoiceManager{
  12 + private final String TAG = "PlayerUtil";
  13 + private String path;
  14 + private Context mContext;
  15 +
  16 + private MediaPlayer mediaPlayer;
  17 +
  18 + public PlayerUtil(Context context){
  19 + this.mContext = context;
  20 +// mediaPlayer = new MediaPlayer();
  21 +// mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  22 +// @Override
  23 +// public void onCompletion(MediaPlayer mediaPlayer) {
  24 +//// mediaPlayer.stop();
  25 +// stop();
  26 +// }
  27 +// });
  28 + }
  29 +
  30 + @Override
  31 + public boolean start(Uri uri) {
  32 + try {
  33 + mediaPlayer = new MediaPlayer();
  34 + mediaPlayer.setOnCompletionListener(onCompletionListener);
  35 + mediaPlayer.setOnPreparedListener(onPreparedListener);
  36 + mediaPlayer.setDataSource(mContext, uri);
  37 + mediaPlayer.prepare();
  38 +// mediaPlayer.start();
  39 + }catch (Exception e){
  40 + e.printStackTrace();
  41 + }
  42 + return false;
  43 + }
  44 +
  45 + @Override
  46 + public boolean stop() {
  47 + mediaPlayer.stop();
  48 + mediaPlayer.release();
  49 + mediaPlayer = null;
  50 + return false;
  51 + }
  52 +
  53 + @Override
  54 + public void onDestory() {
  55 + mediaPlayer.release();
  56 + mediaPlayer = null;
  57 + }
  58 +
  59 + private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
  60 + @Override
  61 + public void onCompletion(MediaPlayer mediaPlayer) {
  62 + stop();
  63 + }
  64 + };
  65 +
  66 + private MediaPlayer.OnPreparedListener onPreparedListener = new MediaPlayer.OnPreparedListener() {
  67 + @Override
  68 + public void onPrepared(MediaPlayer mediaPlayer) {
  69 + mediaPlayer.start();
  70 + }
  71 + };
  72 +}
... ...
app/src/main/java/com/cnlive/im/util/TimeUtils.java 0 → 100644
  1 +package com.cnlive.im.util;
  2 +
  3 +
  4 +import java.text.SimpleDateFormat;
  5 +
  6 +/**
  7 + * Created by fan on 2016/6/23.
  8 + */
  9 +public class TimeUtils {
  10 +
  11 + //毫秒转秒
  12 + public static String long2String(long time){
  13 +
  14 + //毫秒转秒
  15 + int sec = (int) time / 1000 ;
  16 + int min = sec / 60 ; //分钟
  17 + sec = sec % 60 ; //秒
  18 + if(min < 10){ //分钟补0
  19 + if(sec < 10){ //秒补0
  20 + return "0"+min+":0"+sec;
  21 + }else{
  22 + return "0"+min+":"+sec;
  23 + }
  24 + }else{
  25 + if(sec < 10){ //秒补0
  26 + return min+":0"+sec;
  27 + }else{
  28 + return min+":"+sec;
  29 + }
  30 + }
  31 +
  32 + }
  33 +
  34 + /**
  35 + * 返回当前时间的格式为 yyyy-MM-dd HH:mm:ss
  36 + * @return
  37 + */
  38 + public static String getCurrentTime() {
  39 + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
  40 + return sdf.format(System.currentTimeMillis());
  41 + }
  42 +
  43 +
  44 +}
... ...
app/src/main/res/drawable-hdpi/keybord.png 0 → 100644

1.07 KB

app/src/main/res/drawable-hdpi/pic.png 0 → 100644

1.09 KB

app/src/main/res/drawable-hdpi/record_bottom.png 0 → 100644

5.5 KB

app/src/main/res/drawable-hdpi/record_top.png 0 → 100644

6.13 KB

app/src/main/res/drawable-hdpi/send_cancel.png 0 → 100644

788 Bytes

app/src/main/res/drawable-hdpi/voice.png 0 → 100644

1.2 KB

app/src/main/res/drawable-hdpi/voice_bg_left.png 0 → 100644

618 Bytes

app/src/main/res/drawable-hdpi/voice_bg_right.png 0 → 100644

607 Bytes

app/src/main/res/drawable-hdpi/voice_msg_left.png deleted 100644 → 0

1.2 KB

app/src/main/res/drawable-hdpi/voice_msg_right.9.png deleted 100644 → 0

1.19 KB

app/src/main/res/drawable/record_microphone.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  3 + <item android:id="@android:id/background" android:drawable="@drawable/record_top" />
  4 + <item android:id="@android:id/progress" >
  5 + <clip android:drawable="@drawable/record_bottom" android:gravity="bottom" android:clipOrientation="vertical" />
  6 + </item>
  7 +</layer-list>
0 8 \ No newline at end of file
... ...
app/src/main/res/drawable/record_microphone_bj.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:shape="rectangle">
  4 +
  5 + <corners
  6 + android:radius="8dp" />
  7 +
  8 + <solid
  9 + android:color="@color/colorGray" />
  10 +
  11 +</shape>
0 12 \ No newline at end of file
... ...
app/src/main/res/drawable/voice_bg.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +
  3 +<shape xmlns:android="http://schemas.android.com/apk/res/android">
  4 + <solid android:color="#ffffff" />
  5 + <corners
  6 + android:bottomLeftRadius="10dp"
  7 + android:bottomRightRadius="10dp"
  8 + android:topLeftRadius="10dp"
  9 + android:topRightRadius="10dp" />
  10 + <stroke
  11 + android:width="1dp"
  12 + android:color="#8a8a8a" />
  13 +</shape>
0 14 \ No newline at end of file
... ...
app/src/main/res/layout/activity_groupchat.xml
... ... @@ -11,7 +11,8 @@
11 11 android:layout_alignParentLeft="true"
12 12 android:layout_alignParentStart="true"
13 13 android:layout_alignParentTop="true"
14   - android:visibility="visible">
  14 + android:visibility="visible"
  15 + android:clickable="true">
15 16  
16 17 <LinearLayout
17 18 android:id="@+id/listVIewTop"
... ... @@ -30,7 +31,7 @@
30 31 <android.support.v7.widget.RecyclerView
31 32 android:id="@+id/chat_list_viewOne"
32 33 android:layout_width="fill_parent"
33   - android:layout_height="170dp"
  34 + android:layout_height="200dp"
34 35 android:layout_above="@+id/edit_layout"
35 36 android:divider="@null"
36 37 android:fastScrollEnabled="true"
... ... @@ -45,13 +46,39 @@
45 46 android:layout_alignParentBottom="true"
46 47 android:orientation="horizontal">
47 48  
  49 + <ImageView
  50 + android:id="@+id/keybord"
  51 + android:layout_width="0dp"
  52 + android:layout_height="wrap_content"
  53 + android:layout_gravity="center_vertical"
  54 + android:layout_weight="0.1"
  55 + android:src="@drawable/voice" />
  56 +
48 57 <EditText
49 58 android:id="@+id/message_content"
50 59 android:layout_width="0dp"
51 60 android:layout_height="wrap_content"
52 61 android:layout_gravity="center"
53   - android:layout_weight="0.7" />
  62 + android:layout_weight="0.6" />
54 63  
  64 + <Button
  65 + android:id="@+id/send_voice"
  66 + android:layout_width="0dp"
  67 + android:layout_height="40dp"
  68 + android:layout_margin="10dp"
  69 + android:layout_weight="0.6"
  70 + android:background="@drawable/voice_bg"
  71 + android:text="按住说话"
  72 + android:visibility="gone" />
  73 +
  74 + <ImageView
  75 + android:id="@+id/ima_send"
  76 + android:layout_width="0dp"
  77 + android:layout_height="wrap_content"
  78 + android:layout_gravity="center_vertical"
  79 + android:layout_weight="0.1"
  80 + android:src="@drawable/pic"
  81 + android:visibility="visible"/>
55 82  
56 83 <Button
57 84 android:id="@+id/send_messageOne"
... ... @@ -59,7 +86,8 @@
59 86 android:layout_height="wrap_content"
60 87 android:layout_gravity="center"
61 88 android:layout_weight="0.2"
62   - android:text="发送" />
  89 + android:text="发送"
  90 + android:visibility="gone"/>
63 91  
64 92 </LinearLayout>
65 93  
... ... @@ -80,18 +108,11 @@
80 108 android:layout_height="wrap_content"
81 109 android:text="加入聊天室" />
82 110  
83   - <Button
84   - android:id="@+id/ima_send"
85   - android:layout_width="wrap_content"
86   - android:layout_height="wrap_content"
87   - android:text="图片" />
88   -
89   - <Button
90   - android:id="@+id/voice_send"
91   - android:layout_width="wrap_content"
92   - android:layout_height="wrap_content"
93   - android:text="语音" />
94   -
  111 + <!--<Button-->
  112 + <!--android:id="@+id/ima_send"-->
  113 + <!--android:layout_width="wrap_content"-->
  114 + <!--android:layout_height="wrap_content"-->
  115 + <!--android:text="图片" />-->
95 116  
96 117 <Button
97 118 android:id="@+id/exit_chat1"
... ...
app/src/main/res/layout/imag_layout_item_oppsite.xml
... ... @@ -2,7 +2,9 @@
2 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 3 android:layout_width="match_parent"
4 4 android:layout_height="match_parent"
5   - android:orientation="vertical">
  5 + android:orientation="vertical"
  6 + android:paddingBottom="10dp"
  7 + android:paddingTop="10dp">
6 8  
7 9  
8 10 <RelativeLayout
... ...
app/src/main/res/layout/imag_layout_item_user.xml
... ... @@ -2,7 +2,9 @@
2 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 3 android:layout_width="match_parent"
4 4 android:layout_height="match_parent"
5   - android:orientation="vertical">
  5 + android:orientation="vertical"
  6 + android:paddingBottom="10dp"
  7 + android:paddingTop="10dp">
6 8  
7 9 <RelativeLayout
8 10 android:layout_width="wrap_content"
... ...
app/src/main/res/layout/layout_microphone.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:orientation="vertical">
  6 +
  7 + <LinearLayout
  8 + android:id="@+id/send_layout"
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:background="@drawable/record_microphone_bj"
  12 + android:gravity="center"
  13 + android:orientation="vertical"
  14 + android:padding="16dp"
  15 + android:layout_centerInParent="true">
  16 +
  17 + <ImageView
  18 + android:id="@+id/iv_recording_icon"
  19 + android:layout_width="48dp"
  20 + android:layout_height="48dp"
  21 + android:src="@drawable/record_microphone" />
  22 +
  23 + <TextView
  24 + android:id="@+id/tv_recording_time"
  25 + android:layout_width="114dp"
  26 + android:layout_height="wrap_content"
  27 + android:layout_marginTop="6dp"
  28 + android:gravity="center"
  29 + android:text="00:00"
  30 + android:textColor="#FFFFFF"
  31 + android:textSize="16sp" />
  32 +
  33 + <TextView
  34 + android:layout_width="wrap_content"
  35 + android:layout_height="wrap_content"
  36 + android:text="上滑取消发送"
  37 + android:textColor="@android:color/white"
  38 + android:textSize="16sp" />
  39 + </LinearLayout>
  40 +
  41 + <LinearLayout
  42 + android:id="@+id/cancel_send_layout"
  43 + android:layout_width="wrap_content"
  44 + android:layout_height="wrap_content"
  45 + android:background="@drawable/record_microphone_bj"
  46 + android:gravity="center"
  47 + android:orientation="vertical"
  48 + android:padding="16dp"
  49 + android:visibility="gone"
  50 + android:layout_centerInParent="true">
  51 +
  52 + <ImageView
  53 + android:layout_width="48dp"
  54 + android:layout_height="48dp"
  55 + android:src="@drawable/send_cancel" />
  56 +
  57 + <TextView
  58 + android:layout_width="wrap_content"
  59 + android:layout_height="wrap_content"
  60 + android:text="松开手指,取消发送"
  61 + android:textColor="#ffffff"
  62 + android:textSize="16sp" />
  63 + </LinearLayout>
  64 +</RelativeLayout>
0 65 \ No newline at end of file
... ...
app/src/main/res/layout/string_layout_item_oppsite.xml
... ... @@ -2,7 +2,9 @@
2 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 3 android:layout_width="wrap_content"
4 4 android:layout_height="wrap_content"
5   - android:orientation="vertical">
  5 + android:orientation="vertical"
  6 + android:paddingTop="10dp"
  7 + android:paddingBottom="10dp">
6 8  
7 9 <RelativeLayout
8 10 android:id="@+id/re_chat_room"
... ... @@ -25,7 +27,8 @@
25 27 android:layout_toRightOf="@id/user_name"
26 28 android:text="vfgfgf"
27 29 android:textColor="@android:color/black"
28   - android:textSize="15sp" />
  30 + android:textSize="15sp"
  31 + android:layout_marginLeft="5dp"/>
29 32 </RelativeLayout>
30 33  
31 34 </RelativeLayout>
32 35 \ No newline at end of file
... ...
app/src/main/res/layout/string_layout_item_user.xml
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 3 android:layout_width="wrap_content"
4   - android:layout_height="wrap_content">
  4 + android:layout_height="wrap_content"
  5 + android:paddingBottom="10dp"
  6 + android:paddingTop="10dp">
5 7  
6 8 <RelativeLayout
7 9 android:id="@+id/re_chat_room"
... ... @@ -25,7 +27,8 @@
25 27 android:layout_toLeftOf="@id/user_name"
26 28 android:text="vfgfgf"
27 29 android:textColor="@android:color/black"
28   - android:textSize="15sp" />
  30 + android:textSize="15sp"
  31 + android:layout_marginRight="5dp"/>
29 32 </RelativeLayout>
30 33  
31 34  
... ...
app/src/main/res/layout/voice_layout_item_oppsite.xml
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 3 android:layout_width="wrap_content"
4   - android:layout_height="wrap_content">
  4 + android:layout_height="wrap_content"
  5 + android:paddingBottom="10dp"
  6 + android:paddingTop="10dp">
5 7  
6 8  
7 9 <RelativeLayout
... ... @@ -16,12 +18,20 @@
16 18 android:layout_centerVertical="true"
17 19 android:text="游客" />
18 20  
19   - <ImageView
  21 + <TextView
20 22 android:id="@+id/voice_content"
21 23 android:layout_width="wrap_content"
22   - android:layout_height="wrap_content"
  24 + android:layout_height="50dp"
23 25 android:layout_toRightOf="@+id/voice_user_name"
24   - android:src="@drawable/voice_msg_left" />
  26 + android:background="@drawable/voice_bg_left"
  27 + android:layout_marginLeft="5dp"/>
  28 +
  29 + <TextView
  30 + android:id="@+id/voice_duration"
  31 + android:layout_width="wrap_content"
  32 + android:layout_height="wrap_content"
  33 + android:layout_centerVertical="true"
  34 + android:layout_toRightOf="@id/voice_content" />
25 35  
26 36  
27 37 </RelativeLayout>
... ...
app/src/main/res/layout/voice_layout_item_user.xml
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 3 android:layout_width="wrap_content"
4   - android:layout_height="wrap_content">
  4 + android:layout_height="wrap_content"
  5 + android:paddingBottom="10dp"
  6 + android:paddingTop="10dp">
5 7  
6 8 <RelativeLayout
7 9 android:layout_width="wrap_content"
... ... @@ -15,12 +17,20 @@
15 17 android:layout_centerVertical="true"
16 18 android:text="游客" />
17 19  
18   - <ImageView
  20 + <TextView
19 21 android:id="@+id/voice_content"
20 22 android:layout_width="wrap_content"
21   - android:layout_height="wrap_content"
  23 + android:layout_height="50dp"
22 24 android:layout_toLeftOf="@+id/voice_user_name"
23   - android:src="@drawable/voice_msg_right" />
  25 + android:background="@drawable/voice_bg_right"
  26 + android:layout_marginRight="5dp"/>
  27 +
  28 + <TextView
  29 + android:id="@+id/voice_duration"
  30 + android:layout_width="wrap_content"
  31 + android:layout_height="wrap_content"
  32 + android:layout_centerVertical="true"
  33 + android:layout_toLeftOf="@id/voice_content" />
24 34  
25 35 </RelativeLayout>
26 36  
... ...
app/src/main/res/values/colors.xml
... ... @@ -3,4 +3,5 @@
3 3 <color name="colorPrimary">#3F51B5</color>
4 4 <color name="colorPrimaryDark">#303F9F</color>
5 5 <color name="colorAccent">#FF4081</color>
  6 + <color name="colorGray">#33000000</color>
6 7 </resources>
... ...