diff --git a/app/src/main/res/layout/fragment_recent_contacts.xml b/app/src/main/res/layout/fragment_recent_contacts.xml index 36213df9f..62ae9302e 100644 --- a/app/src/main/res/layout/fragment_recent_contacts.xml +++ b/app/src/main/res/layout/fragment_recent_contacts.xml @@ -11,7 +11,9 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:cacheColorHint="@android:color/white" /> + android:cacheColorHint="@android:color/white" + android:clipToPadding="false" + android:paddingBottom="60dp" /> diff --git a/app/src/main/res/layout/item_boss_micro.xml b/app/src/main/res/layout/item_boss_micro.xml index fbcf50a00..bab210820 100644 --- a/app/src/main/res/layout/item_boss_micro.xml +++ b/app/src/main/res/layout/item_boss_micro.xml @@ -284,7 +284,7 @@ android:layout_marginStart="3dp" android:layout_marginEnd="5dp" android:gravity="center" - android:text="9999万+" + android:text="0" android:textColor="@color/white" android:textSize="9dp" /> diff --git a/app/src/module_community/res/layout/fragment_home_dynamic.xml b/app/src/module_community/res/layout/fragment_home_dynamic.xml index e9654aaf3..9dd321c84 100644 --- a/app/src/module_community/res/layout/fragment_home_dynamic.xml +++ b/app/src/module_community/res/layout/fragment_home_dynamic.xml @@ -8,6 +8,8 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/color_F9F9F9" /> + android:background="@color/color_F9F9F9" + android:clipToPadding="false" + android:paddingBottom="60dp" /> \ No newline at end of file diff --git a/app/src/module_community/res/layout/fragment_home_play.xml b/app/src/module_community/res/layout/fragment_home_play.xml index fa506d032..8ebff3048 100644 --- a/app/src/module_community/res/layout/fragment_home_play.xml +++ b/app/src/module_community/res/layout/fragment_home_play.xml @@ -7,5 +7,6 @@ android:clipToPadding="false" android:paddingStart="10dp" android:paddingTop="2dp" + android:paddingBottom="60dp" android:paddingEnd="10dp" /> diff --git a/nim_uikit/src/com/netease/nim/uikit/business/recent/RecentContactsFragment.java b/nim_uikit/src/com/netease/nim/uikit/business/recent/RecentContactsFragment.java deleted file mode 100644 index 9f6fb26bb..000000000 --- a/nim_uikit/src/com/netease/nim/uikit/business/recent/RecentContactsFragment.java +++ /dev/null @@ -1,705 +0,0 @@ -package com.netease.nim.uikit.business.recent; - -import android.os.Bundle; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.netease.nim.uikit.R; -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.adapter.RecentContactAdapter; -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.attachment.MsgAttachment; -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 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; - -import static com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog.onSeparateItemClickListener; - -/** - * 最近联系人列表(会话列表) - *

- * Created by huangjun on 2015/2/1. - */ -public class RecentContactsFragment 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 items; - - private Map cached; // 暂缓刷上列表的数据(未读数红点拖拽动画运行时用) - - private RecentContactAdapter 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 View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.nim_recent_contacts, container, false); - } - - private void notifyDataSetChanged() { - adapter.notifyDataSetChanged(); - boolean empty = items.isEmpty() && msgLoaded; - emptyBg.setVisibility(empty ? View.VISIBLE : View.GONE); - emptyHint.setHint("还没有会话,在通讯录中找个人聊聊吧!"); - } - - @Override - public void onDestroy() { - super.onDestroy(); - registerObservers(false); - registerDropCompletedListener(false); - registerOnlineStateChangeListener(false); - } - - /** - * 查找页面控件 - */ - 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 RecentContactAdapter(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()); - } - } - - @Override - public String getDigestOfAttachment(RecentContact recentContact, MsgAttachment attachment) { - return null; - } - - @Override - public String getDigestOfTipMsg(RecentContact recent) { - return null; - } - }; - } - - private SimpleClickListener touchListener = new SimpleClickListener() { - @Override - public void onItemClick(RecentContactAdapter adapter, View view, int position) { - if (callback != null) { - RecentContact recent = adapter.getItem(position); - callback.onItemClick(recent); - } - } - - @Override - public void onItemLongClick(RecentContactAdapter adapter, View view, int position) { - showLongClickMenu(adapter.getItem(position), position); - } - - @Override - public void onItemChildClick(RecentContactAdapter adapter, View view, int position) { - - } - - @Override - public void onItemChildLongClick(RecentContactAdapter adapter, View view, int position) { - - } - }; - - OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() { - @Override - public void onlineStateChange(Set 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) { - CustomAlertDialog alertDialog = new CustomAlertDialog(getActivity()); - alertDialog.setTitle(UserInfoHelper.getUserTitleName(recent.getContactId(), recent.getSessionType())); - String title = getString(R.string.main_msg_list_delete_chatting); - alertDialog.addItem(title, new onSeparateItemClickListener() { - @Override - public void onClick() { - // 删除会话,删除后,消息历史被一起删除 - NIMClient.getService(MsgService.class).deleteRecentContact(recent); - NIMClient.getService(MsgService.class).clearChattingHistory(recent.getContactId(), recent.getSessionType()); - adapter.remove(position); - - postRunnable(new Runnable() { - @Override - public void run() { - refreshMessages(true); - } - }); - } - }); - - title = (isTagSet(recent, RECENT_TAG_STICKY) ? getString(R.string.main_msg_list_clear_sticky_on_top) : getString(R.string.main_msg_list_sticky_on_top)); - alertDialog.addItem(title, new onSeparateItemClickListener() { - @Override - public void onClick() { - 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.addItem("删除该聊天(仅服务器)", new onSeparateItemClickListener() { - @Override - public void onClick() { - NIMClient.getService(MsgService.class) - .deleteRoamingRecentContact(recent.getContactId(), recent.getSessionType()) - .setCallback(new RequestCallback() { - @Override - public void onSuccess(Void param) { - Toast.makeText(getActivity(), "delete success", Toast.LENGTH_SHORT).show(); - } - - @Override - public void onFailed(int code) { - Toast.makeText(getActivity(), "delete failed, code:" + code, Toast.LENGTH_SHORT).show(); - } - - @Override - public void onException(Throwable exception) { - - } - }); - } - });*/ - 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 loadedRecents; - - public void requestMessages(boolean delay) { - getHandler().postDelayed(new Runnable() { - - @Override - public void run() { - // 查询最近联系人列表数据 - NIMClient.getService(MsgService.class).queryRecentContacts().setCallback(new RequestCallbackWrapper>() { - - @Override - public void onResult(int code, List 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 list) { - if (list.size() == 0) { - return; - } - Collections.sort(list, comp); - } - - private static Comparator comp = new Comparator() { - - @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> cacheMessages = new HashMap<>(); - - //监听在线消息中是否有@我 - private Observer> messageReceiverObserver = new Observer>() { - @Override - public void onEvent(List imMessages) { - if (imMessages != null) { - for (IMMessage imMessage : imMessages) { - if (!TeamMemberAitHelper.isAitMessage(imMessage)) { - continue; - } - Set cacheMessageSet = cacheMessages.get(imMessage.getSessionId()); - if (cacheMessageSet == null) { - cacheMessageSet = new HashSet<>(); - cacheMessages.put(imMessage.getSessionId(), cacheMessageSet); - } - cacheMessageSet.add(imMessage); - } - } - } - }; - - Observer> messageObserver = new Observer>() { - @Override - public void onEvent(List recentContacts) { - if (!DropManager.getInstance().isTouchable()) { - // 正在拖拽红点,缓存数据 - for (RecentContact r : recentContacts) { - cached.put(r.getContactId(), r); - } - - return; - } - - onRecentContactChanged(recentContacts); - } - }; - - private void onRecentContactChanged(List 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 recentContacts = new ArrayList<>(cached.size()); - recentContacts.addAll(cached.values()); - cached.clear(); - - onRecentContactChanged(recentContacts); - } - } - } - }; - - Observer statusObserver = new Observer() { - @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 deleteObserver = new Observer() { - @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 teams) { - adapter.notifyDataSetChanged(); - } - - @Override - public void onRemoveTeam(Team team) { - - } - }; - - TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() { - @Override - public void onUpdateTeamMember(List members) { - adapter.notifyDataSetChanged(); - } - - @Override - public void onRemoveTeamMember(List 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) { - 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 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 accounts) { - refreshMessages(false); - } - - @Override - public void onDeletedFriends(List accounts) { - refreshMessages(false); - } - - @Override - public void onAddUserToBlackList(List account) { - refreshMessages(false); - } - - @Override - public void onRemoveUserFromBlackList(List account) { - refreshMessages(false); - } - }; - - private void updateOfflineContactAited(final RecentContact recentContact) { - if (recentContact == null || recentContact.getSessionType() != SessionTypeEnum.Team - || recentContact.getUnreadCount() <= 0) { - return; - } - - // 锚点 - List uuid = new ArrayList<>(1); - uuid.add(recentContact.getRecentMessageId()); - - List 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>() { - - @Override - public void onResult(int code, List result, Throwable exception) { - if (code == ResponseCode.RES_SUCCESS && result != null) { - result.add(0, anchor); - Set 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(); - } - } - } - }); - - } -} diff --git a/nim_uikit/src/com/netease/nim/uikit/business/recent/holder/RecentViewHolder.java b/nim_uikit/src/com/netease/nim/uikit/business/recent/holder/RecentViewHolder.java index 126b709a3..9cf2fa352 100644 --- a/nim_uikit/src/com/netease/nim/uikit/business/recent/holder/RecentViewHolder.java +++ b/nim_uikit/src/com/netease/nim/uikit/business/recent/holder/RecentViewHolder.java @@ -11,7 +11,6 @@ import android.widget.TextView; import com.netease.nim.uikit.R; import com.netease.nim.uikit.api.NimUIKit; import com.netease.nim.uikit.business.recent.RecentContactsCallback; -import com.netease.nim.uikit.business.recent.RecentContactsFragment; import com.netease.nim.uikit.business.recent.adapter.RecentContactAdapter; import com.netease.nim.uikit.business.session.emoji.MoonUtil; import com.netease.nim.uikit.business.uinfo.UserInfoHelper; @@ -141,7 +140,7 @@ public abstract class RecentViewHolder extends RecyclerViewHolder