乐趣区

关于android:融云即时通讯SDK集成-定制UI二-添加自定义表情库

融云即时通讯 SDK 集成 — 定制 UI(二) ——增加自定义表情库

背景:

最近公司新上的 app 要加上即时通讯的性能, 本人疾速实现一个当然是不可能的了 (我的项目 deadline 也顶不住哇). 就从各家成熟的 SDK 厂商选来选去的, 各有各的好也各有各的有余. 最初点兵点将, 选了融云家的 SDK(老板说了算 hhhh).
他家的官网和文档地址:
官网:https://www.rongcloud.cn/
文档:https://docs.rongcloud.cn/v4
这个工作当然还是落在我的头上. 我是应用的他们家的带 UI 的 sdk,(他们家有带 UI 和不带 UI 的两种 sdk, 不带 UI 的 sdk 就是只有即时通讯能力, 所有的 UI 都须要开发者自定实现, 带 UI 的 sdk 封装了一些根本的界面, 例如会话列表, 和他人聊天的会话界面.)当然这些曾经集成了 UI 的 sdk 并不能齐全满足一个产品的需要, 所以这篇文章跟大家讲下如何增加一套自定义的表情包.

成果如下哈:

尽管这里有点难看了哈哈, 不过是为了给大家展现办法嘛, 就不论那么多了. 能够看到底下除了默认的 emoji 的表情包, 还多了一个 tab, 我是从 QQ 表情搞了一套, 间接就加在这里了. 一个可恶的小猪猪???? 哈哈哈.

增加步骤

须要改变的有这么几个类:

AndroidEmoji: 管制 emoji 图标资源, 编码, 以及相应展现的类
RongExtension: 会话界面除去聊天气泡与 title bar 的整个下方输出区域
IEmoticonTab: 表情 tab
DefaultExtensionModule: 表情 tab 的下层控件.

对于 AndroidEmoji 这个类, 能够间接照抄, 把资源文件替换成本人筹备好的图标, 以及编码 / 形容


public class ConversationListAdapter extends BaseAdapter<UIConversation> {
    private final static String TAG = "ConversationListAdapter";
    LayoutInflater mInflater;
    Context mContext;

    @Override
    public long getItemId(int position) {UIConversation conversation = getItem(position);
        if (conversation == null)
            return 0;
        return conversation.hashCode();}

    protected class ViewHolder {
        public View layout;
        public View leftImageLayout;
        public View rightImageLayout;
        public View leftUnReadView;
        public View rightUnReadView;
        public AsyncImageView leftImageView;
        public TextView unReadMsgCount;
        public ImageView unReadMsgCountIcon;
        public AsyncImageView rightImageView;
        public TextView unReadMsgCountRight;
        public ImageView unReadMsgCountRightIcon;
        public ProviderContainerView contentView;

    }

    public ConversationListAdapter(Context context) {super();
        mContext = context;
        mInflater = LayoutInflater.from(mContext);
    }

    public int findGatheredItem(Conversation.ConversationType type) {int index = getCount();
        int position = -1;
        while ((index-- > 0)) {UIConversation uiConversation = getItem(index);
            if (uiConversation.getConversationType().equals(type)) {
                position = index;
                break;
            }
        }
        return position;
    }

    public int findPosition(Conversation.ConversationType type, String targetId) {int index = getCount();
        int position = -1;
        while (index-- > 0) {if (getItem(index).getConversationType().equals(type)
                    && getItem(index).getConversationTargetId().equals(targetId)) {
                position = index;
                break;
            }
        }
        return position;
    }

    @Override
    protected View newView(Context context, int position, ViewGroup group) {View result = mInflater.inflate(R.layout.rc_item_conversation, null);

        ViewHolder holder = new ViewHolder();
        holder.layout = findViewById(result, R.id.rc_item_conversation);
        holder.leftImageLayout = findViewById(result, R.id.rc_item1);
        holder.rightImageLayout = findViewById(result, R.id.rc_item2);
        holder.leftUnReadView = findViewById(result, R.id.rc_unread_view_left);
        holder.rightUnReadView = findViewById(result, R.id.rc_unread_view_right);
        holder.leftImageView = findViewById(result, R.id.rc_left);
        holder.rightImageView = findViewById(result, R.id.rc_right);
        holder.contentView = findViewById(result, R.id.rc_content);
        holder.unReadMsgCount = findViewById(result, R.id.rc_unread_message);
        holder.unReadMsgCountRight = findViewById(result, R.id.rc_unread_message_right);
        holder.unReadMsgCountIcon = findViewById(result, R.id.rc_unread_message_icon);
        holder.unReadMsgCountRightIcon = findViewById(result, R.id.rc_unread_message_icon_right);
        result.setTag(holder);
        return result;
    }

    @Override
    protected void bindView(View v, int position, final UIConversation data) {ViewHolder holder = (ViewHolder) v.getTag();

        if (data == null) {return;}
        /* 通过会话类型,取得对应的会话 provider.ex: PrivateConversationProvider*/
        IContainerItemProvider provider = RongContext.getInstance().getConversationTemplate(data.getConversationType().getName());
        if (provider == null) {RLog.e(TAG, "provider is null");
            return;
        }

        View view = holder.contentView.inflate(provider);
        provider.bindView(view, position, data);

        // 设置背景色
        if (data.isTop())
            holder.layout.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.rc_item_top_list_selector));
        else
            holder.layout.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.rc_item_list_selector));


        ConversationProviderTag tag = RongContext.getInstance().getConversationProviderTag(data.getConversationType().getName());

        int defaultId;
        if (data.getConversationType().equals(Conversation.ConversationType.GROUP)) {defaultId = R.drawable.rc_default_group_portrait;} else if (data.getConversationType().equals(Conversation.ConversationType.DISCUSSION)) {defaultId = R.drawable.rc_default_discussion_portrait;} else {defaultId = R.drawable.rc_default_portrait;}
        // 1: 图像靠左显示。2:图像靠右显示。3:不显示图像。if (tag.portraitPosition() == 1) {holder.leftImageLayout.setVisibility(View.VISIBLE);

            holder.leftImageLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemClick(v, data);
                }
            });
            holder.leftImageLayout.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemLongClick(v, data);
                    return true;
                }
            });
            if (data.getConversationGatherState()) {holder.leftImageView.setAvatar(null, defaultId);
            } else {if (data.getIconUrl() != null) {holder.leftImageView.setAvatar(data.getIconUrl().toString(), defaultId);
                } else {holder.leftImageView.setAvatar(null, defaultId);
                }
            }

            if (data.getUnReadMessageCount() > 0) {holder.unReadMsgCountIcon.setVisibility(View.VISIBLE);
                setUnReadViewLayoutParams(holder.leftUnReadView, data.getUnReadType());
                if (data.getUnReadType().equals(UIConversation.UnreadRemindType.REMIND_WITH_COUNTING)) {if (data.getUnReadMessageCount() > 99) {holder.unReadMsgCount.setText(mContext.getResources().getString(R.string.rc_message_unread_count));
                    } else {holder.unReadMsgCount.setText(Integer.toString(data.getUnReadMessageCount()));
                    }
                    holder.unReadMsgCount.setVisibility(View.VISIBLE);
                    holder.unReadMsgCountIcon.setImageResource(R.drawable.rc_unread_count_bg);
                } else {holder.unReadMsgCount.setVisibility(View.GONE);
                    holder.unReadMsgCountIcon.setImageResource(R.drawable.rc_unread_remind_list_count);
                }
            } else {holder.unReadMsgCountIcon.setVisibility(View.GONE);
                holder.unReadMsgCount.setVisibility(View.GONE);
            }

            holder.rightImageLayout.setVisibility(View.GONE);
        } else if (tag.portraitPosition() == 2) {holder.rightImageLayout.setVisibility(View.VISIBLE);

            holder.rightImageLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemClick(v, data);
                }
            });
            holder.rightImageLayout.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemLongClick(v, data);
                    return true;
                }
            });

            if (data.getConversationGatherState()) {holder.rightImageView.setAvatar(null, defaultId);
            } else {if (data.getIconUrl() != null) {holder.rightImageView.setAvatar(data.getIconUrl().toString(), defaultId);
                } else {holder.rightImageView.setAvatar(null, defaultId);
                }
            }

            if (data.getUnReadMessageCount() > 0) {holder.unReadMsgCountRightIcon.setVisibility(View.VISIBLE);
                setUnReadViewLayoutParams(holder.rightUnReadView, data.getUnReadType());
                if (data.getUnReadType().equals(UIConversation.UnreadRemindType.REMIND_WITH_COUNTING)) {holder.unReadMsgCount.setVisibility(View.VISIBLE);
                    if (data.getUnReadMessageCount() > 99) {holder.unReadMsgCountRight.setText(mContext.getResources().getString(R.string.rc_message_unread_count));
                    } else {holder.unReadMsgCountRight.setText(Integer.toString(data.getUnReadMessageCount()));
                    }
                    holder.unReadMsgCountRightIcon.setImageResource(R.drawable.rc_unread_count_bg);
                } else {holder.unReadMsgCount.setVisibility(View.GONE);
                    holder.unReadMsgCountRightIcon.setImageResource(R.drawable.rc_unread_remind_without_count);
                }
            } else {holder.unReadMsgCountIcon.setVisibility(View.GONE);
                holder.unReadMsgCount.setVisibility(View.GONE);
            }

            holder.leftImageLayout.setVisibility(View.GONE);
        } else if (tag.portraitPosition() == 3) {holder.rightImageLayout.setVisibility(View.GONE);
            holder.leftImageLayout.setVisibility(View.GONE);
        } else {throw new IllegalArgumentException("the portrait position is wrong!");
        }
        MessageContent content = data.getMessageContent();
        if (content != null && content.isDestruct()) {RongIMClient.getInstance().getMessage(data.getLatestMessageId(), new RongIMClient.ResultCallback<Message>() {

                @Override
                public void onSuccess(Message message) {if (message == null) {EventBus.getDefault().post(new Event.MessageDeleteEvent(data.getLatestMessageId()));
                    }
                }

                @Override
                public void onError(RongIMClient.ErrorCode e) {}});
        }
    }

    protected void setUnReadViewLayoutParams(View view, UIConversation.UnreadRemindType type) {ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        Context context = view.getContext();
        if (type == UIConversation.UnreadRemindType.REMIND_WITH_COUNTING) {params.width = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_18);
            params.height = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_18);
            params.leftMargin = (int) mContext.getResources().getDimension(R.dimen.rc_dimen_size_44);
            params.topMargin = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_5);
        } else {params.width = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_9);
            params.height = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_9);
            params.leftMargin = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_50);
            params.topMargin = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_7);
        }
        view.setLayoutParams(params);
    }

    private OnPortraitItemClick mOnPortraitItemClick;

    public interface OnPortraitItemClick {void onPortraitItemClick(View v, UIConversation data);

        boolean onPortraitItemLongClick(View v, UIConversation data);
    }

    public void setOnPortraitItemClick(OnPortraitItemClick onPortraitItemClick) {this.mOnPortraitItemClick = onPortraitItemClick;}
}

集成 DefaultExtensionModule, 实现 MyExtensionModule, 重写 getEmoticonTabs()办法, 为每个图标设置监听.

@Override
    public List<IEmoticonTab> getEmoticonTabs() {List<IEmoticonTab> emoticonTabs =  super.getEmoticonTabs();
        MyEmoticonTab myEmoticonTab =new MyEmoticonTab();

        myEmoticonTab.setOnItemClickListener(new IEmojiItemClickListener() {
            @Override
            public void onEmojiClick(String emoji) {

                EditText editText = MyExtensionModule.this.mEditText;
                if (editText != null) {int start = editText.getSelectionStart();
                    editText.getText().insert(start, emoji);
                }
            }

            @Override
            public void onDeleteClick() {
                EditText editText = MyExtensionModule.this.mEditText;
                if (editText != null) {editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
                }
            }
        });
        emoticonTabs.add(myEmoticonTab);
        return emoticonTabs;
    }

继承 RongExtension, 实现 MyRongExtension, 而后获取到 editText, 为其设置监听, 代码如下:


public class MyRongExtension extends RongExtension {

    EditText mEditText;

    public MyRongExtension(Context context) {super(context);
        tryAddTextChangedAction();}

    public MyRongExtension(Context context, AttributeSet attrs) {super(context, attrs);

        tryAddTextChangedAction();}

    private void tryAddTextChangedAction() {mEditText = getInputEditText();
        TextWatcher textWatcher = new TextWatcher() {

            private int start;
            private int count;


            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                this.start = start;
                this.count = count;
            }

            @Override
            public void afterTextChanged(Editable s) {

                // 这块的测验规定是纯 emoji 的,加其余表情的话间接给他去掉,或者本人写规定。//                if (QQEmoji.isQQEmoji(s.subSequence(start, start + count).toString())) {mEditText.removeTextChangedListener(this);
                    String resultStr = QQEmoji.replaceEmojiWithText(s.toString());
                    mEditText.setText(QQEmoji.ensure(resultStr), TextView.BufferType.SPANNABLE);
                    mEditText.setSelection(mEditText.getText().length());
                    mEditText.addTextChangedListener(this);
//                }
            }
        };
        mEditText.addTextChangedListener(textWatcher);
    }


}

这样一来, 就功败垂成啦. 增加好了一套属于本人的表情包!

退出移动版