feat : module_room_chat

This commit is contained in:
eggmanQQQ2
2025-07-07 10:34:38 +08:00
parent ac07463f78
commit 424b73ce99
50 changed files with 4835 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
package com.chwl.app.room_chat;
public class TEMP {
}

View File

@@ -0,0 +1,341 @@
package com.chwl.app.room_chat.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.chwl.app.R;
import com.chwl.app.module_hall.team.HTeamDataManager;
import com.chwl.app.module_hall.team.activity.HTeamMemberListActivity;
import com.chwl.app.module_hall.team.adapter.HTeamMemberListAdapter;
import com.chwl.app.room_chat.event.ClickRootViewEvent;
import com.chwl.app.team.view.NimTeamMessageFragment;
import com.chwl.app.ui.im.avtivity.BaseMessageActivity;
import com.chwl.core.initial.InitialModel;
import com.chwl.core.initial.bean.InitInfo;
import com.chwl.core.level.UserLevelVo;
import com.chwl.core.module_hall.hall.bean.HTeamInfo;
import com.chwl.core.module_hall.team.HTeamModel;
import com.chwl.core.team.bean.TeamEvent;
import com.chwl.core.user.UserModel;
import com.chwl.core.user.bean.UserInfo;
import com.chwl.library.rxbus.RxBus;
import com.chwl.library.utils.ResUtil;
import com.netease.nim.uikit.api.NimUIKit;
import com.netease.nim.uikit.api.model.contact.ContactChangedObserver;
import com.netease.nim.uikit.api.model.team.TeamDataChangedObserver;
import com.netease.nim.uikit.api.model.team.TeamMemberDataChangedObserver;
import com.netease.nim.uikit.business.ait.AitManager;
import com.netease.nim.uikit.business.ait.event.AitContactActionEvent;
import com.netease.nim.uikit.business.ait.selector.AitContactSelectorActivity;
import com.netease.nim.uikit.business.session.constant.Extras;
import com.netease.nim.uikit.business.session.fragment.MessageFragment;
import com.netease.nim.uikit.business.session.module.list.MessageListPanelEx;
import com.netease.nim.uikit.impl.NimUIKitImpl;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.team.constant.TeamTypeEnum;
import com.netease.nimlib.sdk.team.model.Team;
import com.netease.nimlib.sdk.team.model.TeamMember;
import com.trello.rxlifecycle3.android.ActivityEvent;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import java.util.Objects;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* 厅群
* Created by lvzebiao on 2019/1/10.
*/
public class NimHallTeamRoomMessageActivity extends BaseMessageActivity {
private static final String TAG = "NimTeamMessageActivity";
private ImageView ivSetting;
private TextView tvTitle;
// model
private Team team;
/**
* 群详情
*/
private HTeamInfo hTeamInfo;
private View invalidTeamTipView;
private TextView invalidTeamTipText;
private NimTeamMessageFragment fragment;
public static void start(Context context, String tid) {
Intent intent = new Intent();
intent.putExtra(Extras.EXTRA_ACCOUNT, tid);
intent.putExtra(Extras.EXTRA_CUSTOMIZATION, NimUIKitImpl.commonTeamSessionCustomization);
intent.setClass(context, NimHallTeamRoomMessageActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
}
protected void findViews() {
ivSetting = findViewById(R.id.iv_setting);
tvTitle = findViewById(R.id.tv_toolbar_title);
invalidTeamTipView = findViewById(R.id.invalid_team_tip);
invalidTeamTipText = findViewById(R.id.invalid_team_text);
findViewById(R.id.iv_back).setOnClickListener(v -> finish());
findViewById(R.id.root_view).setOnClickListener(view -> {
EventBus.getDefault().post(new ClickRootViewEvent());
finish();
});
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
HTeamDataManager.get().init(sessionId);
findViews();
registerTeamUpdateObserver(true);
RxBus.get().toFlowable(TeamEvent.class)
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(teamEvent -> {
switch (teamEvent.getOperation()) {
case TeamEvent.OP_DELETE_TEAM:
case TeamEvent.OP_QUIT_TEAM:
requestTeamInfo();
break;
case TeamEvent.OP_UPDATE_MSG:
MessageListPanelEx messageListPanelEx = fragment.getMessageListPanelEx();
int itemIndex = messageListPanelEx.getItemIndex(teamEvent.getMsgUuid());
messageListPanelEx.refreshViewHolderByIndex(itemIndex);
break;
}
});
EventBus.getDefault().register(this);
requestTeamInfo();
}
private void setTitleBar(Team team) {
if (team.isMyTeam()) {
ivSetting.setVisibility(View.GONE);
} else {
ivSetting.setVisibility(View.GONE);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
HTeamDataManager.get().onDestroy();
registerTeamUpdateObserver(false);
EventBus.getDefault().unregister(this);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
}
/**
* 强行完成@人页面的跳转
*
* @see AitManager 下的 afterTextChanged 方法里改掉原来的跳转逻辑,
* 通过 rxbus 的方式在这里打开我们的成员列表页面
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void openAitTeamMemberPage(AitContactActionEvent event) {
String content = event.getContent();
if (content != null && !Objects.equals(content, "") && content.endsWith("@")) {
if (hTeamInfo == null) {
return;
}
//跳转到群成员列表
HTeamMemberListActivity.start(this, hTeamInfo, HTeamMemberListAdapter.Type.AIT_MEMBERS,
AitContactSelectorActivity.REQUEST_CODE);
}
}
/**
* 请求群基本信息
*/
private void requestTeamInfo() {
// 请求群基本信息
Team t = NimUIKit.getTeamProvider().getTeamById(sessionId);
if (t != null) {
updateTeamInfo(t);
} else {
NimUIKit.getTeamProvider().fetchTeamById(sessionId, (success, result, code) -> {
if (success && result != null) {
updateTeamInfo(result);
} else {
onRequestTeamInfoFailed();
}
});
}
HTeamModel.get().getDetailHTeamInfo(sessionId)
.compose(bindToLifecycle())
.subscribe(info -> this.hTeamInfo = info);
}
private void onRequestTeamInfoFailed() {
toast(ResUtil.getString(R.string.room_chat_activity_nimhallteamroommessageactivity_01));
}
/**
* 更新群信息
*
* @param d
*/
private void updateTeamInfo(final Team d) {
if (d == null) {
return;
}
team = d;
fragment.setTeam(team);
setTitle(team == null ? sessionId : team.getName() + "(" + team.getMemberCount() + ResUtil.getString(R.string.room_chat_activity_nimhallteamroommessageactivity_02));
invalidTeamTipText.setText(team.getType() == TeamTypeEnum.Normal ? R.string.normal_team_invalid_tip : R.string.team_invalid_tip);
invalidTeamTipView.setVisibility(team.isMyTeam() ? View.GONE : View.VISIBLE);
setTitleBar(team);
}
@Override
public void setTitle(CharSequence title) {
if (tvTitle != null) tvTitle.setText(title);
}
/**
* 注册群信息更新监听
*
* @param register
*/
private void registerTeamUpdateObserver(boolean register) {
NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataChangedObserver, register);
NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberDataChangedObserver, register);
NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register);
}
/**
* 群资料变动通知和移除群的通知(包括自己退群和群被解散)
*/
TeamDataChangedObserver teamDataChangedObserver = new TeamDataChangedObserver() {
@Override
public void onUpdateTeams(List<Team> teams) {
if (team == null) {
return;
}
for (Team t : teams) {
if (t.getId().equals(team.getId())) {
updateTeamInfo(t);
break;
}
}
}
@Override
public void onRemoveTeam(Team team) {
if (team == null) {
return;
}
if (team.getId().equals(NimHallTeamRoomMessageActivity.this.team.getId())) {
updateTeamInfo(team);
}
}
};
/**
* 群成员资料变动通知和移除群成员通知
*/
TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() {
@Override
public void onUpdateTeamMember(List<TeamMember> members) {
fragment.refreshMessageList();
}
@Override
public void onRemoveTeamMember(List<TeamMember> member) {
Log.e(TAG, "onRemoveTeamMember() called with: member = [" + member + "]");
}
};
ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() {
@Override
public void onAddedOrUpdatedFriends(List<String> accounts) {
fragment.refreshMessageList();
}
@Override
public void onDeletedFriends(List<String> accounts) {
fragment.refreshMessageList();
}
@Override
public void onAddUserToBlackList(List<String> account) {
fragment.refreshMessageList();
}
@Override
public void onRemoveUserFromBlackList(List<String> account) {
fragment.refreshMessageList();
}
};
@Override
protected MessageFragment fragment() {
// 添加fragment
Bundle arguments = getIntent().getExtras();
if (arguments != null) {
arguments.putSerializable(Extras.EXTRA_TYPE, SessionTypeEnum.Team);
}
fragment = new NimTeamMessageFragment();
fragment.setArguments(arguments);
fragment.setContainerId(R.id.message_fragment_container);
// 等级限制
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (userInfo != null) {
UserLevelVo userLevelVo = userInfo.getUserLevelVo();
if (userLevelVo != null) {
fragment.setCurrentLevel(userLevelVo.experLevelSeq);
}
}
InitInfo initInfo = InitialModel.get().getCacheInitInfo();
if (initInfo != null) {
fragment.setLimitLevel(initInfo.getPrivateChatLevelNo());
}
return fragment;
}
@Override
protected int getContentViewId() {
return R.layout.activity_hall_room_message;
}
@Override
protected void initToolBar() {
}
}

View File

@@ -0,0 +1,316 @@
package com.chwl.app.room_chat.activity;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.netease.nim.uikit.api.NimUIKit;
import com.netease.nim.uikit.api.model.contact.ContactChangedObserver;
import com.netease.nim.uikit.api.model.main.OnlineStateChangeObserver;
import com.netease.nim.uikit.api.model.user.UserInfoObserver;
import com.netease.nim.uikit.business.session.constant.Extras;
import com.netease.nim.uikit.business.uinfo.UserInfoHelper;
import com.netease.nim.uikit.impl.NimUIKitImpl;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.msg.MsgServiceObserve;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.CustomNotification;
import com.chwl.app.R;
import com.chwl.app.ui.im.avtivity.NewBaseMessageActivity;
import com.chwl.app.ui.im.fragment.MessageFragment;
import com.chwl.app.room_chat.event.ClickRootViewEvent;
import com.chwl.core.im.friend.IMFriendModel;
import com.chwl.core.initial.InitialModel;
import com.chwl.core.initial.bean.InitInfo;
import com.chwl.core.level.UserLevelVo;
import com.chwl.core.manager.IMNetEaseManager;
import com.chwl.core.manager.RoomEvent;
import com.chwl.core.user.UserModel;
import com.chwl.core.user.bean.UserInfo;
import com.chwl.core.utils.SystemUidUtil;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.SingleToastUtil;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import java.util.Set;
/**
* 点对点聊天界面
* <p/>
* Created by huangjun on 2015/2/1.
*/
public class NimRoomP2PMessageActivity extends NewBaseMessageActivity {
ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() {
@Override
public void onAddedOrUpdatedFriends(List<String> accounts) {
setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P));
}
@Override
public void onDeletedFriends(List<String> accounts) {
setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P));
}
@Override
public void onAddUserToBlackList(List<String> account) {
// whetherBlack();
// setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P));
}
@Override
public void onRemoveUserFromBlackList(List<String> account) {
//whetherBlack();
// setTitle(UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P));
}
};
OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() {
@Override
public void onlineStateChange(Set<String> accounts) {
// 更新 toolbar
if (accounts.contains(sessionId)) {
// 按照交互来展示
displayOnlineState();
}
}
};
private boolean isResume = false;
/**
* 命令消息接收观察者
*/
Observer<CustomNotification> commandObserver = new Observer<CustomNotification>() {
@Override
public void onEvent(CustomNotification message) {
if (!sessionId.equals(message.getSessionId()) || message.getSessionType() != SessionTypeEnum.P2P) {
return;
}
showCommandMessage(message);
}
};
private View tipsLayout;
private ImageView closeIcon;
private UserInfoObserver uinfoObserver;
public static void start(Context context, String contactId) {
Intent intent = new Intent();
intent.putExtra(Extras.EXTRA_ACCOUNT, contactId);
intent.putExtra(Extras.EXTRA_CUSTOMIZATION, NimUIKitImpl.commonP2PSessionCustomization);
intent.setClass(context, NimRoomP2PMessageActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
}
@Override
protected int getContentViewId() {
return R.layout.activity_p2p_room_message;
}
@SuppressLint("CheckResult")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 单聊特例话数据,包括个人信息,黑名单
//addBlackList();
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestBuddyInfo();
displayOnlineState();
registerObservers(true);
registerOnlineStateChangeListener(true);
IMNetEaseManager.get().getChatRoomEventObservable()
.compose(bindToLifecycle())
.filter(roomEvent -> roomEvent.getEvent() == RoomEvent.KICK_OUT_ROOM)
.subscribe(roomEvent -> finish());
displayAntiFraudTips();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String sessionId = intent.getStringExtra(Extras.EXTRA_ACCOUNT);
//如果sessionId与之前的sessionId不是同一个,刷新数据
if (!TextUtils.isEmpty(this.sessionId) && !this.sessionId.equals(sessionId)) {
this.sessionId = sessionId;
requestBuddyInfo();
displayOnlineState();
displayAntiFraudTips();
messageFragment = (MessageFragment) switchContent(fragment(intent));
}
}
private void displayAntiFraudTips() {
tipsLayout = findViewById(R.id.rl_tips);
closeIcon = findViewById(R.id.iv_close_tips);
tipsLayout.setVisibility(View.GONE);
// if (shouldDisplayAntiFraudTips()) {
// tipsLayout.setVisibility(View.VISIBLE);
// closeIcon.setOnClickListener(view -> {
// IMFriendModel.get().addCloseTipsAccount(sessionId);
// tipsLayout.setVisibility(View.GONE);
// });
// } else {
// tipsLayout.setVisibility(View.GONE);
// }
findViewById(R.id.root_view).setOnClickListener(view -> {
EventBus.getDefault().post(new ClickRootViewEvent());
finish();
});
}
private boolean shouldDisplayAntiFraudTips() {
return !IMFriendModel.get().isMyFriend(sessionId) &&
!SystemUidUtil.isSystemUid(sessionId) &&
!IMFriendModel.get().hasCloseTips(sessionId);
}
@Override
protected void onDestroy() {
super.onDestroy();
registerObservers(false);
registerOnlineStateChangeListener(false);
}
@Override
protected void onResume() {
super.onResume();
isResume = true;
}
@Override
protected void onStop() {
super.onStop();
isResume = false;
}
private void requestBuddyInfo() {
TextView tvToolbarTitle = (TextView) findViewById(R.id.tv_toolbar_title);
String userTitleName = UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P);
SpannableStringBuilder builder = new SpannableStringBuilder(userTitleName);
tvToolbarTitle.setText(builder);
tvToolbarTitle.setVisibility(View.VISIBLE);
Log.e("requestBuddyInfo", "requestBuddyInfo: " + userTitleName);
findViewById(R.id.iv_back).setOnClickListener(v -> finish());
}
private void registerObservers(boolean register) {
if (register) {
registerUserInfoObserver();
} else {
unregisterUserInfoObserver();
}
NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(commandObserver, register);
NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register);
}
private void registerOnlineStateChangeListener(boolean register) {
if (!NimUIKitImpl.enableOnlineState()) {
return;
}
NimUIKitImpl.getOnlineStateChangeObservable().registerOnlineStateChangeListeners(onlineStateChangeObserver, register);
}
private void displayOnlineState() {
if (!NimUIKitImpl.enableOnlineState()) {
return;
}
String detailContent = NimUIKitImpl.getOnlineStateContentProvider().getDetailDisplay(sessionId);
setSubTitle(detailContent);
}
private void registerUserInfoObserver() {
if (uinfoObserver == null) {
uinfoObserver = new UserInfoObserver() {
@Override
public void onUserInfoChanged(List<String> accounts) {
if (accounts.contains(sessionId)) {
requestBuddyInfo();
}
}
};
}
NimUIKit.getUserInfoObservable().registerObserver(uinfoObserver, true);
}
private void unregisterUserInfoObserver() {
if (uinfoObserver != null) {
NimUIKit.getUserInfoObservable().registerObserver(uinfoObserver, false);
}
}
protected void showCommandMessage(CustomNotification message) {
if (!isResume) {
return;
}
String content = message.getContent();
try {
JSONObject json = JSON.parseObject(content);
int id = json.getIntValue("id");
if (id == 1) {
// 正在输入
// Toast.makeText(NimRoomP2PMessageActivity.this, ResUtil.getString(R.string.room_chat_activity_nimroomp2pmessageactivity_01), Toast.LENGTH_LONG).show();
SingleToastUtil.showToastShort(ResUtil.getString(R.string.room_chat_activity_nimroomp2pmessageactivity_02));
} else {
// Toast.makeText(NimP2PMessageActivity.this, "command: " + content, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
}
}
@Override
protected MessageFragment fragment(Intent intent) {
Bundle arguments = intent.getExtras();
if (arguments == null) {
arguments = new Bundle();
}
arguments.putSerializable(Extras.EXTRA_TYPE, SessionTypeEnum.P2P);
arguments.putBoolean(MessageFragment.IN_ROOM, true);
MessageFragment fragment = new MessageFragment();
fragment.setArguments(arguments);
fragment.setContainerId(R.id.message_fragment_container);
// 等级限制:官方小秘书 和 系统消息,不设置等级限制
if (!SystemUidUtil.isSystemUid(sessionId)) {
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (userInfo != null) {
UserLevelVo userLevelVo = userInfo.getUserLevelVo();
if (userLevelVo != null) {
fragment.setCurrentLevel(userLevelVo.experLevelSeq);
}
}
InitInfo initInfo = InitialModel.get().getCacheInitInfo();
if (initInfo != null) {
fragment.setLimitLevel(initInfo.getPrivateChatLevelNo());
fragment.setLimitLevel(initInfo.getPrivateChatRegisterDay());
}
}
return fragment;
}
@Override
protected void initToolBar() {
//ToolBarOptions options = new NimToolBarOptions();
// setToolBar(R.id.toolbar, options);
}
@Override
protected boolean needSteepStateBar() {
return false;
}
}

View File

@@ -0,0 +1,412 @@
package com.chwl.app.room_chat.activity;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.netease.nim.uikit.api.NimUIKit;
import com.netease.nim.uikit.api.model.SimpleCallback;
import com.netease.nim.uikit.api.model.contact.ContactChangedObserver;
import com.netease.nim.uikit.api.model.session.SessionCustomization;
import com.netease.nim.uikit.api.model.team.TeamDataChangedObserver;
import com.netease.nim.uikit.api.model.team.TeamMemberDataChangedObserver;
import com.netease.nim.uikit.business.ait.event.AitContactActionEvent;
import com.netease.nim.uikit.business.session.actions.BaseAction;
import com.netease.nim.uikit.business.session.actions.ImageAction;
import com.netease.nim.uikit.business.session.constant.Extras;
import com.netease.nim.uikit.business.session.fragment.MessageFragment;
import com.netease.nim.uikit.business.session.module.list.MessageListPanelEx;
import com.netease.nim.uikit.impl.NimUIKitImpl;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.team.constant.TeamTypeEnum;
import com.netease.nimlib.sdk.team.model.Team;
import com.netease.nimlib.sdk.team.model.TeamMember;
import com.trello.rxlifecycle3.android.ActivityEvent;
import com.chwl.app.R;
import com.chwl.app.team.view.NimTeamMessageFragment;
import com.chwl.app.team.view.TeamMemberListActivity;
import com.chwl.app.team.viewmodel.TeamVM;
import com.chwl.app.ui.im.actions.FamilyGameAction;
import com.chwl.app.ui.im.actions.LuckyMoneyAction;
import com.chwl.app.ui.im.avtivity.BaseMessageActivity;
import com.chwl.app.room_chat.event.ClickRootViewEvent;
import com.chwl.core.family.bean.FamilyInfo;
import com.chwl.core.family.model.FamilyModel;
import com.chwl.core.initial.InitialModel;
import com.chwl.core.initial.bean.InitInfo;
import com.chwl.core.level.UserLevelVo;
import com.chwl.core.manager.IMNetEaseManager;
import com.chwl.core.manager.RoomEvent;
import com.chwl.core.team.bean.TeamEvent;
import com.chwl.core.team.model.TeamModel;
import com.chwl.core.user.UserModel;
import com.chwl.core.user.bean.UserInfo;
import com.chwl.library.rxbus.RxBus;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.SingleToastUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* Created by MadisonRong on 24/05/2018.
*/
public class NimTeamRoomMessageActivity extends BaseMessageActivity {
private static final String TAG = "NimTeamMessageActivity";
// model
private Team team;
private View invalidTeamTipView;
private TextView invalidTeamTipText;
private TextView tvTitle;
private NimTeamMessageFragment fragment;
private TeamVM teamViewModel;
private View rootView;
public static void start(Context context, String tid) {
Intent intent = new Intent();
intent.putExtra(Extras.EXTRA_ACCOUNT, tid);
intent.putExtra(Extras.EXTRA_CUSTOMIZATION, NimUIKitImpl.commonTeamSessionCustomization);
intent.setClass(context, NimTeamRoomMessageActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
}
protected void findViews() {
invalidTeamTipView = findViewById(R.id.invalid_team_tip);
invalidTeamTipText = (TextView) findViewById(R.id.invalid_team_text);
tvTitle = (TextView) findViewById(R.id.tv_toolbar_title);
findViewById(R.id.iv_back).setOnClickListener(v -> finish());
findViewById(R.id.root_view).setOnClickListener(view -> {
EventBus.getDefault().post(new ClickRootViewEvent());
finish();
});
}
@SuppressLint("CheckResult")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
findViews();
teamViewModel = new TeamVM();
registerTeamUpdateObserver(true);
RxBus.get().toFlowable(TeamEvent.class)
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(teamEvent -> {
switch (teamEvent.getOperation()) {
case TeamEvent.OP_DELETE_TEAM:
case TeamEvent.OP_QUIT_TEAM:
requestTeamInfo();
break;
case TeamEvent.OP_UPDATE_MSG:
MessageListPanelEx messageListPanelEx = fragment.getMessageListPanelEx();
int itemIndex = messageListPanelEx.getItemIndex(teamEvent.getMsgUuid());
messageListPanelEx.refreshViewHolderByIndex(itemIndex);
break;
}
});
IMNetEaseManager.get().getChatRoomEventObservable()
.compose(bindToLifecycle())
.filter(roomEvent -> roomEvent.getEvent() == RoomEvent.KICK_OUT_ROOM)
.subscribe(roomEvent -> finish());
EventBus.getDefault().register(this);
}
@Override
protected void onStart() {
super.onStart();
requestFamilyInfo();
}
@Override
protected void onDestroy() {
super.onDestroy();
registerTeamUpdateObserver(false);
EventBus.getDefault().unregister(this);
}
@Override
protected void onResume() {
super.onResume();
requestTeamInfo();
}
/**
* 获取家族信息,决定输入面板的红包,家族游戏是否出现
*/
private void requestFamilyInfo() {
if (FamilyModel.Instance().getMyFamily() == null) {
return;
}
FamilyModel.Instance().loadFamilySimpleInfo(
FamilyModel.Instance().getMyFamily().getFamilyId()
)
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new SingleObserver<FamilyInfo>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(FamilyInfo familyInfo) {
if (familyInfo.isOpenMoney()) {
SessionCustomization sessionCustomization = new SessionCustomization();
ArrayList<BaseAction> actions = new ArrayList<>();
actions.add(new ImageAction());
actions.add(new LuckyMoneyAction());
if (familyInfo.isOpenGame()) {
actions.add(new FamilyGameAction());
}
sessionCustomization.actions = actions;
sessionCustomization.withSticker = true;
fragment.reloadInputPanel(sessionCustomization);
} else {
SessionCustomization sessionCustomization = new SessionCustomization();
ArrayList<BaseAction> actions = new ArrayList<>();
actions.add(new ImageAction());
sessionCustomization.actions = actions;
sessionCustomization.withSticker = true;
fragment.reloadInputPanel(sessionCustomization);
}
}
@Override
public void onError(Throwable e) {
// Toast.makeText(NimTeamRoomMessageActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
SingleToastUtil.showToastShort(e.getMessage());
}
});
}
/**
* 强行完成@人页面的跳转
*
* @see com.netease.nim.uikit.business.ait.AitManager 下的 afterTextChanged 方法里改掉原来的跳转逻辑,
* 通过 rxbus 的方式在这里打开我们的成员列表页面
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void openAitTeamMemberPage(AitContactActionEvent event) {
String content = event.getContent();
if (content != null && !Objects.equals(content, "") && content.endsWith("@")) {
TeamMemberListActivity.start(this, sessionId,
TeamModel.get().getTeamInfoCache(sessionId).getId(), TeamMemberListActivity.OP_TEAM_MEMBER_NORMAL);
}
}
/**
* 请求群基本信息
*/
private void requestTeamInfo() {
// 请求群基本信息
Team t = NimUIKit.getTeamProvider().getTeamById(sessionId);
if (t != null) {
updateTeamInfo(t);
} else {
NimUIKit.getTeamProvider().fetchTeamById(sessionId, new SimpleCallback<Team>() {
@Override
public void onResult(boolean success, Team result, int code) {
if (success && result != null) {
updateTeamInfo(result);
} else {
onRequestTeamInfoFailed();
}
}
});
}
teamViewModel.getTeamInfo(sessionId)
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribe((teamInfo, throwable) -> {
if (teamInfo != null) {
TeamModel.get().setCurrentTeamInfo(teamInfo);
TeamModel.get().setTeamInfoCache(sessionId, teamInfo);
}
});
}
private void onRequestTeamInfoFailed() {
// Toast.makeText(NimTeamRoomMessageActivity.this, ResUtil.getString(R.string.room_chat_activity_nimteamroommessageactivity_01), Toast.LENGTH_SHORT).show();
SingleToastUtil.showToastShort(ResUtil.getString(R.string.room_chat_activity_nimteamroommessageactivity_02));
finish();
}
/**
* 更新群信息
*
* @param d
*/
private void updateTeamInfo(final Team d) {
if (d == null) {
return;
}
team = d;
fragment.setTeam(team);
setTitle(team == null ? sessionId : team.getName() + "(" + team.getMemberCount() + ResUtil.getString(R.string.room_chat_activity_nimteamroommessageactivity_03));
invalidTeamTipText.setText(team.getType() == TeamTypeEnum.Normal ? R.string.normal_team_invalid_tip : R.string.team_invalid_tip);
invalidTeamTipView.setVisibility(team.isMyTeam() ? View.GONE : View.VISIBLE);
}
@Override
public void setTitle(CharSequence title) {
if (tvTitle != null) tvTitle.setText(title);
}
/**
* 注册群信息更新监听
*
* @param register
*/
private void registerTeamUpdateObserver(boolean register) {
NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataChangedObserver, register);
NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberDataChangedObserver, register);
NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register);
}
/**
* 群资料变动通知和移除群的通知(包括自己退群和群被解散)
*/
TeamDataChangedObserver teamDataChangedObserver = new TeamDataChangedObserver() {
@Override
public void onUpdateTeams(List<Team> teams) {
if (team == null) {
return;
}
for (Team t : teams) {
if (t.getId().equals(team.getId())) {
updateTeamInfo(t);
break;
}
}
}
@Override
public void onRemoveTeam(Team team) {
if (team == null) {
return;
}
if (team.getId().equals(NimTeamRoomMessageActivity.this.team.getId())) {
updateTeamInfo(team);
}
}
};
/**
* 群成员资料变动通知和移除群成员通知
*/
TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() {
@Override
public void onUpdateTeamMember(List<TeamMember> members) {
fragment.refreshMessageList();
}
@Override
public void onRemoveTeamMember(List<TeamMember> member) {
Log.e(TAG, "onRemoveTeamMember() called with: member = [" + member + "]");
}
};
ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() {
@Override
public void onAddedOrUpdatedFriends(List<String> accounts) {
fragment.refreshMessageList();
}
@Override
public void onDeletedFriends(List<String> accounts) {
fragment.refreshMessageList();
}
@Override
public void onAddUserToBlackList(List<String> account) {
fragment.refreshMessageList();
}
@Override
public void onRemoveUserFromBlackList(List<String> account) {
fragment.refreshMessageList();
}
};
@Override
protected MessageFragment fragment() {
// 添加fragment
Bundle arguments = getIntent().getExtras();
if (arguments != null) {
arguments.putSerializable(Extras.EXTRA_TYPE, SessionTypeEnum.Team);
}
fragment = new NimTeamMessageFragment();
fragment.setArguments(arguments);
fragment.setContainerId(R.id.message_fragment_container);
// 等级限制
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (userInfo != null) {
UserLevelVo userLevelVo = userInfo.getUserLevelVo();
if (userLevelVo != null) {
fragment.setCurrentLevel(userLevelVo.experLevelSeq);
}
}
InitInfo initInfo = InitialModel.get().getCacheInitInfo();
if (initInfo != null) {
fragment.setLimitLevel(initInfo.getPrivateChatLevelNo());
}
return fragment;
}
@Override
protected int getContentViewId() {
return R.layout.activity_team_room_message;
}
@Override
protected void initToolBar() {
}
@Override
protected boolean needSteepStateBar() {
return false;
}
}

View File

@@ -0,0 +1,145 @@
package com.chwl.app.room_chat.activity;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import com.chwl.app.R;
import com.chwl.app.base.BaseViewBindingActivity;
import com.chwl.app.databinding.ActivityRoomInviteFansBinding;
import com.chwl.app.room_chat.event.ClickRootViewEvent;
import com.chwl.app.room_chat.utils.InViteFansTimer;
import com.chwl.core.manager.AvRoomDataManager;
import com.chwl.core.room.model.RoomInviteFansModel;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.SingleToastUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class RoomInviteFansActivity extends BaseViewBindingActivity<ActivityRoomInviteFansBinding> {
private InViteFansTimer timer;
public static void start(Context context) {
Intent starter = new Intent(context, RoomInviteFansActivity.class);
context.startActivity(starter);
}
@Override
public void init() {
getInviteFans();
EventBus.getDefault().register(this);
binding.rootView.setOnClickListener(view -> finish());
}
@SuppressLint("CheckResult")
private void getInviteFans() {
if (AvRoomDataManager.get().mCurrentRoomInfo == null) {
return;
}
RoomInviteFansModel.INSTANCE.getRoomInviteFans(AvRoomDataManager.get().mCurrentRoomInfo.getUid())
.doOnError(throwable ->
getInviteError(throwable.getMessage())
)
.subscribe(info -> {
binding.tvInviteFansCount.setText(Html.fromHtml(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_01) + "<font color=#FFBC52 font-size=12dp>" + info.getFansNum() + "</font>" + ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_02)));
binding.tvInviteFansTimes.setText(Html.fromHtml(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_03) + "<font color=#7662FE font-size=18dp>" + info.getInviteTimes() + "</font>" + ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_04)));
binding.tvInviteFansConfirm.setBackground(getResources().getDrawable(R.drawable.base_shape_theme_30dp));
if (info.getInviteInterval() > 0) {
if (info.getInviteTimes() > 0) {
startCountDownTimer(info.getInviteInterval());
} else {
binding.tvInviteFansConfirm.setBackground(getResources().getDrawable(R.drawable.base_shape_e6e6e6_30dp));
binding.tvInviteFansConfirm.setText(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_05));
}
binding.tvInviteFansConfirm.setClickable(false);
} else {
if (info.getInviteTimes() <= 0) {
binding.tvInviteFansConfirm.setBackground(getResources().getDrawable(R.drawable.base_shape_e6e6e6_30dp));
binding.tvInviteFansConfirm.setText(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_06));
binding.tvInviteFansConfirm.setClickable(false);
return;
}
binding.tvInviteFansConfirm.setClickable(true);
binding.tvInviteFansConfirm.setText(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_07));
binding.tvInviteFansConfirm.setOnClickListener(v -> {
onRoomInviteFansClick();
});
}
});
}
@SuppressLint("CheckResult")
private void onRoomInviteFansClick() {
if (AvRoomDataManager.get().mCurrentRoomInfo == null) {
return;
}
RoomInviteFansModel.INSTANCE.setRoomInviteFans(AvRoomDataManager.get().mCurrentRoomInfo.getUid())
.doOnError(throwable -> SingleToastUtil.showToastShort(throwable.getMessage()))
.subscribe(info -> {
binding.tvInviteFansCount.setText(Html.fromHtml(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_09) + "<font color=#FFBC52 font-size=12dp>" + info.getFansNum() + "</font>" + ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_010)));
binding.tvInviteFansTimes.setText(Html.fromHtml(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_011) + "<font color=#7662FE font-size=18dp>" + info.getInviteTimes() + "</font>" + ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_012)));
binding.tvInviteFansConfirm.setBackground(getResources().getDrawable(R.drawable.base_shape_theme_30dp));
if (info.getInviteInterval() > 0) {
binding.tvInviteFansConfirm.setClickable(false);
if (info.getInviteTimes() > 0) {
startCountDownTimer(info.getInviteInterval());
SingleToastUtil.showToastShort(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_013));
} else {
stopCountDownTimer();
binding.tvInviteFansConfirm.setBackground(getResources().getDrawable(R.drawable.base_shape_e6e6e6_30dp));
binding.tvInviteFansConfirm.setText(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_014));
}
} else {
if (info.getInviteTimes() <= 0) {
binding.tvInviteFansConfirm.setBackground(getResources().getDrawable(R.drawable.base_shape_e6e6e6_30dp));
binding.tvInviteFansConfirm.setText(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_015));
binding.tvInviteFansConfirm.setClickable(false);
return;
}
binding.tvInviteFansConfirm.setClickable(true);
binding.tvInviteFansConfirm.setText(ResUtil.getString(R.string.room_chat_activity_roominvitefansactivity_016));
}
});
}
private void getInviteError(String msg) {
SingleToastUtil.showToast(msg);
finish();
}
@Override
protected boolean needSteepStateBar() {
return false;
}
@Override
protected void onDestroy() {
super.onDestroy();
stopCountDownTimer();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRootViewClicked(ClickRootViewEvent event) {
finish();
}
private void startCountDownTimer(long timeSecond) {
stopCountDownTimer();
timer = new InViteFansTimer(this, binding.tvInviteFansConfirm, timeSecond * 1000, 1000);
timer.start();
}
private void stopCountDownTimer() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
}

View File

@@ -0,0 +1,114 @@
package com.chwl.app.room_chat.activity;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.View;
import androidx.fragment.app.Fragment;
import com.chwl.app.R;
import com.chwl.app.base.BaseViewBindingActivity;
import com.chwl.app.common.ViewPagerAdapter;
import com.chwl.app.databinding.ActivityRoomMessageBinding;
import com.chwl.app.decoration.view.widgets.CarMagicIndicator;
import com.chwl.app.friend.action.AbstractSelectFriendAction;
import com.chwl.app.room_chat.event.ClickRootViewEvent;
import com.chwl.app.room_chat.fragment.RoomMsgAttentionFragment;
import com.chwl.app.room_chat.fragment.RoomMsgFansListFragment;
import com.chwl.app.room_chat.fragment.RoomMsgFriendListFragment;
import com.chwl.app.room_chat.fragment.RoomMsgRecentListFragment;
import com.chwl.core.home.bean.TabInfo;
import com.chwl.core.manager.IMNetEaseManager;
import com.chwl.core.manager.RoomEvent;
import com.chwl.library.utils.ResUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
public class RoomMsgActivity extends BaseViewBindingActivity<ActivityRoomMessageBinding>
implements CarMagicIndicator.OnItemSelectListener, View.OnClickListener {
private String[] titles = {ResUtil.getString(R.string.room_chat_activity_roommsgactivity_01), ResUtil.getString(R.string.room_chat_activity_roommsgactivity_02), ResUtil.getString(R.string.room_chat_activity_roommsgactivity_03), ResUtil.getString(R.string.room_chat_activity_roommsgactivity_04)};
private int type = AbstractSelectFriendAction.ROOM_MSG;
public static final String KEY_PRIVATE_CHAT_ACCOUNT = "key_private_chat_account";
public static void start(Context context) {
Intent starter = new Intent(context, RoomMsgActivity.class);
context.startActivity(starter);
}
public static void startForPrivateChat(Context context, String account) {
Intent starter = new Intent(context, RoomMsgActivity.class);
starter.putExtra(KEY_PRIVATE_CHAT_ACCOUNT, account);
context.startActivity(starter);
}
@SuppressLint("CheckResult")
@Override
public void init() {
List<TabInfo> tabInfoList = new ArrayList<>(2);
for (int i = 0; i < titles.length; i++) {
tabInfoList.add(new TabInfo(i, titles[i]));
}
binding.viewpager.setOffscreenPageLimit(2);
binding.viewpager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getFragment(), titles));
binding.viewIndicator.setViewPager(binding.viewpager, titles, this, getFragment());
IMNetEaseManager.get().getChatRoomEventObservable()
.compose(bindToLifecycle())
.filter(roomEvent -> roomEvent.getEvent() == RoomEvent.KICK_OUT_ROOM)
.subscribe(roomEvent -> finish());
String account = getIntent().getStringExtra(KEY_PRIVATE_CHAT_ACCOUNT);
if (!TextUtils.isEmpty(account)) {
NimRoomP2PMessageActivity.start(this, account);
}
EventBus.getDefault().register(this);
binding.rootView.setOnClickListener(this);
}
@Override
protected boolean needSteepStateBar() {
return false;
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
private ArrayList<Fragment> getFragment() {
ArrayList<Fragment> list = new ArrayList<>();
list.add(RoomMsgRecentListFragment.newInstance());
list.add(RoomMsgFriendListFragment.newInstance());
list.add(RoomMsgFansListFragment.newInstanceForSelect(type));
list.add(RoomMsgAttentionFragment.newInstance());
return list;
}
@Override
public void onItemSelect(int position) {
binding.viewpager.setCurrentItem(position);
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.root_view) {
finish();
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRootViewClicked(ClickRootViewEvent event) {
finish();
}
}

View File

@@ -0,0 +1,38 @@
package com.chwl.app.room_chat.adapter;
import android.widget.ImageView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.chwl.app.R;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.core.user.bean.AttentionInfo;
import java.util.List;
/**
* 房间内私聊用的 关注列表 adapter
*
* @author MadisonRong
*/
public class RoomMsgAttentionListAdapter extends BaseQuickAdapter<AttentionInfo, BaseViewHolder> {
public RoomMsgAttentionListAdapter(List<AttentionInfo> attentionInfoList) {
super(R.layout.room_msg_user_list_item, attentionInfoList);
}
@Override
protected void convert(BaseViewHolder baseViewHolder, final AttentionInfo attentionInfo) {
if (attentionInfo == null) return;
baseViewHolder.setText(R.id.tv_userName, attentionInfo.getNick())
.setText(R.id.tv_user_desc, attentionInfo.getUserDesc() != null ?
attentionInfo.getUserDesc()
: baseViewHolder.itemView.getContext().getResources().getString(R.string.msg_no_user_desc))
.addOnClickListener(R.id.container);
ImageView avatar = baseViewHolder.getView(R.id.noble_avatar_view);
ImageLoadUtils.loadAvatar(mContext, attentionInfo.avatar, avatar);
}
}

View File

@@ -0,0 +1,127 @@
package com.chwl.app.room_chat.adapter;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.annotation.SuppressLint;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import com.netease.nim.uikit.api.NimUIKit;
import com.netease.nim.uikit.common.ui.drop.DropFake;
import com.netease.nim.uikit.common.ui.drop.DropManager;
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter;
import com.netease.nim.uikit.common.ui.recyclerview.holder.NIMBaseViewHolder;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.RecentContact;
import com.chwl.app.R;
import com.chwl.core.utils.SystemUidUtil;
/**
* @author Administrator
*/
public class RoomMsgCommonRecentViewHolder extends RoomMsgRecentViewHolder {
public RoomMsgCommonRecentViewHolder(BaseQuickAdapter adapter) {
super(adapter);
}
@Override
protected String getContent(RecentContact recent) {
return descOfMsg(recent);
}
@Override
protected String getOnlineStateContent(RecentContact recent) {
if (recent.getSessionType() == SessionTypeEnum.P2P && NimUIKit.enableOnlineState()) {
return NimUIKit.getOnlineStateContentProvider().getSimpleDisplay(recent.getContactId());
} else {
return super.getOnlineStateContent(recent);
}
}
@Override
public void inflate(NIMBaseViewHolder holder, final RecentContact recent) {
this.imgHead = holder.getView(R.id.img_head);
this.tvNickname = holder.getView(R.id.tv_nickname);
this.tvMessage = holder.getView(R.id.tv_message);
this.tvUnread = holder.getView(R.id.unread_number_tip);
this.imgUnreadExplosion = holder.getView(R.id.unread_number_explosion);
this.tvDatetime = holder.getView(R.id.tv_date_time);
this.imgMsgStatus = holder.getView(R.id.img_msg_status);
this.tvOnlineState = holder.getView(R.id.tv_online_state);
holder.addOnClickListener(R.id.unread_number_tip);
this.tvUnread.setTouchListener(new DropFake.ITouchListener() {
@Override
public void onDown() {
DropManager.getInstance().setCurrentId(recent);
DropManager.getInstance().down(tvUnread, tvUnread.getText());
}
@Override
public void onMove(float curX, float curY) {
DropManager.getInstance().move(curX, curY);
}
@Override
public void onUp() {
DropManager.getInstance().up();
}
});
}
@Override
public void refresh(NIMBaseViewHolder holder, RecentContact recent, final int position) {
// unread count animation
boolean shouldBoom = lastUnreadCount > 0 && recent.getUnreadCount() == 0; // 未读数从N->0执行爆裂动画;
lastUnreadCount = recent.getUnreadCount();
updateBackground(holder, recent, position);
loadNoble(recent);
loadPortrait(recent);
updateNickLabel(recent);
updateOnlineState(recent);
updateMsgLabel(holder, recent);
updateNewIndicator(recent);
if (shouldBoom) {
Object o = DropManager.getInstance().getCurrentId();
if (o instanceof String && o.equals("0")) {
imgUnreadExplosion.setImageResource(R.drawable.explosion);
imgUnreadExplosion.setVisibility(VISIBLE);
new Handler().post(new Runnable() {
@Override
public void run() {
((AnimationDrawable) imgUnreadExplosion.getDrawable()).start();
// 解决部分手机动画无法播放的问题(例如华为荣耀)
getAdapter().notifyItemChanged(getAdapter().getViewHolderPosition(position));
}
});
}
} else {
imgUnreadExplosion.setVisibility(GONE);
}
}
@SuppressLint("CheckResult")
private void loadNoble(RecentContact recent) {
if (recent == null) return;
String contactId = recent.getContactId();
//去除小秘书,系统消息
if (SystemUidUtil.isSystemUid(contactId) ) {
return;
}
}
}

View File

@@ -0,0 +1,36 @@
package com.chwl.app.room_chat.adapter;
import android.widget.ImageView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.chwl.app.R;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.core.user.bean.FansInfo;
import java.util.List;
/**
* 房间内私聊用的粉丝列表 adapter
*
* @author MadisonRong
*/
public class RoomMsgFansViewAdapter extends BaseQuickAdapter<FansInfo, BaseViewHolder> {
public RoomMsgFansViewAdapter(List<FansInfo> fansInfoList) {
super(R.layout.room_msg_user_list_item, fansInfoList);
}
@Override
protected void convert(BaseViewHolder baseViewHolder, final FansInfo fansInfo) {
if (fansInfo == null) return;
baseViewHolder.setText(R.id.tv_userName, fansInfo.getNick())
.setText(R.id.tv_user_desc, fansInfo.getUserDesc() != null ?
fansInfo.getUserDesc()
: baseViewHolder.itemView.getContext().getResources().getString(R.string.msg_no_user_desc))
.addOnClickListener(R.id.container);
ImageView avatar = baseViewHolder.getView(R.id.noble_avatar_view);
ImageLoadUtils.loadAvatar(mContext, fansInfo.getAvatar(), avatar);
}
}

View File

@@ -0,0 +1,50 @@
package com.chwl.app.room_chat.adapter;
import android.app.Activity;
import android.view.View;
import android.widget.ImageView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.chwl.app.R;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.app.room_chat.activity.NimRoomP2PMessageActivity;
import com.chwl.core.user.bean.UserInfo;
/**
* @author chenran
* @date 2017/10/3
*/
public class RoomMsgFriendListAdapter extends BaseQuickAdapter<UserInfo, BaseViewHolder> {
private Activity context;
public RoomMsgFriendListAdapter(Activity context) {
super(R.layout.room_msg_user_list_item);
this.context = context;
}
@Override
protected void convert(BaseViewHolder helper, UserInfo item) {
if (item == null) return;
helper.setText(R.id.tv_userName, item.getNick())
.setText(R.id.tv_user_desc, item.getUserDesc() != null ?
item.getUserDesc()
: helper.itemView.getContext().getResources().getString(R.string.msg_no_user_desc));
ImageView avatar = helper.getView(R.id.noble_avatar_view);
ImageLoadUtils.loadAvatar(context, item.getAvatar(), avatar);
helper.addOnClickListener(R.id.container);
helper.getView(R.id.container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NimRoomP2PMessageActivity.start(context, String.valueOf(item.getUid()));
}
});
}
}

View File

@@ -0,0 +1,51 @@
package com.chwl.app.room_chat.adapter;
import androidx.recyclerview.widget.RecyclerView;
import com.netease.nim.uikit.business.recent.RecentContactsCallback;
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemQuickAdapter;
import com.netease.nim.uikit.common.ui.recyclerview.holder.NIMBaseViewHolder;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.RecentContact;
import com.chwl.app.R;
import java.util.List;
/**
* 房间私聊用的 ContactAdapter
*
* @author MadisonRong
*/
public class RoomMsgRecentContactAdapter extends BaseMultiItemQuickAdapter<RecentContact, NIMBaseViewHolder> {
interface ViewType {
int VIEW_TYPE_COMMON = 1;
int VIEW_TYPE_TEAM = 2;
}
private RecentContactsCallback callback;
public RoomMsgRecentContactAdapter(RecyclerView recyclerView, List<RecentContact> data) {
super(recyclerView, data);
addItemType(ViewType.VIEW_TYPE_COMMON, R.layout.room_msg_nim_recent_contact_list_item, RoomMsgCommonRecentViewHolder.class);
addItemType(ViewType.VIEW_TYPE_TEAM, R.layout.room_msg_nim_recent_contact_team_list_item, RoomMsgTeamRecentViewHolder.class);
}
@Override
protected int getViewType(RecentContact item) {
return item.getSessionType() == SessionTypeEnum.Team ? ViewType.VIEW_TYPE_TEAM : ViewType.VIEW_TYPE_COMMON;
}
@Override
protected String getItemKey(RecentContact item) {
return String.valueOf(item.getSessionType().getValue()) + "_" + item.getContactId();
}
public RecentContactsCallback getCallback() {
return callback;
}
public void setCallback(RecentContactsCallback callback) {
this.callback = callback;
}
}

View File

@@ -0,0 +1,172 @@
package com.chwl.app.room_chat.adapter;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.text.TextUtils;
import android.widget.ImageView;
import android.widget.TextView;
import com.netease.nim.uikit.business.recent.RecentContactsCallback;
import com.netease.nim.uikit.business.session.emoji.MoonUtil;
import com.netease.nim.uikit.business.uinfo.UserInfoHelper;
import com.netease.nim.uikit.common.ui.drop.DropFake;
import com.netease.nim.uikit.common.ui.imageview.HeadImageView;
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter;
import com.netease.nim.uikit.common.ui.recyclerview.holder.NIMBaseViewHolder;
import com.netease.nim.uikit.common.ui.recyclerview.holder.RecyclerViewHolder;
import com.netease.nim.uikit.common.util.sys.TimeUtil;
import com.netease.nim.uikit.impl.cache.TeamDataCache;
import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.RecentContact;
import com.netease.nimlib.sdk.team.model.Team;
import com.chwl.app.R;
import com.chwl.core.helper.ImHelperUtils;
public abstract class RoomMsgRecentViewHolder extends RecyclerViewHolder<BaseQuickAdapter, NIMBaseViewHolder, RecentContact> {
public RoomMsgRecentViewHolder(BaseQuickAdapter adapter) {
super(adapter);
}
protected int lastUnreadCount = 0;
protected HeadImageView imgHead;
protected TextView tvNickname;
protected TextView tvMessage;
protected TextView tvDatetime;
// 消息发送错误状态标记,目前没有逻辑处理
protected ImageView imgMsgStatus;
// 未读红点(一个占坑,一个全屏动画)
protected DropFake tvUnread;
protected ImageView imgUnreadExplosion;
protected TextView tvOnlineState;
protected ImageView msgNotifyIcon;
// 子类覆写
protected abstract String getContent(RecentContact recent);
@Override
public void convert(NIMBaseViewHolder holder, RecentContact data, int position, boolean isScrolling) {
inflate(holder, data);
refresh(holder, data, position);
}
protected abstract void inflate(NIMBaseViewHolder holder, RecentContact data);
protected abstract void refresh(NIMBaseViewHolder holder, RecentContact data, int position);
protected void updateBackground(NIMBaseViewHolder holder, RecentContact recent, int position) {
// if ((recent.getTag() & RecentContactsFragment.RECENT_TAG_STICKY) == 0) {
// holder.getConvertView().setBackgroundResource(R.drawable.bg_common_touch);
// } else {
// holder.getConvertView().setBackgroundResource(R.drawable.nim_recent_contact_sticky_selecter);
// }
}
protected void loadPortrait(RecentContact recent) {
// 设置头像
if (recent.getSessionType() == SessionTypeEnum.P2P) {
imgHead.loadBuddyAvatar(recent.getContactId());
} else if (recent.getSessionType() == SessionTypeEnum.Team) {
Team team = TeamDataCache.getInstance().getTeamById(recent.getContactId());
imgHead.loadTeamIconByTeam(team);
}
}
protected void updateNewIndicator(RecentContact recent) {
int unreadNum = recent.getUnreadCount();
setUnRead(unreadNum);
}
protected void setUnRead(int unreadNum) {
tvUnread.setVisibility(unreadNum > 0 ? VISIBLE : GONE);
tvUnread.setText(unreadCountShowRule(unreadNum));
}
protected void updateMsgNotifyIcon(RecentContact recentContact) {
//
}
protected void updateMsgLabel(NIMBaseViewHolder holder, RecentContact recent) {
// 显示消息具体内容
MoonUtil.identifyRecentVHFaceExpressionAndTags(holder.getContext(), tvMessage, getContent(recent), -1, 0.45f);
//tvMessage.setText(getContent());
MsgStatusEnum status = recent.getMsgStatus();
switch (status) {
case fail:
imgMsgStatus.setImageResource(R.drawable.nim_g_ic_failed_small);
imgMsgStatus.setVisibility(VISIBLE);
break;
case sending:
imgMsgStatus.setImageResource(R.drawable.nim_recent_contact_ic_sending);
imgMsgStatus.setVisibility(VISIBLE);
break;
default:
imgMsgStatus.setVisibility(GONE);
break;
}
String timeString = TimeUtil.getTimeShowString(recent.getTime(), true);
tvDatetime.setText(timeString);
}
protected String getOnlineStateContent(RecentContact recent) {
return "";
}
protected void updateOnlineState(RecentContact recent) {
if (recent.getSessionType() == SessionTypeEnum.Team) {
tvOnlineState.setVisibility(GONE);
} else {
String onlineStateContent = getOnlineStateContent(recent);
if (TextUtils.isEmpty(onlineStateContent)) {
tvOnlineState.setVisibility(GONE);
} else {
tvOnlineState.setVisibility(VISIBLE);
tvOnlineState.setText(getOnlineStateContent(recent));
}
}
}
protected void updateNickLabel(RecentContact recent) {
switch (recent.getSessionType()) {
case Team:
Team team = TeamDataCache.getInstance().getTeamById(recent.getContactId());
if (team != null) {
tvNickname.setText(team.getName());
}
break;
default:
case P2P:
String nick = UserInfoHelper.getUserTitleName(recent.getContactId(), recent.getSessionType());
tvNickname.setText(nick);
break;
}
}
protected String unreadCountShowRule(int unread) {
unread = Math.min(unread, 99);
return String.valueOf(unread);
}
protected RecentContactsCallback getCallback() {
return ((RoomMsgRecentContactAdapter) getAdapter()).getCallback();
}
protected String descOfMsg(RecentContact recent) {
return ImHelperUtils.getMsgDigest(recent);
}
}

View File

@@ -0,0 +1,187 @@
package com.chwl.app.room_chat.adapter;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import android.text.TextUtils;
import android.widget.ImageView;
import com.google.gson.Gson;
import com.netease.nim.uikit.api.NimUIKit;
import com.netease.nim.uikit.business.recent.TeamMemberAitHelper;
import com.netease.nim.uikit.business.team.helper.TeamHelper;
import com.netease.nim.uikit.common.ui.drop.DropFake;
import com.netease.nim.uikit.common.ui.drop.DropManager;
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter;
import com.netease.nim.uikit.common.ui.recyclerview.holder.NIMBaseViewHolder;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.msg.attachment.MsgAttachment;
import com.netease.nimlib.sdk.msg.attachment.NotificationAttachment;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.RecentContact;
import com.netease.nimlib.sdk.team.TeamService;
import com.netease.nimlib.sdk.team.constant.TeamMessageNotifyTypeEnum;
import com.netease.nimlib.sdk.team.model.Team;
import com.chwl.app.R;
import com.chwl.app.ui.im.recent.TeamExt;
import com.chwl.core.im.custom.bean.LuckyMoneyAttachment;
import com.chwl.core.im.custom.bean.LuckyMoneyTipsAttachment;
public class RoomMsgTeamRecentViewHolder extends RoomMsgRecentViewHolder {
private Team team;
private ImageView ivMiniWorld;
public RoomMsgTeamRecentViewHolder(BaseQuickAdapter adapter) {
super(adapter);
}
@Override
public void inflate(NIMBaseViewHolder holder, final RecentContact recent) {
this.imgHead = holder.getView(R.id.img_head);
this.tvNickname = holder.getView(R.id.tv_nickname);
this.tvMessage = holder.getView(R.id.tv_message);
this.tvUnread = holder.getView(R.id.unread_number_tip);
this.imgUnreadExplosion = holder.getView(R.id.unread_number_explosion);
this.tvDatetime = holder.getView(R.id.tv_date_time);
this.imgMsgStatus = holder.getView(R.id.img_msg_status);
this.tvOnlineState = holder.getView(R.id.tv_online_state);
this.msgNotifyIcon = holder.getView(R.id.iv_mute_notification);
this.ivMiniWorld = holder.getView(R.id.iv_mini_world_img);
holder.addOnClickListener(R.id.unread_number_tip);
this.tvUnread.setTouchListener(new DropFake.ITouchListener() {
@Override
public void onDown() {
DropManager.getInstance().setCurrentId(recent);
DropManager.getInstance().down(tvUnread, tvUnread.getText());
}
@Override
public void onMove(float curX, float curY) {
DropManager.getInstance().move(curX, curY);
}
@Override
public void onUp() {
DropManager.getInstance().up();
}
});
team = NIMClient.getService(TeamService.class).queryTeamBlock(recent.getContactId());
}
@Override
public void refresh(NIMBaseViewHolder holder, RecentContact recent, final int position) {
// unread count animation
boolean shouldBoom = lastUnreadCount > 0 && recent.getUnreadCount() == 0; // 未读数从N->0执行爆裂动画;
lastUnreadCount = recent.getUnreadCount();
updateBackground(holder, recent, position);
loadPortrait(recent);
updateOnlineState(recent);
updateNickLabel(recent);
updateMsgLabel(holder, recent);
if (!isNotifyIconShow(recent))
updateNewIndicator(recent);
else
setUnRead(0);// 关闭消息提醒不显示未读数量
updateMsgNotifyIcon(recent);
if (shouldBoom) {
Object o = DropManager.getInstance().getCurrentId();
if (o instanceof String && o.equals("0")) {
imgUnreadExplosion.setImageResource(R.drawable.explosion);
imgUnreadExplosion.setVisibility(VISIBLE);
new Handler().post(new Runnable() {
@Override
public void run() {
((AnimationDrawable) imgUnreadExplosion.getDrawable()).start();
// 解决部分手机动画无法播放的问题(例如华为荣耀)
getAdapter().notifyItemChanged(getAdapter().getViewHolderPosition(position));
}
});
}
} else {
imgUnreadExplosion.setVisibility(GONE);
}
if (ivMiniWorld != null) {
if (team != null) {
int type = 0;
String ext = team.getExtServer();
if (!TextUtils.isEmpty(ext)) {
TeamExt teamExt = new Gson().fromJson(ext, TeamExt.class);
if (teamExt != null) {
type = teamExt.getType();
}
}
if (type == 2) {
ivMiniWorld.setVisibility(VISIBLE);
} else {
ivMiniWorld.setVisibility(GONE);
}
} else {
ivMiniWorld.setVisibility(GONE);
}
}
}
@Override
protected String getContent(RecentContact recent) {
String content = descOfMsg(recent);
String fromId = recent.getFromAccount();
MsgAttachment attachment = recent.getAttachment();
if (!TextUtils.isEmpty(fromId)
&& !fromId.equals(NimUIKit.getAccount())
&& !(attachment instanceof NotificationAttachment)
&& !(attachment instanceof LuckyMoneyAttachment)
&& !(attachment instanceof LuckyMoneyTipsAttachment)) {
String tid = recent.getContactId();
String teamNick = getTeamUserDisplayName(tid, fromId);
content = teamNick + ": " + content;
if (TeamMemberAitHelper.hasAitExtension(recent)) {
if (recent.getUnreadCount() == 0) {
TeamMemberAitHelper.clearRecentContactAited(recent);
} else {
content = TeamMemberAitHelper.getAitAlertString(content);
}
}
}
return content;
}
private String getTeamUserDisplayName(String tid, String account) {
return TeamHelper.getTeamMemberDisplayName(tid, account);
}
@Override
protected void updateMsgNotifyIcon(RecentContact recentContact) {
super.updateMsgNotifyIcon(recentContact);
msgNotifyIcon.setVisibility(isNotifyIconShow(recentContact) ? VISIBLE : GONE);
}
private boolean isNotifyIconShow(RecentContact recentContact) {
return recentContact.getSessionType() == SessionTypeEnum.Team
&& team != null && team.getMessageNotifyType() == TeamMessageNotifyTypeEnum.Mute;
}
}

View File

@@ -0,0 +1,4 @@
package com.chwl.app.room_chat.event;
public class ChangeNewbieMessageEvent {
}

View File

@@ -0,0 +1,4 @@
package com.chwl.app.room_chat.event;
public class ClickRootViewEvent {
}

View File

@@ -0,0 +1,4 @@
package com.chwl.app.room_chat.event;
public class SendHelloEvent {
}

View File

@@ -0,0 +1,4 @@
package com.chwl.app.room_chat.event;
public class SendHelloSuccessEvent {
}

View File

@@ -0,0 +1,210 @@
package com.chwl.app.room_chat.fragment;
import static com.chwl.app.R.id.swipe_refresh;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chwl.app.R;
import com.chwl.app.base.BaseFragment;
import com.chwl.app.friend.view.SelectFriendActivity;
import com.chwl.app.room_chat.activity.NimRoomP2PMessageActivity;
import com.chwl.app.room_chat.adapter.RoomMsgAttentionListAdapter;
import com.chwl.core.Constants;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.praise.event.PraiseEvent;
import com.chwl.core.user.AttentionModel;
import com.chwl.core.user.bean.AttentionInfo;
import com.chwl.core.user.event.LoginUserInfoUpdateEvent;
import com.chwl.core.utils.net.RxHelper;
import com.chwl.library.utils.ListUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
/**
* 房间私聊用的关注界面
*
* @author MadisonRong
*/
public class RoomMsgAttentionFragment extends BaseFragment {
public static final String TAG = "RoomMsgAttentionFragment";
private RecyclerView mRecylcerView;
private SwipeRefreshLayout swipeRefreshLayout;
private RoomMsgAttentionListAdapter adapter;
private List<AttentionInfo> mAttentionInfoList = new ArrayList<>();
private int mPage = Constants.PAGE_START;
private SelectFriendActivity friendActivity;
public static RoomMsgAttentionFragment newInstance() {
return new RoomMsgAttentionFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//需要踩人等东西,所以进入这个界面需要强制刷新
if (isVisibleToUser) {
firstLoadData();
}
}
@Override
public void onFindViews() {
mRecylcerView = mView.findViewById(R.id.recycler_view);
swipeRefreshLayout = mView.findViewById(swipe_refresh);
mRecylcerView.setLayoutManager(new LinearLayoutManager(getContext()));
}
@Override
public void onSetListener() {
swipeRefreshLayout.setOnRefreshListener(onRefreshLisetener);
adapter = new RoomMsgAttentionListAdapter(mAttentionInfoList);
adapter.setOnItemChildClickListener((adapter1, view, position) -> {
AttentionInfo attentionInfo = (AttentionInfo) adapter1.getItem(position);
if (attentionInfo != null) {
NimRoomP2PMessageActivity.start(getActivity(), String.valueOf(attentionInfo.getUid()));
}
});
adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
@Override
public void onLoadMoreRequested() {
mPage++;
onRefreshing();
}
}, mRecylcerView);
}
@Override
public void initiate() {
mRecylcerView.setAdapter(adapter);
swipeRefreshLayout.setRefreshing(true);
firstLoadData();
}
@Override
public int getRootLayoutId() {
return R.layout.fragment_fans_list;
}
SwipeRefreshLayout.OnRefreshListener onRefreshLisetener = this::firstLoadData;
public void firstLoadData() {
mPage = Constants.PAGE_START;
onRefreshing();
}
private void onRefreshing() {
AttentionModel.get().getAttentionList(
AuthModel.get().getCurrentUid(),
mPage,
Constants.PAGE_SIZE
)
.compose(RxHelper.bindFragment(this))
.subscribe(new SingleObserver<List<AttentionInfo>>() {
@Override
public void onSubscribe(Disposable d) {
if (mCompositeDisposable != null) {
mCompositeDisposable.add(d);
}
}
@Override
public void onSuccess(List<AttentionInfo> attentionInfos) {
onGetAttentionList(attentionInfos, mPage);
}
@Override
public void onError(Throwable e) {
onGetAttentionListFail(e.getMessage(), mPage);
}
});
}
public void onGetAttentionList(List<AttentionInfo> attentionInfoList, int page) {
mPage = page;
if (!ListUtils.isListEmpty(attentionInfoList)) {
if (mPage == Constants.PAGE_START) {
hideStatus();
swipeRefreshLayout.setRefreshing(false);
mAttentionInfoList.clear();
adapter.setNewData(attentionInfoList);
if (attentionInfoList.size() < Constants.PAGE_SIZE) {
adapter.setEnableLoadMore(false);
}
} else {
adapter.loadMoreComplete();
adapter.addData(attentionInfoList);
}
} else {
if (mPage == Constants.PAGE_START) {
swipeRefreshLayout.setRefreshing(false);
showNoData(R.drawable.icon_common_failure, getString(R.string.no_attention_text));
} else {
adapter.loadMoreEnd(true);
}
}
}
public void onGetAttentionListFail(String error, int page) {
mPage = page;
if (mPage == Constants.PAGE_START) {
swipeRefreshLayout.setRefreshing(false);
showNetworkErr();
} else {
adapter.loadMoreFail();
toast(error);
}
}
// ------------------关注动作回调 begin-------------------
@Subscribe(threadMode = ThreadMode.MAIN)
public void onPraise(PraiseEvent event) {
if (event.isFailed()) {
return;
}
onRefreshing();
}
// ------------------关注动作回调 end-------------------
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) {
onRefreshing();
}
@Override
public void onReloadData() {
super.onReloadData();
mPage = Constants.PAGE_START;
showLoading();
onRefreshing();
}
}

View File

@@ -0,0 +1,238 @@
package com.chwl.app.room_chat.fragment;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.chwl.app.R;
import com.chwl.app.base.BaseFragment;
import com.chwl.app.common.NoDataFragment;
import com.chwl.app.room_chat.activity.NimRoomP2PMessageActivity;
import com.chwl.app.room_chat.adapter.RoomMsgFansViewAdapter;
import com.chwl.core.Constants;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.praise.event.PraiseEvent;
import com.chwl.core.user.AttentionModel;
import com.chwl.core.user.bean.FansInfo;
import com.chwl.core.user.bean.FansListInfo;
import com.chwl.core.user.event.LoginUserInfoUpdateEvent;
import com.chwl.core.utils.SystemUidUtil;
import com.chwl.library.utils.ListUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
/**
* 房间内私聊用的粉丝列表
*
* @author MadisonRong
*/
public class RoomMsgFansListFragment extends BaseFragment {
private RecyclerView mRecyclerView;
private SwipeRefreshLayout mSwipeRefreshLayout;
private RoomMsgFansViewAdapter adapter;
private int mCurrentCounter = Constants.PAGE_START;
private List<FansInfo> mFansInfoList = new ArrayList<>();
private Context mContext;
private int mPageType;
public static RoomMsgFansListFragment newInstanceForSelect(int type) {
return new RoomMsgFansListFragment();
}
public static RoomMsgFansListFragment newInstance(int pageType) {
RoomMsgFansListFragment fragment = new RoomMsgFansListFragment();
Bundle bundle = new Bundle();
bundle.putInt(Constants.KEY_PAGE_TYPE, pageType);
fragment.setArguments(bundle);
return fragment;
}
@Override
protected void onInitArguments(Bundle bundle) {
super.onInitArguments(bundle);
if (bundle != null) {
mPageType = bundle.getInt(Constants.KEY_PAGE_TYPE);
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getContext();
EventBus.getDefault().register(this);
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Override
public void onFindViews() {
mRecyclerView = mView.findViewById(R.id.recycler_view);
mSwipeRefreshLayout = mView.findViewById(R.id.swipe_refresh);
}
@Override
public void onSetListener() {
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
adapter = new RoomMsgFansViewAdapter(mFansInfoList);
adapter.setOnLoadMoreListener(() -> {
mCurrentCounter++;
onRefreshing();
}, mRecyclerView);
mRecyclerView.setAdapter(adapter);
mSwipeRefreshLayout.setOnRefreshListener(() -> {
mCurrentCounter = Constants.PAGE_START;
onRefreshing();
});
adapter.setOnItemChildClickListener((adapter1, view, position) -> {
FansInfo fansInfo = (FansInfo) adapter1.getItem(position);
if (fansInfo != null) {
if ( SystemUidUtil.isSystemUid(String.valueOf(fansInfo.getUid())) ) {
return;
}
NimRoomP2PMessageActivity.start(getActivity(), String.valueOf(fansInfo.getUid()));
}
});
}
private void onRefreshing() {
AttentionModel.get().getFansList(
AuthModel.get().getCurrentUid(),
mCurrentCounter,
Constants.PAGE_SIZE
).subscribe(new SingleObserver<FansListInfo>() {
@Override
public void onSubscribe(Disposable d) {
mCompositeDisposable.add(d);
}
@Override
public void onSuccess(FansListInfo fansListInfo) {
onGetMyFansList(fansListInfo, mPageType, mCurrentCounter);
}
@Override
public void onError(Throwable e) {
onGetMyFansListFail(e.getMessage(), mPageType, mCurrentCounter);
}
});
}
@Override
public void initiate() {
mSwipeRefreshLayout.setRefreshing(true);
mCurrentCounter = Constants.PAGE_START;
onRefreshing();
}
@Override
public int getRootLayoutId() {
return R.layout.fragment_fans_list;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onPraise(PraiseEvent event) {
getDialogManager().dismissDialog();
if (event.isFailed()) {
toast(event.getError());
return;
}
//该界面关注后,关注按钮消失,所有没有取消操作
toast(getString(R.string.fan_success));
}
public void onGetMyFansList(FansListInfo fansListInfo, int pageType, int page) {
mCurrentCounter = page;
if (pageType == mPageType) {
mSwipeRefreshLayout.setRefreshing(false);
if (fansListInfo == null || ListUtils.isListEmpty(fansListInfo.getFansList())) {
//第一页
if (mCurrentCounter == Constants.PAGE_START) {
showNoData(R.drawable.icon_common_failure, getString(R.string.no_fan_text));
} else {
adapter.loadMoreEnd(true);
}
} else {
hideStatus();
if (mCurrentCounter == Constants.PAGE_START) {
mFansInfoList.clear();
List<FansInfo> fansList = fansListInfo.getFansList();
mFansInfoList.addAll(fansList);
adapter.setNewData(mFansInfoList);
if (fansList.size() < Constants.PAGE_SIZE) {
adapter.setEnableLoadMore(false);
}
return;
}
adapter.loadMoreComplete();
adapter.addData(fansListInfo.getFansList());
}
}
}
@SuppressLint("ResourceType")
@Override
public void showNoData(View view, int drawable, CharSequence charSequence) {
if (!checkActivityValid())
return;
if (view == null) {
return;
}
View status = view.findViewById(R.id.status_layout);
if (status == null || status.getId() <= 0) {
return;
}
NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_large_iv, drawable, charSequence);
fragment.setListener(getLoadListener());
getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss();
}
public void onGetMyFansListFail(String error, int pageType, int page) {
mCurrentCounter = page;
if (pageType == mPageType) {
if (mCurrentCounter == Constants.PAGE_START) {
mSwipeRefreshLayout.setRefreshing(false);
showNetworkErr();
} else {
adapter.loadMoreFail();
toast(error);
}
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) {
mCurrentCounter = Constants.PAGE_START;
onRefreshing();
}
@Override
public void onReloadData() {
super.onReloadData();
mCurrentCounter = Constants.PAGE_START;
showLoading();
onRefreshing();
}
}

View File

@@ -0,0 +1,208 @@
package com.chwl.app.room_chat.fragment;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.orhanobut.logger.Logger;
import com.chwl.app.R;
import com.chwl.app.base.BaseFragment;
import com.chwl.app.common.NoDataFragment;
import com.chwl.app.room_chat.activity.NimRoomP2PMessageActivity;
import com.chwl.app.room_chat.adapter.RoomMsgFriendListAdapter;
import com.chwl.core.im.friend.IMFriendModel;
import com.chwl.core.manager.IMNetEaseManager;
import com.chwl.core.manager.RelationShipEvent;
import com.chwl.core.user.UserModel;
import com.chwl.core.user.bean.UserInfo;
import com.chwl.core.user.event.LoginUserInfoUpdateEvent;
import com.chwl.library.utils.ListUtils;
import com.chwl.library.utils.ResUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
/**
* 房间内私聊用的好友列表界面
*
* @author MadisonRong
*/
public class RoomMsgFriendListFragment extends BaseFragment {
private RoomMsgFriendListAdapter adapter = null;
private SwipeRefreshLayout mSwipeRefresh;
private RecyclerView mRecyclerView;
public static RoomMsgFriendListFragment newInstance() {
return new RoomMsgFriendListFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Override
public void onFindViews() {
mSwipeRefresh = mView.findViewById(R.id.swipe_refresh);
mRecyclerView = mView.findViewById(R.id.recycler_view);
}
@Override
public void onSetListener() {
}
@Override
public void initiate() {
mSwipeRefresh.setOnRefreshListener(() -> {
loadFriends();
});
adapter = new RoomMsgFriendListAdapter(getActivity());
adapter.setOnItemChildClickListener((adapter1, view, position) -> {
UserInfo item = (UserInfo) adapter1.getItem(position);
if (item != null) {
NimRoomP2PMessageActivity.start(getContext(), String.valueOf(item.getUid()));
}
});
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setAdapter(adapter);
loadFriends();
Disposable d = IMNetEaseManager.get().getRelationShipEventObservable().subscribe(this::onGetRelationShipEvent);
mCompositeDisposable.add(d);
}
private void onGetRelationShipEvent(RelationShipEvent event) {
if (event.event == RelationShipEvent.EVENT_FRIEND_UPDATE) {
onFriendListUpdate(event.accounts);
}
}
private void loadFriends() {
mSwipeRefresh.setRefreshing(true);
onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts());
}
@Override
public int getRootLayoutId() {
return R.layout.fragment_fans_list;
}
private void onFriendListUpdate(List<String> accounts) {
if (ListUtils.isListEmpty(accounts)) {
mSwipeRefresh.setRefreshing(false);
showNoData(R.drawable.icon_common_failure, getString(R.string.no_frenids_text));
return;
}
UserModel.get().loadUserInfoByUids(accounts)
.compose(bindToLifecycle())
.map(new Function<List<UserInfo>, LinkedHashMap<Long, UserInfo>>() {
@Override
public LinkedHashMap<Long, UserInfo> apply(List<UserInfo> userInfos) throws Exception {
LinkedHashMap<Long, UserInfo> userInfoLinkedHashMap = new LinkedHashMap<>();
for (UserInfo userInfo : userInfos) {
userInfoLinkedHashMap.put(userInfo.getUid(), userInfo);
}
return userInfoLinkedHashMap;
}
})
.subscribe(new SingleObserver<LinkedHashMap<Long, UserInfo>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(LinkedHashMap<Long, UserInfo> longUserInfoLinkedHashMap) {
onRequestUserInfoMap(longUserInfoLinkedHashMap);
mSwipeRefresh.setRefreshing(false);
}
@Override
public void onError(Throwable e) {
toast(e.getMessage());
showNetworkErr();
mSwipeRefresh.setRefreshing(false);
}
});
}
private void setData(List<UserInfo> userInfos) {
if (userInfos != null && !userInfos.isEmpty()) {
hideStatus();
adapter.setNewData(userInfos);
} else {
showNoData(R.drawable.icon_common_failure, getString(R.string.no_frenids_text));
}
}
@Override
public void showNoData(View view, int drawable, CharSequence charSequence) {
if (!checkActivityValid())
return;
if (view == null) {
return;
}
View status = view.findViewById(R.id.status_layout);
if (status == null || status.getId() <= 0) {
return;
}
NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_large_iv, drawable, charSequence);
fragment.setListener(getLoadListener());
getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) {
mRecyclerView.postDelayed(() -> {
if (getActivity() == null || getActivity().isFinishing()) {
Logger.i(ResUtil.getString(R.string.room_chat_fragment_roommsgfriendlistfragment_01));
return;
}
RoomMsgFriendListFragment.this.onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts());
}, 250);
}
public void onRequestUserInfoMap(LinkedHashMap<Long, UserInfo> userInfoLinkedHashMap) {
hideStatus();
List<UserInfo> userInfos = null;
if (adapter != null) {
userInfos = adapter.getData();
}
if (userInfoLinkedHashMap != null && userInfoLinkedHashMap.size() > 0) {
userInfos = new ArrayList(userInfoLinkedHashMap.size());
Set<Map.Entry<Long, UserInfo>> entries = userInfoLinkedHashMap.entrySet();
for (Map.Entry<Long, UserInfo> entry : entries) {
userInfos.add(entry.getValue());
}
}
setData(userInfos);
}
}

View File

@@ -0,0 +1,674 @@
package com.chwl.app.room_chat.fragment;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.netease.nim.uikit.api.NimUIKit;
import com.netease.nim.uikit.api.model.contact.ContactChangedObserver;
import com.netease.nim.uikit.api.model.main.OnlineStateChangeObserver;
import com.netease.nim.uikit.api.model.team.TeamDataChangedObserver;
import com.netease.nim.uikit.api.model.team.TeamMemberDataChangedObserver;
import com.netease.nim.uikit.api.model.user.UserInfoObserver;
import com.netease.nim.uikit.business.recent.RecentContactsCallback;
import com.netease.nim.uikit.business.recent.TeamMemberAitHelper;
import com.netease.nim.uikit.business.uinfo.UserInfoHelper;
import com.netease.nim.uikit.common.badger.Badger;
import com.netease.nim.uikit.common.fragment.TFragment;
import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog;
import com.netease.nim.uikit.common.ui.drop.DropCover;
import com.netease.nim.uikit.common.ui.drop.DropManager;
import com.netease.nim.uikit.common.ui.recyclerview.listener.SimpleClickListener;
import com.netease.nim.uikit.impl.NimUIKitImpl;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.RequestCallbackWrapper;
import com.netease.nimlib.sdk.ResponseCode;
import com.netease.nimlib.sdk.msg.MsgService;
import com.netease.nimlib.sdk.msg.MsgServiceObserve;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum;
import com.netease.nimlib.sdk.msg.model.RecentContact;
import com.netease.nimlib.sdk.team.model.Team;
import com.netease.nimlib.sdk.team.model.TeamMember;
import com.chwl.app.R;
import com.chwl.app.room_chat.adapter.RoomMsgRecentContactAdapter;
import com.chwl.library.utils.ResUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;
/**
* 房间私聊用的最近联系人列表(会话列表)
*
* @author MadisonRong
*/
public class RoomMsgRecentContactsFragment extends TFragment {
// 置顶功能可直接使用也可作为思路供开发者充分利用RecentContact的tag字段
public static final long RECENT_TAG_STICKY = 1; // 联系人置顶tag
// view
private RecyclerView recyclerView;
private View emptyBg;
private TextView emptyHint;
// data
private List<RecentContact> items;
private Map<String, RecentContact> cached; // 暂缓刷上列表的数据(未读数红点拖拽动画运行时用)
private RoomMsgRecentContactAdapter adapter;
private boolean msgLoaded = false;
private RecentContactsCallback callback;
private UserInfoObserver userInfoObserver;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
findViews();
initMessageList();
requestMessages(true);
registerObservers(true);
registerDropCompletedListener(true);
registerOnlineStateChangeListener(true);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public static RoomMsgRecentContactsFragment newInstance() {
return new RoomMsgRecentContactsFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_recent_contacts, container, false);
}
private void notifyDataSetChanged() {
adapter.notifyDataSetChanged();
boolean empty = items.isEmpty() && msgLoaded;
emptyBg.setVisibility(empty ? View.VISIBLE : View.GONE);
emptyHint.setText(ResUtil.getString(R.string.room_chat_fragment_roommsgrecentcontactsfragment_01));
}
@Override
public void onDestroy() {
super.onDestroy();
registerObservers(false);
registerDropCompletedListener(false);
registerOnlineStateChangeListener(false);
DropManager.getInstance().setDropListener(null);
}
/**
* 查找页面控件
*/
private void findViews() {
recyclerView = findView(R.id.recycler_view);
emptyBg = findView(R.id.emptyBg);
emptyHint = findView(R.id.message_list_empty_hint);
}
/**
* 初始化消息列表
*/
private void initMessageList() {
items = new ArrayList<>();
cached = new HashMap<>(3);
// adapter
adapter = new RoomMsgRecentContactAdapter(recyclerView, items);
initCallBack();
adapter.setCallback(callback);
// recyclerView
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addOnItemTouchListener(touchListener);
// ios style
OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL);
// drop listener
DropManager.getInstance().setDropListener(new DropManager.IDropListener() {
@Override
public void onDropBegin() {
touchListener.setShouldDetectGesture(false);
}
@Override
public void onDropEnd() {
touchListener.setShouldDetectGesture(true);
}
});
}
private void initCallBack() {
if (callback != null) {
return;
}
callback = new RecentContactsCallback() {
@Override
public void onRecentContactsLoaded() {
}
@Override
public void onUnreadCountChange(int unreadCount) {
}
@Override
public void onItemClick(RecentContact recent) {
if (recent.getSessionType() == SessionTypeEnum.Team) {
NimUIKit.startTeamSession(getActivity(), recent.getContactId());
} else if (recent.getSessionType() == SessionTypeEnum.P2P) {
NimUIKit.startP2PSession(getActivity(), recent.getContactId());
}
}
};
}
private SimpleClickListener<RoomMsgRecentContactAdapter> touchListener = new SimpleClickListener<RoomMsgRecentContactAdapter>() {
@Override
public void onItemClick(RoomMsgRecentContactAdapter adapter, View view, int position) {
if (callback != null) {
RecentContact recent = adapter.getItem(position);
callback.onItemClick(recent);
}
}
@Override
public void onItemLongClick(RoomMsgRecentContactAdapter adapter, View view, int position) {
showLongClickMenu(adapter.getItem(position), position);
}
@Override
public void onItemChildClick(RoomMsgRecentContactAdapter adapter, View view, int position) {
}
@Override
public void onItemChildLongClick(RoomMsgRecentContactAdapter adapter, View view, int position) {
}
};
OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() {
@Override
public void onlineStateChange(Set<String> accounts) {
notifyDataSetChanged();
}
};
private void registerOnlineStateChangeListener(boolean register) {
if (!NimUIKitImpl.enableOnlineState()) {
return;
}
NimUIKitImpl.getOnlineStateChangeObservable().registerOnlineStateChangeListeners(onlineStateChangeObserver, register);
}
private void showLongClickMenu(final RecentContact recent, final int position) {
if (getActivity() == null) return;
CustomAlertDialog alertDialog = new CustomAlertDialog(getActivity());
alertDialog.setTitle(UserInfoHelper.getUserTitleName(recent.getContactId(), recent.getSessionType()));
String title = ResUtil.getString(R.string.room_chat_fragment_roommsgrecentcontactsfragment_02);
alertDialog.addItem(title, () -> {
// 删除会话,删除后,消息历史被一起删除
NIMClient.getService(MsgService.class).deleteRecentContact2(recent.getContactId(), recent.getSessionType());
NIMClient.getService(MsgService.class).clearChattingHistory(recent.getContactId(), recent.getSessionType());
});
title = (isTagSet(recent, RECENT_TAG_STICKY) ? ResUtil.getString(R.string.room_chat_fragment_roommsgrecentcontactsfragment_03) : ResUtil.getString(R.string.room_chat_fragment_roommsgrecentcontactsfragment_04));
alertDialog.addItem(title, () -> {
if (isTagSet(recent, RECENT_TAG_STICKY)) {
removeTag(recent, RECENT_TAG_STICKY);
} else {
addTag(recent, RECENT_TAG_STICKY);
}
NIMClient.getService(MsgService.class).updateRecent(recent);
refreshMessages(false);
});
alertDialog.show();
}
private void addTag(RecentContact recent, long tag) {
tag = recent.getTag() | tag;
recent.setTag(tag);
}
private void removeTag(RecentContact recent, long tag) {
tag = recent.getTag() & ~tag;
recent.setTag(tag);
}
private boolean isTagSet(RecentContact recent, long tag) {
return (recent.getTag() & tag) == tag;
}
private List<RecentContact> loadedRecents;
public void requestMessages(boolean delay) {
getHandler().postDelayed(new Runnable() {
@Override
public void run() {
// 查询最近联系人列表数据
NIMClient.getService(MsgService.class).queryRecentContacts().setCallback(new RequestCallbackWrapper<List<RecentContact>>() {
@Override
public void onResult(int code, List<RecentContact> recents, Throwable exception) {
if (code != ResponseCode.RES_SUCCESS || recents == null) {
return;
}
loadedRecents = recents;
// 初次加载,更新离线的消息中是否有@我的消息
for (RecentContact loadedRecent : loadedRecents) {
if (loadedRecent.getSessionType() == SessionTypeEnum.Team) {
updateOfflineContactAited(loadedRecent);
}
}
// 此处如果是界面刚初始化,为了防止界面卡顿,可先在后台把需要显示的用户资料和群组资料在后台加载好,然后再刷新界面
//
msgLoaded = true;
if (isAdded()) {
onRecentContactsLoaded();
}
}
});
}
}, delay ? 250 : 0);
}
private void onRecentContactsLoaded() {
items.clear();
if (loadedRecents != null) {
items.addAll(loadedRecents);
loadedRecents = null;
}
refreshMessages(true);
if (callback != null) {
callback.onRecentContactsLoaded();
}
}
private void refreshMessages(boolean unreadChanged) {
sortRecentContacts(items);
notifyDataSetChanged();
if (unreadChanged) {
// 方式一:累加每个最近联系人的未读(快)
int unreadNum = 0;
for (RecentContact r : items) {
unreadNum += r.getUnreadCount();
}
// 方式二直接从SDK读取相对慢
//int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount();
if (callback != null) {
callback.onUnreadCountChange(unreadNum);
}
Badger.updateBadgerCount(unreadNum);
}
}
/**
* **************************** 排序 ***********************************
*/
private void sortRecentContacts(List<RecentContact> list) {
if (list.size() == 0) {
return;
}
Collections.sort(list, comp);
}
private static Comparator<RecentContact> comp = new Comparator<RecentContact>() {
@Override
public int compare(RecentContact o1, RecentContact o2) {
// 先比较置顶tag
long sticky = (o1.getTag() & RECENT_TAG_STICKY) - (o2.getTag() & RECENT_TAG_STICKY);
if (sticky != 0) {
return sticky > 0 ? -1 : 1;
} else {
long time = o1.getTime() - o2.getTime();
return time == 0 ? 0 : (time > 0 ? -1 : 1);
}
}
};
/**
* ********************** 收消息,处理状态变化 ************************
*/
private void registerObservers(boolean register) {
MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class);
service.observeReceiveMessage(messageReceiverObserver, register);
service.observeRecentContact(messageObserver, register);
service.observeMsgStatus(statusObserver, register);
service.observeRecentContactDeleted(deleteObserver, register);
registerTeamUpdateObserver(register);
registerTeamMemberUpdateObserver(register);
NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register);
if (register) {
registerUserInfoObserver();
} else {
unregisterUserInfoObserver();
}
}
/**
* 注册群信息&群成员更新监听
*/
private void registerTeamUpdateObserver(boolean register) {
NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataChangedObserver, register);
}
private void registerTeamMemberUpdateObserver(boolean register) {
NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberDataChangedObserver, register);
}
private void registerDropCompletedListener(boolean register) {
if (register) {
DropManager.getInstance().addDropCompletedListener(dropCompletedListener);
} else {
DropManager.getInstance().removeDropCompletedListener(dropCompletedListener);
}
}
// 暂存消息当RecentContact 监听回来时使用,结束后清掉
private Map<String, Set<IMMessage>> cacheMessages = new HashMap<>();
//监听在线消息中是否有@我
private Observer<List<IMMessage>> messageReceiverObserver = new Observer<List<IMMessage>>() {
@Override
public void onEvent(List<IMMessage> imMessages) {
if (imMessages != null) {
for (IMMessage imMessage : imMessages) {
if (!TeamMemberAitHelper.isAitMessage(imMessage)) {
continue;
}
Set<IMMessage> cacheMessageSet = cacheMessages.get(imMessage.getSessionId());
if (cacheMessageSet == null) {
cacheMessageSet = new HashSet<>();
cacheMessages.put(imMessage.getSessionId(), cacheMessageSet);
}
cacheMessageSet.add(imMessage);
}
}
}
};
Observer<List<RecentContact>> messageObserver = new Observer<List<RecentContact>>() {
@Override
public void onEvent(List<RecentContact> recentContacts) {
if (!DropManager.getInstance().isTouchable()) {
// 正在拖拽红点,缓存数据
for (RecentContact r : recentContacts) {
cached.put(r.getContactId(), r);
}
return;
}
onRecentContactChanged(recentContacts);
}
};
private void onRecentContactChanged(List<RecentContact> recentContacts) {
int index;
for (RecentContact r : recentContacts) {
index = -1;
for (int i = 0; i < items.size(); i++) {
if (r.getContactId().equals(items.get(i).getContactId())
&& r.getSessionType() == (items.get(i).getSessionType())) {
index = i;
break;
}
}
if (index >= 0) {
items.remove(index);
}
items.add(r);
if (r.getSessionType() == SessionTypeEnum.Team && cacheMessages.get(r.getContactId()) != null) {
TeamMemberAitHelper.setRecentContactAited(r, cacheMessages.get(r.getContactId()));
}
}
cacheMessages.clear();
refreshMessages(true);
}
DropCover.IDropCompletedListener dropCompletedListener = new DropCover.IDropCompletedListener() {
@Override
public void onCompleted(Object id, boolean explosive) {
if (cached != null && !cached.isEmpty()) {
// 红点爆裂已经要清除未读不需要再刷cached
if (explosive) {
if (id instanceof RecentContact) {
RecentContact r = (RecentContact) id;
cached.remove(r.getContactId());
} else if (id instanceof String && ((String) id).contentEquals("0")) {
cached.clear();
}
}
// 刷cached
if (!cached.isEmpty()) {
List<RecentContact> recentContacts = new ArrayList<>(cached.size());
recentContacts.addAll(cached.values());
cached.clear();
onRecentContactChanged(recentContacts);
}
}
}
};
Observer<IMMessage> statusObserver = new Observer<IMMessage>() {
@Override
public void onEvent(IMMessage message) {
int index = getItemIndex(message.getUuid());
if (index >= 0 && index < items.size()) {
RecentContact item = items.get(index);
item.setMsgStatus(message.getStatus());
refreshViewHolderByIndex(index);
}
}
};
Observer<RecentContact> deleteObserver = new Observer<RecentContact>() {
@Override
public void onEvent(RecentContact recentContact) {
if (recentContact != null) {
for (RecentContact item : items) {
if (TextUtils.equals(item.getContactId(), recentContact.getContactId())
&& item.getSessionType() == recentContact.getSessionType()) {
items.remove(item);
refreshMessages(true);
break;
}
}
} else {
items.clear();
refreshMessages(true);
}
}
};
TeamDataChangedObserver teamDataChangedObserver = new TeamDataChangedObserver() {
@Override
public void onUpdateTeams(List<Team> teams) {
adapter.notifyDataSetChanged();
}
@Override
public void onRemoveTeam(Team team) {
}
};
TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() {
@Override
public void onUpdateTeamMember(List<TeamMember> members) {
adapter.notifyDataSetChanged();
}
@Override
public void onRemoveTeamMember(List<TeamMember> member) {
}
};
private int getItemIndex(String uuid) {
for (int i = 0; i < items.size(); i++) {
RecentContact item = items.get(i);
if (TextUtils.equals(item.getRecentMessageId(), uuid)) {
return i;
}
}
return -1;
}
protected void refreshViewHolderByIndex(final int index) {
if (recyclerView == null) return;
recyclerView.post(() -> adapter.notifyItemChanged(index));
// if (getActivity() == null) return;
// getActivity().runOnUiThread(new Runnable() {
//
// @Override
// public void run() {
// adapter.notifyItemChanged(index);
// }
// });
}
public void setCallback(RecentContactsCallback callback) {
this.callback = callback;
}
private void registerUserInfoObserver() {
if (userInfoObserver == null) {
userInfoObserver = new UserInfoObserver() {
@Override
public void onUserInfoChanged(List<String> accounts) {
refreshMessages(false);
}
};
}
NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, true);
}
private void unregisterUserInfoObserver() {
if (userInfoObserver != null) {
NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, false);
}
}
ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() {
@Override
public void onAddedOrUpdatedFriends(List<String> accounts) {
refreshMessages(false);
}
@Override
public void onDeletedFriends(List<String> accounts) {
refreshMessages(false);
}
@Override
public void onAddUserToBlackList(List<String> account) {
refreshMessages(false);
}
@Override
public void onRemoveUserFromBlackList(List<String> account) {
refreshMessages(false);
}
};
private void updateOfflineContactAited(final RecentContact recentContact) {
if (recentContact == null || recentContact.getSessionType() != SessionTypeEnum.Team
|| recentContact.getUnreadCount() <= 0) {
return;
}
// 锚点
List<String> uuid = new ArrayList<>(1);
uuid.add(recentContact.getRecentMessageId());
List<IMMessage> messages = NIMClient.getService(MsgService.class).queryMessageListByUuidBlock(uuid);
if (messages == null || messages.size() < 1) {
return;
}
final IMMessage anchor = messages.get(0);
// 查未读消息
NIMClient.getService(MsgService.class).queryMessageListEx(anchor, QueryDirectionEnum.QUERY_OLD,
recentContact.getUnreadCount() - 1, false).setCallback(new RequestCallbackWrapper<List<IMMessage>>() {
@Override
public void onResult(int code, List<IMMessage> result, Throwable exception) {
if (code == ResponseCode.RES_SUCCESS && result != null) {
result.add(0, anchor);
Set<IMMessage> messages = null;
// 过滤存在的@我的消息
for (IMMessage msg : result) {
if (TeamMemberAitHelper.isAitMessage(msg)) {
if (messages == null) {
messages = new HashSet<>();
}
messages.add(msg);
}
}
// 更新并展示
if (messages != null) {
TeamMemberAitHelper.setRecentContactAited(recentContact, messages);
notifyDataSetChanged();
}
}
}
});
}
}

View File

@@ -0,0 +1,145 @@
package com.chwl.app.room_chat.fragment;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.google.gson.Gson;
import com.netease.nim.uikit.business.recent.RecentContactsCallback;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.RecentContact;
import com.chwl.app.R;
import com.chwl.app.base.BaseFragment;
import com.chwl.app.module_hall.im.NimHelper;
import com.chwl.app.ui.im.recent.TeamExt;
import com.chwl.app.room_chat.activity.NimHallTeamRoomMessageActivity;
import com.chwl.app.room_chat.activity.NimRoomP2PMessageActivity;
import com.chwl.app.room_chat.activity.NimTeamRoomMessageActivity;
import com.chwl.core.auth.event.LoginEvent;
import com.chwl.core.user.event.LoadLoginUserInfoEvent;
import com.chwl.core.utils.net.BeanObserver;
import com.chwl.library.utils.ResUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import io.reactivex.Single;
/**
* 房间内私聊显示用的最近聊天列表
* 发现萌新
*
* @author MadisonRong
*/
public class RoomMsgRecentListFragment extends BaseFragment {
private RoomMsgRecentContactsFragment recentContactsFragment;
public static RoomMsgRecentListFragment newInstance() {
return new RoomMsgRecentListFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
@Override
public void onFindViews() {
recentContactsFragment = RoomMsgRecentContactsFragment.newInstance();
FragmentManager fragmentManager = getChildFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.recent_container, recentContactsFragment).commitAllowingStateLoss();
// 等级限制
setFindNewbieView();
}
@SuppressLint("CheckResult")
private void setFindNewbieView() {
}
@Override
public void onSetListener() {
}
@Override
public void initiate() {
recentContactsFragment.setCallback(new RecentContactsCallback() {
@Override
public void onRecentContactsLoaded() {
}
@Override
public void onUnreadCountChange(int unreadCount) {
}
@Override
public void onItemClick(RecentContact recent) {
if (recent.getSessionType() == SessionTypeEnum.Team) {
//判断群类型
NimHelper.getTeamById(RoomMsgRecentListFragment.this, recent.getContactId())
.flatMap(team -> {
int type = 0;
String ext = team.getExtServer();
if (!TextUtils.isEmpty(ext)) {
TeamExt teamExt = new Gson().fromJson(ext, TeamExt.class);
if (teamExt != null) {
type = teamExt.getType();
}
}
return Single.just(type);
})
.subscribe(new BeanObserver<Integer>() {
@Override
public void onErrorMsg(String error) {
toast(error);
}
@Override
public void onSuccess(Integer type) {
if (type == 1) {
NimHallTeamRoomMessageActivity.start(mContext, recent.getContactId());
} else if (type == 0) {
NimTeamRoomMessageActivity.start(mContext, recent.getContactId());
} else {
toast(ResUtil.getString(R.string.room_chat_fragment_roommsgrecentlistfragment_02));
}
}
});
} else if (recent.getSessionType() == SessionTypeEnum.P2P) {
NimRoomP2PMessageActivity.start(mContext, recent.getContactId());
}
}
});
}
@Override
public int getRootLayoutId() {
return R.layout.fragment_recent_list;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginUserInfoUpdateEvent(LoadLoginUserInfoEvent event) {
recentContactsFragment.requestMessages(true);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginEvent(LoginEvent event) {
//登录成功刷新消息页萌新
setFindNewbieView();
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}

View File

@@ -0,0 +1,134 @@
package com.chwl.app.room_chat.fragment
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.view.ViewGroup.LayoutParams
import androidx.fragment.app.Fragment
import androidx.viewpager2.widget.ViewPager2
import com.chwl.app.R
import com.chwl.app.base.BaseDialogFragment
import com.chwl.app.databinding.ActivityRoomMessage2Binding
import com.chwl.app.databinding.ItemRoomMsgTabBinding
import com.chwl.app.friend.action.AbstractSelectFriendAction
import com.chwl.app.room_chat.activity.NimRoomP2PMessageActivity
import com.chwl.app.room_chat.activity.RoomMsgActivity
import com.chwl.app.room_chat.activity.RoomMsgActivity.KEY_PRIVATE_CHAT_ACCOUNT
import com.chwl.app.room_chat.event.ClickRootViewEvent
import com.chwl.app.ui.im.recent.RecentListFragment
import com.chwl.core.home.bean.TabInfo
import com.chwl.core.manager.IMNetEaseManager
import com.chwl.core.manager.RoomEvent
import com.chwl.library.common.util.setVis
import com.chwl.library.utils.ResUtil
import com.chwl.library.widget.tab.util.FragmentPageAdapter
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class RoomMsgTabFragment : BaseDialogFragment<ActivityRoomMessage2Binding>(), View.OnClickListener {
override var gravity = Gravity.BOTTOM
override var width = LayoutParams.MATCH_PARENT
companion object{
fun newInstance(account: String?): RoomMsgTabFragment{
val args = Bundle()
args.putString(KEY_PRIVATE_CHAT_ACCOUNT,account)
val fragment = RoomMsgTabFragment()
fragment.arguments = args
return fragment
}
}
private val titles = arrayOf<String>(
ResUtil.getString(R.string.room_chat_activity_roommsgactivity_01),
ResUtil.getString(R.string.room_chat_activity_roommsgactivity_02),
ResUtil.getString(R.string.room_chat_activity_roommsgactivity_03),
ResUtil.getString(R.string.room_chat_activity_roommsgactivity_04)
)
private val type = AbstractSelectFriendAction.ROOM_MSG
val KEY_PRIVATE_CHAT_ACCOUNT: String = "key_private_chat_account"
override fun init() {
EventBus.getDefault().register(this)
val tabInfoList: MutableList<TabInfo> = ArrayList(2)
for (i in titles.indices) {
tabInfoList.add(TabInfo(i, titles[i]))
}
// binding.tabLayout.setCustomTabView(SmartTabLayout2.TabProvider { container, position, pageTitle ->
// val tabView = TextView(context)
// tabView.text = titles[position]
// return@TabProvider tabView
// })
val pageAdapter = FragmentPageAdapter(this,getFragment())
binding.tabLayout.setViewPager(binding.viewPage,pageAdapter) { position -> titles[position] }
binding.viewPage.offscreenPageLimit = 2
binding.viewPage.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
selectTab(position)
}
})
IMNetEaseManager.get().chatRoomEventObservable
.compose<RoomEvent>(bindToLifecycle<RoomEvent>())
.filter { roomEvent: RoomEvent -> roomEvent.event == RoomEvent.KICK_OUT_ROOM }
.subscribe { roomEvent: RoomEvent? -> dismiss()}
val account = arguments?.getString(RoomMsgActivity.KEY_PRIVATE_CHAT_ACCOUNT,"")
if (!TextUtils.isEmpty(account)) {
NimRoomP2PMessageActivity.start(context, account)
}
binding.rootView.setOnClickListener(this)
}
private fun selectTab(pos: Int) {
for (i in titles.indices) {
val tabAt = binding.tabLayout.getTabAt(i)
val tabView = ItemRoomMsgTabBinding.bind(tabAt)
tabView.select.setVis((pos == i),true)
tabView.title.alpha = if (pos == i) 1f else 0.5f
}
}
private fun getFragment(): java.util.ArrayList<Fragment> {
val list = java.util.ArrayList<Fragment>()
list.add(RecentListFragment.newInstance(true))
list.add(RoomMsgFriendListFragment.newInstance())
list.add(RoomMsgFansListFragment.newInstanceForSelect(type))
list.add(RoomMsgAttentionFragment.newInstance())
return list
}
override fun onClick(view: View) {
if (view.id == R.id.root_view) {
dismiss()
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onRootViewClicked(event: ClickRootViewEvent?) {
dismiss()
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
}

View File

@@ -0,0 +1,53 @@
package com.chwl.app.room_chat.utils;
import android.content.Context;
import android.os.CountDownTimer;
import android.text.Html;
import android.widget.TextView;
import com.chwl.app.R;
import com.chwl.library.utils.ResUtil;
/**
* Created by zhouxiangfeng on 2017/5/2.
*/
public class InViteFansTimer extends CountDownTimer {
private TextView tvInvite;
private Context mContext;
/**
* @param tvInvite
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receiver
* {@link #onTick(long)} callbacks.
*/
public InViteFansTimer(Context context,TextView tvInvite, long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
this.tvInvite = tvInvite;
this.mContext = context;
}
@Override
public void onTick(long millisUntilFinished) {
tvInvite.setClickable(false); //设置不可点击
tvInvite.setText(inviteInterval((int)millisUntilFinished/1000));
}
@Override
public void onFinish() {
tvInvite.setBackground(mContext.getResources().getDrawable(R.drawable.base_shape_theme_30dp));
tvInvite.setText(Html.fromHtml(ResUtil.getString(R.string.room_chat_utils_invitefanstimer_01)));
tvInvite.setClickable(true);//重新获得点击
}
private String inviteInterval(int timeSecond){
tvInvite.setBackground(mContext.getResources().getDrawable(R.drawable.base_shape_e6e6e6_30dp));
return (timeSecond / 60) + ResUtil.getString(R.string.room_chat_utils_invitefanstimer_02) + (timeSecond % 60) + ResUtil.getString(R.string.room_chat_utils_invitefanstimer_03);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:topLeftRadius="@dimen/dp_20"
android:bottomLeftRadius="@dimen/dp_20"
android:topRightRadius="@dimen/dp_8"
android:bottomRightRadius="@dimen/dp_18"/>
<solid android:color="@color/color_F4F4F4" />
</shape>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<shape android:shape="rectangle">
<solid android:color="#FFF0C9" />
<stroke android:width="1px" android:color="#FFBC51" />
<corners android:radius="100dp" />
</shape>
</item>
<item android:state_checked="false">
<shape android:shape="rectangle">
<solid android:color="#F1F1FA" />
<corners android:radius="100dp" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="270"
android:startColor="#E6F9F9F9"
android:centerColor="@color/color_F9F9F9"
android:endColor="@color/color_F9F9F9"/>
<corners android:radius="0dp" />
</shape>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="270"
android:startColor="#00000000"
android:centerColor="#1AF9F9F9"
android:endColor="#FFF9F9F9"
/>
<corners android:radius="0dp" />
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#FFA936" android:state_checked="true" />
<item android:color="#666666" android:state_pressed="false" />
</selector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/bg_normal_1c1b22"/>
<corners android:topLeftRadius="@dimen/dp_15"
android:topRightRadius="@dimen/dp_15"/>
</shape>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white"/>
<corners android:topLeftRadius="@dimen/dp_14"
android:topRightRadius="@dimen/dp_14"/>
</shape>

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/room_msg_height"
android:layout_gravity="bottom"
android:background="@drawable/shape_white_top_14dp"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_back"
android:layout_width="@dimen/dp_50"
android:layout_height="@dimen/dp_50"
android:scaleType="center"
android:src="@drawable/icon_arrow_left_black" />
<TextView
android:id="@+id/tv_toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="@style/Toolbar.TitleText"
tools:text="@string/layout_activity_hall_room_message_01"
tools:visibility="visible" />
<ImageView
android:id="@+id/iv_setting"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end"
android:padding="@dimen/dp_12"
android:src="@drawable/h_team_chat_more" />
<ImageView
android:id="@+id/iv_team_member_list"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="end"
android:padding="17dp"
android:src="@drawable/icon_team_member_management"
android:visibility="gone" />
</FrameLayout>
<RelativeLayout
android:id="@+id/invalid_team_tip"
android:layout_width="match_parent"
android:layout_height="40dip"
android:background="@drawable/nim_message_activity_top_tip"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/invalid_team_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/team_invalid_tip"
android:textColor="@color/color_yellow_796413"
android:textSize="14sp" />
</RelativeLayout>
<LinearLayout
android:id="@+id/message_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/room_msg_height"
android:layout_gravity="bottom"
android:background="@drawable/shape_1c1b22_top_15dp"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_back"
android:layout_width="@dimen/dp_50"
android:layout_height="@dimen/dp_50"
android:scaleType="center"
android:src="@drawable/arrow_left" />
<TextView
android:id="@+id/tv_toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:ellipsize="end"
android:maxWidth="214dp"
android:maxLines="1"
android:singleLine="true"
android:textSize="@dimen/sp_16"
android:textColor="@color/text_title_color"
android:visibility="gone"
tools:text="@string/layout_activity_p2p_room_message_01"
tools:visibility="visible" />
</FrameLayout>
<RelativeLayout
android:id="@+id/rl_tips"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_30"
android:orientation="horizontal">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_FEE4E4" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/layout_activity_p2p_room_message_02"
android:textColor="@color/color_ff5454"
android:textSize="@dimen/dp_12"
tools:ignore="SpUsage" />
<ImageView
android:id="@+id/iv_close_tips"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:paddingStart="@dimen/dp_15"
android:paddingTop="@dimen/dp_11"
android:paddingEnd="@dimen/dp_15"
android:paddingBottom="@dimen/dp_11"
android:src="@mipmap/common_ic_close_red" />
</RelativeLayout>
<LinearLayout
android:id="@+id/message_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@color/color_666666">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@drawable/smash_eggs_rank_bg"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="375:552">
<LinearLayout
android:id="@+id/layout_tab"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="@dimen/dp_22"
android:background="@drawable/smash_eggs_rank_bg_tab"
android:orientation="horizontal"
android:weightSum="2"
app:layout_constraintDimensionRatio="225:40"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.6">
<TextView
android:id="@+id/tv_tab_today"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:autoSizeMaxTextSize="@dimen/dp_15"
android:autoSizeMinTextSize="@dimen/dp_8"
android:autoSizeStepGranularity="1sp"
android:autoSizeTextType="uniform"
android:background="@drawable/smash_eggs_rank_bg_tab_selected_left"
android:gravity="center"
android:text="@string/treasure_box_activity_boxrankingactivity_01"
android:textColor="@color/white"
android:textSize="@dimen/dp_15"
app:autoSizeMaxTextSize="@dimen/dp_15"
app:autoSizeMinTextSize="@dimen/dp_8"
app:autoSizeStepGranularity="1sp"
app:autoSizeTextType="uniform" />
<TextView
android:id="@+id/tv_tab_yesterday"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:autoSizeMaxTextSize="@dimen/dp_15"
android:autoSizeMinTextSize="@dimen/dp_8"
android:autoSizeStepGranularity="1sp"
android:autoSizeTextType="uniform"
android:gravity="center"
android:text="@string/treasure_box_activity_boxrankingactivity_02"
android:textColor="@color/white"
android:textSize="@dimen/dp_15"
app:autoSizeMaxTextSize="@dimen/dp_15"
app:autoSizeMinTextSize="@dimen/dp_8"
app:autoSizeStepGranularity="1sp"
app:autoSizeTextType="uniform"
tools:background="@drawable/smash_eggs_rank_bg_tab_selected_right" />
</LinearLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="@dimen/dp_4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_tab" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@color/color_666666">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="273dp"
android:layout_gravity="bottom"
android:background="@drawable/shape_1c1b22_top_15dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/dp_16"
android:text="@string/layout_activity_room_invite_fans_01"
android:textColor="@color/text_title_color"
android:textStyle="bold"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dp_20"
/>
<TextView
android:id="@+id/tv_invite_fans_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/layout_activity_room_invite_fans_02"
android:drawableStart="@drawable/shap_round_room_invite_des"
android:drawablePadding="8dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:textColor="@color/text_normal_c6c6e9"
android:textSize="@dimen/dp_12"
android:layout_marginTop="@dimen/dp_25"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/layout_activity_room_invite_fans_03"
android:drawableStart="@drawable/shap_round_room_invite_des"
android:drawablePadding="8dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:textColor="@color/text_normal_c6c6e9"
android:textSize="@dimen/dp_12"
android:layout_marginTop="@dimen/dp_14"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/layout_activity_room_invite_fans_04"
android:drawableStart="@drawable/shap_round_room_invite_des"
android:drawablePadding="8dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:textColor="@color/text_normal_c6c6e9"
android:layout_marginTop="@dimen/dp_14"
android:textSize="@dimen/dp_12"
/>
<TextView
android:id="@+id/tv_invite_fans_confirm"
android:layout_width="160dp"
android:layout_height="38dp"
android:background="@drawable/base_selector_theme_30dp"
android:textColor="@color/base_selector_color_theme_btn"
android:gravity="center"
android:layout_marginTop="@dimen/dp_35"
android:layout_gravity="center_horizontal"
android:text="@string/layout_activity_room_invite_fans_05"
/>
<TextView
android:id="@+id/tv_invite_fans_times"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="13dp"
android:textColor="@color/text_normal_c6c6e9"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dp_16"
/>
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@color/color_666666">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/room_msg_height"
android:layout_gravity="bottom"
android:background="@drawable/shape_1c1b22_top_15dp"
android:orientation="vertical">
<com.flyco.tablayout.SlidingTabLayout
android:id="@+id/view_indicator"
android:layout_width="match_parent"
android:layout_height="46dp"
app:tl_indicator_color="@color/app_248cfe"
app:tl_indicator_corner_radius="2dp"
app:tl_indicator_height="@dimen/dp_3"
app:tl_indicator_width="@dimen/dp_9"
app:tl_tab_space_equal="true"
app:tl_textSelectColor="@color/text_title_color"
app:tl_textUnselectColor="@color/text_secondary_4f516a"
app:tl_textsize="@dimen/dp_16" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/line_353548" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@color/color_666666">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/room_msg_height"
android:layout_gravity="bottom"
android:background="@drawable/shape_1c1b22_top_15dp"
android:orientation="vertical">
<com.chwl.library.widget.tab.SmartTabLayout2
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="44dp"
app:stl_distributeEvenly="true"
android:layout_marginTop="5dp"
app:stl_indicatorThickness="0dp"
app:stl_customTabTextViewId="@id/title"
app:stl_underlineColor="@color/transparent"
app:stl_underlineThickness="0px"
app:stl_customTabTextLayoutId="@layout/item_room_msg_tab"
app:stl_indicatorWidth="0dp"
tools:layout_height="50dp" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPage"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/room_msg_height"
android:layout_gravity="bottom"
android:background="@drawable/shape_white_top_14dp"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_back"
android:layout_width="@dimen/dp_50"
android:layout_height="@dimen/dp_50"
android:scaleType="center"
android:src="@drawable/icon_arrow_left_black" />
<TextView
android:id="@+id/tv_toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="@style/Toolbar.TitleText"
tools:text="@string/layout_activity_team_room_message_01"
tools:visibility="visible" />
</FrameLayout>
<RelativeLayout
android:id="@+id/invalid_team_tip"
android:layout_width="match_parent"
android:layout_height="40dip"
android:background="@drawable/nim_message_activity_top_tip"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/invalid_team_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/team_invalid_tip"
android:textColor="@color/color_yellow_796413"
android:textSize="14sp" />
</RelativeLayout>
<LinearLayout
android:id="@+id/message_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@drawable/shape_white_top_12dp"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/layout_dialog_newbie_filter_01"
android:textStyle="bold"
android:textColor="#ff333333"
android:textSize="15sp" />
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="15dp"
android:src="@drawable/ic_close_filter" />
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="12dp"
android:text="@string/layout_dialog_newbie_filter_02"
android:textColor="#ff333333"
android:textSize="15sp" />
<RadioGroup
android:id="@+id/rg_gender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_gender_all"
android:layout_width="72dp"
android:layout_height="26dp"
android:layout_marginStart="15dp"
android:background="@drawable/bg_newbie_filter_rb"
android:button="@null"
android:checked="true"
android:gravity="center"
android:text="@string/layout_dialog_newbie_filter_03"
android:textColor="@drawable/color_newbie_rb"
android:textSize="12sp" />
<RadioButton
android:id="@+id/rb_gender_male"
android:layout_width="72dp"
android:layout_height="26dp"
android:layout_marginStart="20dp"
android:background="@drawable/bg_newbie_filter_rb"
android:button="@null"
android:gravity="center"
android:text="@string/layout_dialog_newbie_filter_04"
android:textColor="@drawable/color_newbie_rb"
android:textSize="12sp" />
<RadioButton
android:id="@+id/rb_gender_female"
android:layout_width="72dp"
android:layout_height="26dp"
android:layout_marginStart="20dp"
android:background="@drawable/bg_newbie_filter_rb"
android:button="@null"
android:gravity="center"
android:text="@string/layout_dialog_newbie_filter_05"
android:textColor="@drawable/color_newbie_rb"
android:textSize="12sp" />
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="24dp"
android:text="@string/layout_dialog_newbie_filter_06"
android:textColor="#ff333333"
android:textSize="15sp" />
<RadioGroup
android:id="@+id/rg_hello"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_hello_all"
android:layout_width="72dp"
android:layout_height="26dp"
android:layout_marginStart="15dp"
android:background="@drawable/bg_newbie_filter_rb"
android:button="@null"
android:checked="true"
android:gravity="center"
android:text="@string/layout_dialog_newbie_filter_07"
android:textColor="@drawable/color_newbie_rb"
android:textSize="12sp" />
<RadioButton
android:id="@+id/rb_hello_already"
android:layout_width="72dp"
android:layout_height="26dp"
android:layout_marginStart="20dp"
android:background="@drawable/bg_newbie_filter_rb"
android:button="@null"
android:gravity="center"
android:text="@string/layout_dialog_newbie_filter_08"
android:textColor="@drawable/color_newbie_rb"
android:textSize="12sp" />
<RadioButton
android:id="@+id/rb_hello_no"
android:layout_width="72dp"
android:layout_height="26dp"
android:layout_marginStart="20dp"
android:background="@drawable/bg_newbie_filter_rb"
android:button="@null"
android:gravity="center"
android:text="@string/layout_dialog_newbie_filter_09"
android:textColor="@drawable/color_newbie_rb"
android:textSize="12sp" />
</RadioGroup>
<TextView
android:id="@+id/tv_confirm"
android:layout_width="250dp"
android:layout_height="38dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:layout_marginBottom="45dp"
android:background="@drawable/base_selector_theme_30dp"
android:gravity="center"
android:text="@string/layout_dialog_newbie_filter_010"
android:textColor="@color/base_selector_color_theme_btn"
android:textSize="14sp" />
</LinearLayout>
</layout>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="44dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingVertical="5dp"
android:textColor="@color/color_333333"
android:textSize="18sp"
tools:text="1111" />
<com.chwl.library.widget.text.DrawableTextView
android:id="@+id/select"
android:layout_width="20dp"
android:layout_height="5dp"
android:layout_marginTop="5dp"
app:dt_drawableType="shape"
android:visibility="invisible"
app:dt_radius="25dp"
app:dt_soildColor="#FFC107" />
</LinearLayout>

View File

@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="75dp">
<com.netease.nim.uikit.common.ui.imageview.HeadImageView
android:id="@+id/img_head"
android:layout_width="@dimen/room_msg_avatar_size"
android:layout_height="@dimen/room_msg_avatar_size"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginEnd="@dimen/dp_10" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_charm_level"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_18"
android:adjustViewBounds="true"
android:layout_alignTop="@+id/tv_nickname"
android:layout_alignBottom="@+id/tv_nickname"
android:layout_toEndOf="@+id/iv_noble_level"
android:visibility="gone"
tools:src="@mipmap/ic_user_level"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_noble_level"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_18"
android:adjustViewBounds="true"
android:layout_alignTop="@+id/tv_nickname"
android:layout_alignBottom="@+id/tv_nickname"
android:layout_marginEnd="2dp"
android:layout_toEndOf="@+id/iv_user_badge"
android:visibility="gone"
tools:src="@mipmap/ic_user_level"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_user_badge"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_alignTop="@+id/tv_nickname"
android:layout_alignBottom="@+id/tv_nickname"
android:layout_marginEnd="2dp"
android:layout_toEndOf="@+id/iv_user_gender"
android:visibility="gone"
tools:src="@mipmap/ic_user_level_king"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_user_gender"
android:layout_width="13dp"
android:layout_height="13dp"
android:layout_alignTop="@+id/tv_nickname"
android:layout_alignBottom="@+id/tv_nickname"
android:layout_marginEnd="2dp"
android:layout_toEndOf="@+id/tv_nickname"
android:scaleType="centerInside"
android:visibility="visible"
tools:src="@drawable/ic_gender_female"
tools:visibility="visible" />
<TextView
android:id="@+id/tv_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/center_view"
android:layout_marginEnd="2dp"
android:layout_toEndOf="@+id/img_head"
android:ellipsize="end"
android:includeFontPadding="false"
android:maxWidth="190dp"
android:singleLine="true"
android:text=""
android:textColor="@color/text_title_color"
android:textSize="15dp"
tools:ignore="SpUsage"
tools:text="@string/layout_room_msg_nim_recent_contact_list_item_01" />
<View
android:id="@+id/center_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerVertical="true"
android:layout_marginTop="@dimen/dp_4"
android:layout_marginBottom="@dimen/dp_4" />
<LinearLayout
android:id="@+id/content_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/center_view"
android:layout_marginEnd="50dp"
android:layout_toEndOf="@+id/img_head"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_online_state"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="6dp"
android:gravity="center_vertical"
android:lines="1"
android:text=""
android:textColor="@color/text_normal_c6c6e9"
android:textSize="13dp"
tools:ignore="SpUsage"
tools:text="@string/layout_room_msg_nim_recent_contact_list_item_02" />
<ImageView
android:id="@+id/img_msg_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6dp"
android:contentDescription="@string/empty"
android:visibility="visible"
tools:visibility="visible" />
<TextView
android:id="@+id/tv_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:autoLink="none"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="1"
android:maxWidth="190dp"
android:scrollHorizontally="true"
android:text=""
android:textColor="@color/text_normal_c6c6e9"
android:textSize="13dp"
tools:ignore="SpUsage"
tools:text="@string/layout_room_msg_nim_recent_contact_list_item_03" />
</LinearLayout>
<TextView
android:id="@+id/tv_date_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="16dip"
android:layout_marginEnd="10dip"
android:textColor="@color/text_secondary_4f516a"
android:textSize="@dimen/text_small_size_ten_sp"
tools:text="just now" />
<com.netease.nim.uikit.common.ui.drop.DropFake
android:id="@+id/unread_number_tip"
android:layout_width="16dip"
android:layout_height="16dip"
android:layout_below="@id/tv_nickname"
android:layout_alignParentEnd="true"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:gravity="center"
android:singleLine="true"
android:textColor="@android:color/white"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible" />
<ImageView
android:id="@+id/unread_number_explosion"
android:layout_width="35dip"
android:layout_height="35dip"
android:layout_below="@id/tv_nickname"
android:layout_alignParentEnd="true"
android:layout_marginEnd="6dip"
android:gravity="center"
android:visibility="gone"
tools:visibility="visible" />
</RelativeLayout>

View File

@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="75dp"
android:background="@drawable/bg_common_touch">
<FrameLayout
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginEnd="@dimen/dp_10">
<com.netease.nim.uikit.common.ui.imageview.HeadImageView
android:id="@+id/img_head"
android:layout_width="@dimen/room_msg_avatar_size"
android:layout_height="@dimen/room_msg_avatar_size" />
<ImageView
android:id="@+id/iv_mini_world_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="@drawable/ic_mini_world_team"
android:visibility="gone" />
</FrameLayout>
<View
android:id="@+id/center_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerVertical="true"
android:layout_marginTop="@dimen/dp_4"
android:layout_marginBottom="@dimen/dp_4" />
<LinearLayout
android:id="@+id/content_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/center_view"
android:layout_marginStart="80dp"
android:layout_marginEnd="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_online_state"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="6dp"
android:gravity="center_vertical"
android:lines="1"
android:text=""
android:textColor="@color/text_normal_c6c6e9"
android:textSize="13dp"
tools:ignore="SpUsage"
tools:text="@string/layout_room_msg_nim_recent_contact_team_list_item_01" />
<ImageView
android:id="@+id/img_msg_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6dp"
android:contentDescription="@string/empty"
android:visibility="visible" />
<TextView
android:id="@+id/tv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:autoLink="none"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="1"
android:maxWidth="190dp"
android:scrollHorizontally="true"
android:text=""
android:textColor="@color/text_normal_c6c6e9"
android:textSize="13dp"
tools:ignore="SpUsage" />
</LinearLayout>
<TextView
android:id="@+id/tv_date_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="16dip"
android:layout_marginEnd="10dip"
android:textColor="@color/text_secondary_4f516a"
android:textSize="@dimen/text_small_size_ten_sp"
tools:text="@string/layout_room_msg_nim_recent_contact_team_list_item_02" />
<TextView
android:id="@+id/tv_nickname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/center_view"
android:layout_marginStart="80dp"
android:layout_toStartOf="@+id/tv_date_time"
android:ellipsize="end"
android:includeFontPadding="false"
android:maxWidth="190dp"
android:singleLine="true"
android:text=""
android:textColor="@color/text_title_color"
android:textSize="15dp"
tools:ignore="SpUsage"
tools:text="@string/layout_room_msg_nim_recent_contact_team_list_item_03" />
<ImageView
android:id="@+id/iv_mute_notification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_nickname"
android:layout_alignParentEnd="true"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:src="@drawable/ic_mute_notification"
android:visibility="gone"
tools:visibility="visible" />
<com.netease.nim.uikit.common.ui.drop.DropFake
android:id="@+id/unread_number_tip"
android:layout_width="16dip"
android:layout_height="16dip"
android:layout_below="@id/tv_nickname"
android:layout_alignParentEnd="true"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_toStartOf="@+id/iv_mute_notification"
android:gravity="center"
android:singleLine="true"
android:textColor="@android:color/white"
android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible" />
<ImageView
android:id="@+id/unread_number_explosion"
android:layout_width="35dip"
android:layout_height="35dip"
android:layout_below="@id/tv_nickname"
android:layout_alignParentEnd="true"
android:layout_marginEnd="6dip"
android:gravity="center"
android:visibility="gone" />
</RelativeLayout>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="75dp"
android:background="@drawable/bg_common_touch">
<ImageView
android:id="@+id/noble_avatar_view"
android:layout_width="@dimen/room_msg_avatar_size"
android:layout_height="@dimen/room_msg_avatar_size"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/dp_15"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/default_avatar" />
<TextView
android:id="@+id/tv_userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_5"
android:layout_marginEnd="2dp"
android:layout_weight="1"
android:ellipsize="end"
android:includeFontPadding="false"
android:lines="1"
android:maxWidth="250dp"
android:singleLine="true"
android:textColor="@color/text_title_color"
android:textSize="15sp"
app:layout_constraintStart_toEndOf="@+id/noble_avatar_view"
app:layout_constraintTop_toTopOf="@+id/noble_avatar_view"
tools:text="@string/layout_room_msg_user_list_item_01" />
<TextView
android:id="@+id/tv_user_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_10"
android:layout_marginBottom="@dimen/dp_5"
android:ellipsize="end"
android:includeFontPadding="false"
android:lines="1"
android:maxWidth="250dp"
android:textColor="@color/text_normal_c6c6e9"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@+id/noble_avatar_view"
app:layout_constraintStart_toEndOf="@+id/noble_avatar_view"
tools:text="@string/layout_room_msg_user_list_item_02" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="room_message_activity" parent="MyMaterialTheme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
</resources>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="room_msg_height">500dp</dimen>
<dimen name="room_msg_avatar_size">55dp</dimen>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="room_message_activity" parent="MyMaterialTheme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
</resources>