Commit dd175e595daff5b537a20766b78627f028edffc5
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,7 +2,6 @@ | ||
| 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | package="com.cnlive.im"> | 3 | package="com.cnlive.im"> |
| 4 | 4 | ||
| 5 | - | ||
| 6 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | 5 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
| 7 | <uses-permission android:name="android.permission.INTERNET" /> | 6 | <uses-permission android:name="android.permission.INTERNET" /> |
| 8 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | 7 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
| @@ -17,44 +16,37 @@ | @@ -17,44 +16,37 @@ | ||
| 17 | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | 16 | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> |
| 18 | 17 | ||
| 19 | <application | 18 | <application |
| 20 | - android:name="com.cnlive.im.CNLiveApplication" | 19 | + android:name=".CNLiveApplication" |
| 21 | android:allowBackup="true" | 20 | android:allowBackup="true" |
| 22 | android:icon="@mipmap/ic_launcher" | 21 | android:icon="@mipmap/ic_launcher" |
| 23 | android:label="@string/app_name" | 22 | android:label="@string/app_name" |
| 24 | android:supportsRtl="true" | 23 | android:supportsRtl="true" |
| 25 | android:theme="@style/AppTheme"> | 24 | android:theme="@style/AppTheme"> |
| 26 | - <activity android:name="com.cnlive.im.ui.MainActivity"> | 25 | + <activity android:name=".ui.MainActivity"> |
| 27 | <intent-filter> | 26 | <intent-filter> |
| 28 | <action android:name="android.intent.action.MAIN" /> | 27 | <action android:name="android.intent.action.MAIN" /> |
| 29 | 28 | ||
| 30 | <category android:name="android.intent.category.LAUNCHER" /> | 29 | <category android:name="android.intent.category.LAUNCHER" /> |
| 31 | </intent-filter> | 30 | </intent-filter> |
| 32 | </activity> | 31 | </activity> |
| 33 | - | ||
| 34 | - | ||
| 35 | <activity | 32 | <activity |
| 36 | - android:name="com.cnlive.im.ui.ChatRoomActivity" | 33 | + android:name=".ui.ChatRoomActivity" |
| 37 | android:theme="@style/Theme.AppCompat.Light.NoActionBar" | 34 | android:theme="@style/Theme.AppCompat.Light.NoActionBar" |
| 38 | - android:windowSoftInputMode="adjustResize"></activity> | ||
| 39 | - | 35 | + android:windowSoftInputMode="adjustResize" /> |
| 40 | <activity | 36 | <activity |
| 41 | - android:name="com.cnlive.im.ui.LoGinActivity" | 37 | + android:name=".ui.LoGinActivity" |
| 42 | android:screenOrientation="portrait" /> | 38 | android:screenOrientation="portrait" /> |
| 43 | - | ||
| 44 | <activity | 39 | <activity |
| 45 | android:name=".ui.UserLoginActivity" | 40 | android:name=".ui.UserLoginActivity" |
| 46 | android:screenOrientation="portrait" /> | 41 | android:screenOrientation="portrait" /> |
| 47 | - | ||
| 48 | <activity | 42 | <activity |
| 49 | - android:name="com.cnlive.im.ui.CommentActivity" | 43 | + android:name=".ui.CommentActivity" |
| 50 | android:screenOrientation="portrait" /> | 44 | android:screenOrientation="portrait" /> |
| 51 | 45 | ||
| 52 | - | ||
| 53 | <service | 46 | <service |
| 54 | android:name="io.rong.imlib.ipc.RongService" | 47 | android:name="io.rong.imlib.ipc.RongService" |
| 55 | android:exported="true" | 48 | android:exported="true" |
| 56 | android:process=":ipc" /> | 49 | android:process=":ipc" /> |
| 57 | - | ||
| 58 | <service | 50 | <service |
| 59 | android:name="io.rong.imlib.ReConnectService" | 51 | android:name="io.rong.imlib.ReConnectService" |
| 60 | android:exported="true" /> | 52 | android:exported="true" /> |
| @@ -62,10 +54,10 @@ | @@ -62,10 +54,10 @@ | ||
| 62 | <receiver | 54 | <receiver |
| 63 | android:name="io.rong.imlib.ConnectChangeReceiver" | 55 | android:name="io.rong.imlib.ConnectChangeReceiver" |
| 64 | android:exported="true" /> | 56 | android:exported="true" /> |
| 65 | - | ||
| 66 | <receiver | 57 | <receiver |
| 67 | android:name="io.rong.imlib.HeartbeatReceiver" | 58 | android:name="io.rong.imlib.HeartbeatReceiver" |
| 68 | android:process=":ipc" /> | 59 | android:process=":ipc" /> |
| 60 | + | ||
| 69 | </application> | 61 | </application> |
| 70 | 62 | ||
| 71 | </manifest> | 63 | </manifest> |
| 72 | \ No newline at end of file | 64 | \ No newline at end of file |
app/src/main/java/com/cnlive/im/adapter/ChatRoomAdpter.java
| 1 | package com.cnlive.im.adapter; | 1 | package com.cnlive.im.adapter; |
| 2 | 2 | ||
| 3 | import android.content.Context; | 3 | import android.content.Context; |
| 4 | +import android.database.Cursor; | ||
| 4 | import android.graphics.Color; | 5 | import android.graphics.Color; |
| 5 | import android.net.Uri; | 6 | import android.net.Uri; |
| 7 | +import android.provider.ContactsContract; | ||
| 8 | +import android.provider.MediaStore; | ||
| 6 | import android.support.v7.widget.RecyclerView; | 9 | import android.support.v7.widget.RecyclerView; |
| 10 | +import android.util.Log; | ||
| 7 | import android.view.LayoutInflater; | 11 | import android.view.LayoutInflater; |
| 8 | import android.view.View; | 12 | import android.view.View; |
| 9 | import android.view.ViewGroup; | 13 | import android.view.ViewGroup; |
| 14 | +import android.view.WindowManager; | ||
| 10 | import android.widget.ImageView; | 15 | import android.widget.ImageView; |
| 16 | +import android.widget.LinearLayout; | ||
| 11 | import android.widget.TextView; | 17 | import android.widget.TextView; |
| 12 | 18 | ||
| 13 | import com.bumptech.glide.Glide; | 19 | import com.bumptech.glide.Glide; |
| @@ -18,6 +24,12 @@ import com.cnlive.im.mode.ImagMessage; | @@ -18,6 +24,12 @@ import com.cnlive.im.mode.ImagMessage; | ||
| 18 | import com.cnlive.im.mode.StringMessage; | 24 | import com.cnlive.im.mode.StringMessage; |
| 19 | import com.cnlive.im.mode.VoiceMessage; | 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 | * @author 陈硕 | 34 | * @author 陈硕 |
| 23 | * @time 2017/7/14 14:35 | 35 | * @time 2017/7/14 14:35 |
| @@ -100,6 +112,9 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { | @@ -100,6 +112,9 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { | ||
| 100 | Object o = mItems.get(position); | 112 | Object o = mItems.get(position); |
| 101 | ImagMessage o1 = (ImagMessage) o; | 113 | ImagMessage o1 = (ImagMessage) o; |
| 102 | holder1.ima_user_name.setTextColor(Color.parseColor("#d61d0c")); | 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 | Glide.with(mContext).load(o1.getCnImgMessage().getRemoteUri()).into(holder1.img_content); | 118 | Glide.with(mContext).load(o1.getCnImgMessage().getRemoteUri()).into(holder1.img_content); |
| 104 | holder1.ima_user_name.setText(o1.getCnImgMessage().getUserInfo().getUserName()); | 119 | holder1.ima_user_name.setText(o1.getCnImgMessage().getUserInfo().getUserName()); |
| 105 | } else if (holder instanceof VoiceMessageHolder) { | 120 | } else if (holder instanceof VoiceMessageHolder) { |
| @@ -108,6 +123,8 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { | @@ -108,6 +123,8 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { | ||
| 108 | VoiceMessage o1 = (VoiceMessage) o; | 123 | VoiceMessage o1 = (VoiceMessage) o; |
| 109 | holder1.voice_user_name.setText(o1.getCnVoiceMessage().getUserInfo().getUserName()); | 124 | holder1.voice_user_name.setText(o1.getCnVoiceMessage().getUserInfo().getUserName()); |
| 110 | final Uri voiceUri = o1.getCnVoiceMessage().getVoiceUri(); | 125 | final Uri voiceUri = o1.getCnVoiceMessage().getVoiceUri(); |
| 126 | + int duration = o1.getCnVoiceMessage().getVoiceTime(); | ||
| 127 | + holder1.voice_duration.setText(String.valueOf(duration).concat("\"")); | ||
| 111 | holder1.itemView.setOnClickListener(new View.OnClickListener() { | 128 | holder1.itemView.setOnClickListener(new View.OnClickListener() { |
| 112 | @Override | 129 | @Override |
| 113 | public void onClick(View v) { | 130 | public void onClick(View v) { |
| @@ -146,15 +163,15 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { | @@ -146,15 +163,15 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { | ||
| 146 | 163 | ||
| 147 | 164 | ||
| 148 | private TextView voice_user_name; | 165 | private TextView voice_user_name; |
| 149 | - private ImageView voice_content; | 166 | + private TextView voice_content; |
| 167 | + private TextView voice_duration; | ||
| 150 | 168 | ||
| 151 | public VoiceMessageHolder(View itemView) { | 169 | public VoiceMessageHolder(View itemView) { |
| 152 | super(itemView); | 170 | super(itemView); |
| 153 | voice_user_name = (TextView) itemView.findViewById(R.id.voice_user_name); | 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,23 +2,37 @@ package com.cnlive.im.ui; | ||
| 2 | 2 | ||
| 3 | import android.Manifest; | 3 | import android.Manifest; |
| 4 | import android.app.Activity; | 4 | import android.app.Activity; |
| 5 | +import android.content.ContentResolver; | ||
| 6 | +import android.content.Context; | ||
| 5 | import android.content.Intent; | 7 | import android.content.Intent; |
| 6 | import android.content.pm.PackageManager; | 8 | import android.content.pm.PackageManager; |
| 9 | +import android.database.Cursor; | ||
| 7 | import android.net.Uri; | 10 | import android.net.Uri; |
| 8 | import android.os.Build; | 11 | import android.os.Build; |
| 9 | import android.os.Bundle; | 12 | import android.os.Bundle; |
| 10 | import android.os.Handler; | 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 | import android.support.v4.content.ContextCompat; | 18 | import android.support.v4.content.ContextCompat; |
| 12 | import android.support.v7.app.AppCompatActivity; | 19 | import android.support.v7.app.AppCompatActivity; |
| 13 | import android.support.v7.widget.LinearLayoutManager; | 20 | import android.support.v7.widget.LinearLayoutManager; |
| 14 | import android.support.v7.widget.RecyclerView; | 21 | import android.support.v7.widget.RecyclerView; |
| 22 | +import android.text.Editable; | ||
| 23 | +import android.text.TextUtils; | ||
| 24 | +import android.text.TextWatcher; | ||
| 15 | import android.util.Log; | 25 | import android.util.Log; |
| 26 | +import android.view.Gravity; | ||
| 16 | import android.view.MotionEvent; | 27 | import android.view.MotionEvent; |
| 17 | import android.view.View; | 28 | import android.view.View; |
| 29 | +import android.view.inputmethod.InputMethodManager; | ||
| 18 | import android.widget.Button; | 30 | import android.widget.Button; |
| 19 | import android.widget.EditText; | 31 | import android.widget.EditText; |
| 32 | +import android.widget.ImageView; | ||
| 20 | import android.widget.LinearLayout; | 33 | import android.widget.LinearLayout; |
| 21 | import android.widget.RelativeLayout; | 34 | import android.widget.RelativeLayout; |
| 35 | +import android.widget.TextView; | ||
| 22 | import android.widget.Toast; | 36 | import android.widget.Toast; |
| 23 | 37 | ||
| 24 | import com.cnlive.im.R; | 38 | import com.cnlive.im.R; |
| @@ -27,8 +41,11 @@ import com.cnlive.im.adapter.base.VoiceItemClickListener; | @@ -27,8 +41,11 @@ import com.cnlive.im.adapter.base.VoiceItemClickListener; | ||
| 27 | import com.cnlive.im.mode.ImagMessage; | 41 | import com.cnlive.im.mode.ImagMessage; |
| 28 | import com.cnlive.im.mode.StringMessage; | 42 | import com.cnlive.im.mode.StringMessage; |
| 29 | import com.cnlive.im.mode.VoiceMessage; | 43 | import com.cnlive.im.mode.VoiceMessage; |
| 44 | +import com.cnlive.im.util.AudioRecordUtil; | ||
| 30 | import com.cnlive.im.util.MediaRecorderUtil; | 45 | import com.cnlive.im.util.MediaRecorderUtil; |
| 31 | import com.cnlive.im.util.MessageType; | 46 | import com.cnlive.im.util.MessageType; |
| 47 | +import com.cnlive.im.util.PlayerUtil; | ||
| 48 | +import com.cnlive.im.util.TimeUtils; | ||
| 32 | import com.cnlive.libs.util.chat.ChatUtil; | 49 | import com.cnlive.libs.util.chat.ChatUtil; |
| 33 | import com.cnlive.libs.util.chat.base.IChat; | 50 | import com.cnlive.libs.util.chat.base.IChat; |
| 34 | import com.cnlive.libs.util.chat.model.CNImgMessage; | 51 | import com.cnlive.libs.util.chat.model.CNImgMessage; |
| @@ -38,15 +55,18 @@ import com.cnlive.libs.util.chat.model.CNVoiceMessage; | @@ -38,15 +55,18 @@ import com.cnlive.libs.util.chat.model.CNVoiceMessage; | ||
| 38 | 55 | ||
| 39 | import org.json.JSONException; | 56 | import org.json.JSONException; |
| 40 | 57 | ||
| 58 | +import java.io.LineNumberReader; | ||
| 41 | import java.util.ArrayList; | 59 | import java.util.ArrayList; |
| 42 | 60 | ||
| 61 | +import static android.R.id.edit; | ||
| 62 | + | ||
| 43 | 63 | ||
| 44 | /** | 64 | /** |
| 45 | * @author 陈硕 | 65 | * @author 陈硕 |
| 46 | * @time 2017/3/7 14:36 | 66 | * @time 2017/3/7 14:36 |
| 47 | * @desc ${TODD} | 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 | private static final String TAG = "ChatRoomActivity"; | 70 | private static final String TAG = "ChatRoomActivity"; |
| 51 | private ArrayList<Object> groupChatOneListMy; | 71 | private ArrayList<Object> groupChatOneListMy; |
| 52 | private String roomIdOne = "ChatRoom05"; | 72 | private String roomIdOne = "ChatRoom05"; |
| @@ -57,32 +77,55 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | @@ -57,32 +77,55 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 57 | private Button foundChatBtn; | 77 | private Button foundChatBtn; |
| 58 | private Handler mHandler; | 78 | private Handler mHandler; |
| 59 | private RelativeLayout re_chat; | 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 | private Button exit_chat1; | 82 | private Button exit_chat1; |
| 63 | public static String user_name_string; | 83 | public static String user_name_string; |
| 64 | private boolean isUserLogin = false; | 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 | public static final int IMG_FROM_PICTURE = 0x1001; | 101 | public static final int IMG_FROM_PICTURE = 0x1001; |
| 70 | public static final int VOICE = 0x1002; | 102 | public static final int VOICE = 0x1002; |
| 71 | public static final int PICTURE_REQUEST_CODE = 0x1003; | 103 | public static final int PICTURE_REQUEST_CODE = 0x1003; |
| 72 | public static final int VOICE_REQUEST_CODE = 0x1004; | 104 | public static final int VOICE_REQUEST_CODE = 0x1004; |
| 73 | - private MediaRecorderUtil mediaRecorderUtil; | ||
| 74 | private long l; | 105 | private long l; |
| 75 | int i; | 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 | @Override | 118 | @Override |
| 78 | protected void onCreate(Bundle savedInstanceState) { | 119 | protected void onCreate(Bundle savedInstanceState) { |
| 79 | super.onCreate(savedInstanceState); | 120 | super.onCreate(savedInstanceState); |
| 80 | //取消状态栏 | 121 | //取消状态栏 |
| 81 | setContentView(R.layout.activity_groupchat); | 122 | setContentView(R.layout.activity_groupchat); |
| 123 | + context = this; | ||
| 82 | initUI(); | 124 | initUI(); |
| 125 | + mAudioRecordUtil = new AudioRecordUtil(); | ||
| 126 | + mAudioRecordUtil.setOnAudioStatusUpdateListener(onAudioStatusUpdateListener); | ||
| 83 | //设置监听 | 127 | //设置监听 |
| 84 | mHandler = new Handler(); | 128 | mHandler = new Handler(); |
| 85 | - mediaRecorderUtil = new MediaRecorderUtil(); | ||
| 86 | ChatUtil.setOnConnectStatusListener(connectStatusListener); | 129 | ChatUtil.setOnConnectStatusListener(connectStatusListener); |
| 87 | ChatUtil.setOnChatRoomActionListener(chatRoomActionListener); | 130 | ChatUtil.setOnChatRoomActionListener(chatRoomActionListener); |
| 88 | ChatUtil.setOnReceiveMessageListener(receiveMessageListener); | 131 | ChatUtil.setOnReceiveMessageListener(receiveMessageListener); |
| @@ -93,21 +136,30 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | @@ -93,21 +136,30 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 93 | if (user_name_string != null) | 136 | if (user_name_string != null) |
| 94 | ChatUtil.login(new CNUserInfo(user_id_string, user_name_string, ""), connectListener); | 137 | ChatUtil.login(new CNUserInfo(user_id_string, user_name_string, ""), connectListener); |
| 95 | else ChatUtil.logOut(connectListener); | 138 | else ChatUtil.logOut(connectListener); |
| 139 | + requestPermission(); | ||
| 140 | + playerUtil = new PlayerUtil(this); | ||
| 96 | 141 | ||
| 97 | } | 142 | } |
| 98 | 143 | ||
| 99 | 144 | ||
| 100 | private void initUI() { | 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 | exit_chat1 = (Button) findViewById(R.id.exit_chat1); | 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 | re_chat = (RelativeLayout) findViewById(R.id.re_chat); | 158 | re_chat = (RelativeLayout) findViewById(R.id.re_chat); |
| 108 | foundChatBtn = (Button) findViewById(R.id.creatChat); | 159 | foundChatBtn = (Button) findViewById(R.id.creatChat); |
| 109 | listViewOne = (RecyclerView) findViewById(R.id.chat_list_viewOne); | 160 | listViewOne = (RecyclerView) findViewById(R.id.chat_list_viewOne); |
| 110 | editText = (EditText) findViewById(R.id.message_content); | 161 | editText = (EditText) findViewById(R.id.message_content); |
| 162 | + editText.addTextChangedListener(textWatcher); | ||
| 111 | send_messageOneBtn = (Button) findViewById(R.id.send_messageOne); | 163 | send_messageOneBtn = (Button) findViewById(R.id.send_messageOne); |
| 112 | ima_send.setOnClickListener(this); | 164 | ima_send.setOnClickListener(this); |
| 113 | exit_chat1.setOnClickListener(this); | 165 | exit_chat1.setOnClickListener(this); |
| @@ -118,7 +170,15 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | @@ -118,7 +170,15 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 118 | chatListAdapterOne.setonVoiceItemClickListener(this); | 170 | chatListAdapterOne.setonVoiceItemClickListener(this); |
| 119 | listViewOne.setLayoutManager(new LinearLayoutManager(ChatRoomActivity.this)); | 171 | listViewOne.setLayoutManager(new LinearLayoutManager(ChatRoomActivity.this)); |
| 120 | listViewOne.setAdapter(chatListAdapterOne); | 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,7 +186,6 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 126 | /** | 186 | /** |
| 127 | * 发送消息监听 | 187 | * 发送消息监听 |
| 128 | */ | 188 | */ |
| 129 | - | ||
| 130 | private IChat.OnSendMessageListener sendMessageListener = new IChat.OnSendMessageListener() { | 189 | private IChat.OnSendMessageListener sendMessageListener = new IChat.OnSendMessageListener() { |
| 131 | @Override | 190 | @Override |
| 132 | public void onAttached(Object o) { | 191 | public void onAttached(Object o) { |
| @@ -148,14 +207,20 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | @@ -148,14 +207,20 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 148 | CNVoiceMessage o1 = (CNVoiceMessage) o; | 207 | CNVoiceMessage o1 = (CNVoiceMessage) o; |
| 149 | VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, true); | 208 | VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, true); |
| 150 | chatListAdapterOne.addItem(voiceMessage); | 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 | @Override | 219 | @Override |
| 157 | public void onError(Object o, int i, String s) { | 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,6 +251,7 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 186 | VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, false); | 251 | VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, false); |
| 187 | chatListAdapterOne.addItem(voiceMessage); | 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,41 +348,24 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 282 | case R.id.ima_send: | 348 | case R.id.ima_send: |
| 283 | fromPicture(); | 349 | fromPicture(); |
| 284 | break; | 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 | public void fromPicture() { | 370 | public void fromPicture() { |
| 322 | if (Build.VERSION.SDK_INT >= 23) { | 371 | if (Build.VERSION.SDK_INT >= 23) { |
| @@ -336,31 +385,8 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | @@ -336,31 +385,8 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 336 | private void toIntentPicture() { | 385 | private void toIntentPicture() { |
| 337 | Intent intent = new Intent(); | 386 | Intent intent = new Intent(); |
| 338 | intent.setType("image/*"); | 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,7 +396,19 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 370 | if (resultCode == Activity.RESULT_OK) { | 396 | if (resultCode == Activity.RESULT_OK) { |
| 371 | switch (requestCode) { | 397 | switch (requestCode) { |
| 372 | case IMG_FROM_PICTURE: | 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 | ChatUtil.sendImaMessage(IChat.CHATROOM, roomIdOne, uri, uri, sendMessageListener); | 412 | ChatUtil.sendImaMessage(IChat.CHATROOM, roomIdOne, uri, uri, sendMessageListener); |
| 375 | break; | 413 | break; |
| 376 | 414 | ||
| @@ -406,53 +444,169 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | @@ -406,53 +444,169 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL | ||
| 406 | 444 | ||
| 407 | 445 | ||
| 408 | @Override | 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 | } else { | 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,7 +50,7 @@ public class UserLoginActivity extends AppCompatActivity implements View.OnClick | ||
| 50 | doIntentChatRoom(ChatRoomActivity.class); | 50 | doIntentChatRoom(ChatRoomActivity.class); |
| 51 | break; | 51 | break; |
| 52 | case R.id.private_chat: | 52 | case R.id.private_chat: |
| 53 | - // doIntentChatRoom(PrivateChatActivity.class); | 53 | + doIntentChatRoom(PrivateChatActivity.class); |
| 54 | 54 | ||
| 55 | break; | 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
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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 14 | \ No newline at end of file |
app/src/main/res/layout/activity_groupchat.xml
| @@ -11,7 +11,8 @@ | @@ -11,7 +11,8 @@ | ||
| 11 | android:layout_alignParentLeft="true" | 11 | android:layout_alignParentLeft="true" |
| 12 | android:layout_alignParentStart="true" | 12 | android:layout_alignParentStart="true" |
| 13 | android:layout_alignParentTop="true" | 13 | android:layout_alignParentTop="true" |
| 14 | - android:visibility="visible"> | 14 | + android:visibility="visible" |
| 15 | + android:clickable="true"> | ||
| 15 | 16 | ||
| 16 | <LinearLayout | 17 | <LinearLayout |
| 17 | android:id="@+id/listVIewTop" | 18 | android:id="@+id/listVIewTop" |
| @@ -30,7 +31,7 @@ | @@ -30,7 +31,7 @@ | ||
| 30 | <android.support.v7.widget.RecyclerView | 31 | <android.support.v7.widget.RecyclerView |
| 31 | android:id="@+id/chat_list_viewOne" | 32 | android:id="@+id/chat_list_viewOne" |
| 32 | android:layout_width="fill_parent" | 33 | android:layout_width="fill_parent" |
| 33 | - android:layout_height="170dp" | 34 | + android:layout_height="200dp" |
| 34 | android:layout_above="@+id/edit_layout" | 35 | android:layout_above="@+id/edit_layout" |
| 35 | android:divider="@null" | 36 | android:divider="@null" |
| 36 | android:fastScrollEnabled="true" | 37 | android:fastScrollEnabled="true" |
| @@ -45,13 +46,39 @@ | @@ -45,13 +46,39 @@ | ||
| 45 | android:layout_alignParentBottom="true" | 46 | android:layout_alignParentBottom="true" |
| 46 | android:orientation="horizontal"> | 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 | <EditText | 57 | <EditText |
| 49 | android:id="@+id/message_content" | 58 | android:id="@+id/message_content" |
| 50 | android:layout_width="0dp" | 59 | android:layout_width="0dp" |
| 51 | android:layout_height="wrap_content" | 60 | android:layout_height="wrap_content" |
| 52 | android:layout_gravity="center" | 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 | <Button | 83 | <Button |
| 57 | android:id="@+id/send_messageOne" | 84 | android:id="@+id/send_messageOne" |
| @@ -59,7 +86,8 @@ | @@ -59,7 +86,8 @@ | ||
| 59 | android:layout_height="wrap_content" | 86 | android:layout_height="wrap_content" |
| 60 | android:layout_gravity="center" | 87 | android:layout_gravity="center" |
| 61 | android:layout_weight="0.2" | 88 | android:layout_weight="0.2" |
| 62 | - android:text="发送" /> | 89 | + android:text="发送" |
| 90 | + android:visibility="gone"/> | ||
| 63 | 91 | ||
| 64 | </LinearLayout> | 92 | </LinearLayout> |
| 65 | 93 | ||
| @@ -80,18 +108,11 @@ | @@ -80,18 +108,11 @@ | ||
| 80 | android:layout_height="wrap_content" | 108 | android:layout_height="wrap_content" |
| 81 | android:text="加入聊天室" /> | 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 | <Button | 117 | <Button |
| 97 | android:id="@+id/exit_chat1" | 118 | android:id="@+id/exit_chat1" |
app/src/main/res/layout/imag_layout_item_oppsite.xml
| @@ -2,7 +2,9 @@ | @@ -2,7 +2,9 @@ | ||
| 2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | android:layout_width="match_parent" | 3 | android:layout_width="match_parent" |
| 4 | android:layout_height="match_parent" | 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 | <RelativeLayout | 10 | <RelativeLayout |
app/src/main/res/layout/imag_layout_item_user.xml
| @@ -2,7 +2,9 @@ | @@ -2,7 +2,9 @@ | ||
| 2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | android:layout_width="match_parent" | 3 | android:layout_width="match_parent" |
| 4 | android:layout_height="match_parent" | 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 | <RelativeLayout | 9 | <RelativeLayout |
| 8 | android:layout_width="wrap_content" | 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 | \ No newline at end of file | 65 | \ No newline at end of file |
app/src/main/res/layout/string_layout_item_oppsite.xml
| @@ -2,7 +2,9 @@ | @@ -2,7 +2,9 @@ | ||
| 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | android:layout_width="wrap_content" | 3 | android:layout_width="wrap_content" |
| 4 | android:layout_height="wrap_content" | 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 | <RelativeLayout | 9 | <RelativeLayout |
| 8 | android:id="@+id/re_chat_room" | 10 | android:id="@+id/re_chat_room" |
| @@ -25,7 +27,8 @@ | @@ -25,7 +27,8 @@ | ||
| 25 | android:layout_toRightOf="@id/user_name" | 27 | android:layout_toRightOf="@id/user_name" |
| 26 | android:text="vfgfgf" | 28 | android:text="vfgfgf" |
| 27 | android:textColor="@android:color/black" | 29 | android:textColor="@android:color/black" |
| 28 | - android:textSize="15sp" /> | 30 | + android:textSize="15sp" |
| 31 | + android:layout_marginLeft="5dp"/> | ||
| 29 | </RelativeLayout> | 32 | </RelativeLayout> |
| 30 | 33 | ||
| 31 | </RelativeLayout> | 34 | </RelativeLayout> |
| 32 | \ No newline at end of file | 35 | \ No newline at end of file |
app/src/main/res/layout/string_layout_item_user.xml
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | android:layout_width="wrap_content" | 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 | <RelativeLayout | 8 | <RelativeLayout |
| 7 | android:id="@+id/re_chat_room" | 9 | android:id="@+id/re_chat_room" |
| @@ -25,7 +27,8 @@ | @@ -25,7 +27,8 @@ | ||
| 25 | android:layout_toLeftOf="@id/user_name" | 27 | android:layout_toLeftOf="@id/user_name" |
| 26 | android:text="vfgfgf" | 28 | android:text="vfgfgf" |
| 27 | android:textColor="@android:color/black" | 29 | android:textColor="@android:color/black" |
| 28 | - android:textSize="15sp" /> | 30 | + android:textSize="15sp" |
| 31 | + android:layout_marginRight="5dp"/> | ||
| 29 | </RelativeLayout> | 32 | </RelativeLayout> |
| 30 | 33 | ||
| 31 | 34 |
app/src/main/res/layout/voice_layout_item_oppsite.xml
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | android:layout_width="wrap_content" | 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 | <RelativeLayout | 9 | <RelativeLayout |
| @@ -16,12 +18,20 @@ | @@ -16,12 +18,20 @@ | ||
| 16 | android:layout_centerVertical="true" | 18 | android:layout_centerVertical="true" |
| 17 | android:text="游客" /> | 19 | android:text="游客" /> |
| 18 | 20 | ||
| 19 | - <ImageView | 21 | + <TextView |
| 20 | android:id="@+id/voice_content" | 22 | android:id="@+id/voice_content" |
| 21 | android:layout_width="wrap_content" | 23 | android:layout_width="wrap_content" |
| 22 | - android:layout_height="wrap_content" | 24 | + android:layout_height="50dp" |
| 23 | android:layout_toRightOf="@+id/voice_user_name" | 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 | </RelativeLayout> | 37 | </RelativeLayout> |
app/src/main/res/layout/voice_layout_item_user.xml
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | android:layout_width="wrap_content" | 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 | <RelativeLayout | 8 | <RelativeLayout |
| 7 | android:layout_width="wrap_content" | 9 | android:layout_width="wrap_content" |
| @@ -15,12 +17,20 @@ | @@ -15,12 +17,20 @@ | ||
| 15 | android:layout_centerVertical="true" | 17 | android:layout_centerVertical="true" |
| 16 | android:text="游客" /> | 18 | android:text="游客" /> |
| 17 | 19 | ||
| 18 | - <ImageView | 20 | + <TextView |
| 19 | android:id="@+id/voice_content" | 21 | android:id="@+id/voice_content" |
| 20 | android:layout_width="wrap_content" | 22 | android:layout_width="wrap_content" |
| 21 | - android:layout_height="wrap_content" | 23 | + android:layout_height="50dp" |
| 22 | android:layout_toLeftOf="@+id/voice_user_name" | 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 | </RelativeLayout> | 35 | </RelativeLayout> |
| 26 | 36 |
app/src/main/res/values/colors.xml
| @@ -3,4 +3,5 @@ | @@ -3,4 +3,5 @@ | ||
| 3 | <color name="colorPrimary">#3F51B5</color> | 3 | <color name="colorPrimary">#3F51B5</color> |
| 4 | <color name="colorPrimaryDark">#303F9F</color> | 4 | <color name="colorPrimaryDark">#303F9F</color> |
| 5 | <color name="colorAccent">#FF4081</color> | 5 | <color name="colorAccent">#FF4081</color> |
| 6 | + <color name="colorGray">#33000000</color> | ||
| 6 | </resources> | 7 | </resources> |