EaseUI 使用指南


内容已不再维护,请参考 EaseIMKit 使用指南

EaseUI 是一个 UI 库,封装了 IM 功能常用的控件、fragment 等等,旨在帮助开发者快速集成环信 SDK。

Fragment 的使用更适用于ui改动较少或者着急出功能的开发者,建议开发者基于 EaseUI 的控件做开发,这样更灵活(后续会把 fragment 级别的封装放到 demo 里)。

EaseUI 包含一个最简单的使用 demo:simpledemo,开发者可导出查看。

EaseUI 及 Demo 的 GitHub 下载地址为:

3.0 的代码需要切换到 SDK3.0 分支。

注意:因为这是一个 UI 库,后续很可能还会继续改动,新旧版本在 API 的兼容上不会像 IM SDK 那样绝对的兼容。

注意:单独使用 EaseUI 时请参考 demo 中的实现,确保申请了相关的权限。

以下是 EaseUI 集成参考视频,您可以通过视频学习如何集成环信 SDK。

EaseUI 库的代码是开源的,下载的 SDK 压缩包里面已经包含此库,解压后路径为 /examples/easeui。

Eclipse 中导入

  1. 先把 EaseUI 项目导入到 Eclipse 中。
  2. 在自己的项目中把 EaseUI 作为一个 library 引入。右键你的项目→Android→点击右下角的Add按钮→选中 EaseUI→OK→OK。

Android Studio 中导入

打开你的 AS 项目→File→New→Import Module→选择或输入 EaseUI 库路径→Next→Next→Finish。

导入完可能会有如下错误:

导入后可能会出现的错误

找到相应报错的地方把 swipeRefreshLayout.setColorSchemeResources 改成 swipeRefreshLayout.setColorSchemeViewCompat.getX 改成 new ViewCompat().getX,然后重新 build 即可。

或者,把 v4 包的版本号加大,譬如 compile 'com.android.support:support-v4:23.1.1'。

  • EaseChatMessageList – 聊天消息列表控件
  • EaseConversationList – 会话列表控件
  • EaseContactList – 联系人列表页面
  • EaseChatInputMenu – 聊天输入菜单栏-
  • EaseImageView – 自定义的 ImageView,支持设置 ImageView 形状、倒角大小等
  • EaseTitleBar – 标题栏
  • 其他控件,后文会挑选一些介绍

这里对聊天页面几个控件做简单图示:

主要控件

  • EaseChatFragment – 聊天页面,最主要的 fragment
  • EaseConversationListFragment – 会话列表页面
  • EaseContactListFragment – 联系人页面

主要fragment

正式使用 EaseUI 需要先调用初始化方法,在 Application 的 oncreate 里调用初始化。

EMOptions options = new EMOptions();
// 默认添加好友时,是不需要验证的,改成需要验证
options.setAcceptInvitationAlways(false);
...
EaseUI.getInstance().init(applicationContext, options);

注意:使用 EaseUI 中的自定义控件时,如果需要 xml 中设置其属性(具体哪些属性可查看 attrs 文件), 务必在 xml 根节点中加上 xmlns:hyphenate=“http://schemas.android.com/apk/res-auto

标题栏控件 EaseTitleBar 使用

标题栏控件 EaseTitleBar 使用

在 xml 中声明标题栏控件,可以在 xml 直接设置标题内容,左右图片,在 Java 文件中亦可以设置这些属性以及相关的点击事件。

示例:

<com.hyphenate.easeui.widget.EaseTitleBar
	android:id="@+id/title_bar"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	hyphenate:titleBarLeftImage="@drawable/ease_mm_title_back" /> 

titleBar = (EaseTitleBar) getView().findViewById(R.id.title_bar);
titleBar.setTitle("张建国");
titleBar.setRightImageResource(R.drawable.ease_mm_title_remove);

可以调用 fragment 里的 hideTitleBar() 隐藏标题栏

聊天消息列表控件 EaseChatMessageList 使用

聊天消息列表控件EaseChatMessageList使用

EaseChatMessageList默认包含文字、表情、图片、语音、视频、文件消息的显示。

使用该控件,可以在 xml 中设置其 item(chatrow) 的背景图片,是否显示用户头像、昵称等属性。

<com.hyphenate.easeui.widget.EaseChatMessageList
	android:id="@+id/message_list"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	hyphenate:msgListShowUserNick="false"
	 />

常用API:

messageList = (EaseChatMessageList) getView().findViewById(R.id.message_list);
//初始化messagelist
messageList.init(toChatUsername, chatType, null);
//设置item里的控件的点击事件
messageList.setItemClickListener(new EaseChatMessageList.MessageListItemClickListener() {
	
	@Override
	public void onUserAvatarClick(String username) {
		//头像点击事件
	}
	
	@Override
	public void onResendClick(final EMMessage message) {
		//重发消息按钮点击事件
	}
	
	@Override
	public void onBubbleLongClick(EMMessage message) {
		//气泡框长按事件
	}
	
	@Override
	public boolean onBubbleClick(EMMessage message) {
		//气泡框点击事件,EaseUI有默认实现这个事件,如果需要覆盖,return值要返回true
		return false; 
	}
});
//获取下拉刷新控件
swipeRefreshLayout = messageList.getSwipeRefreshLayout();
//刷新消息列表
messageList.refresh();
messageList.refreshSeekTo(position);
messageList.refreshSelectLast();

自定义 EaseChatMessageList 的 item(chatrow)

自定义 EaseChatMessageList 的 item(chatrow)

在 EaseUI 里,每一个 messagelist 的 item 称为一个 chatrow,开发者可以覆盖默认的 chatrow 或者自定义自己的 chatrow。

简单示例(具体可参考的 chatfragment 和 easechatfragment 类):

private final class CustomChatRowProvider implements EaseCustomChatRowProvider {
	@Override
	public int getCustomChatRowTypeCount() {
		//音、视频通话发送、接收共 4 种
		return 4;
	}

	@Override
	public int getCustomChatRowType(EMMessage message) {
		if(message.getType() == EMMessage.Type.TXT){
			//语音通话类型
			if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false)){
				return message.direct == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VOICE_CALL : MESSAGE_TYPE_SENT_VOICE_CALL;
			}else if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){
				//视频通话
				return message.direct == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VIDEO_CALL : MESSAGE_TYPE_SENT_VIDEO_CALL;
			}
		}
		return 0;
	}

	@Override
	public EaseChatRow getCustomChatRow(EMMessage message, int position, BaseAdapter adapter) {
		if(message.getType() == EMMessage.Type.TXT){
			// 语音通话、视频通话
			if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false) ||
				message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){
				//ChatRowVoiceCall为一个继承自EaseChatRow的类
				return new ChatRowVoiceCall(getActivity(), message, position, adapter);
			}
		}
		return null;
	}
}
//初始化的时候把 provider 传入
messageList.init(toChatUsername, chatType, new CustomChatRowProvider());

chatrow 基类里默认会去查找头像、气泡框等控件,但是并不强制子类一定要有这些控件,子类的布局可以和基类是完全不一样的。

底部操作栏 EaseChatInputMenu 使用

底部操作栏EaseChatInputMenu使用1 底部操作栏EaseChatInputMenu使用2

EaseChatInputMenu包含3个控件:

  • EaseChatPrimaryMenu(主菜单栏,包含文字输入、发送等功能)
  • EaseChatExtendMenu(扩展栏,点击加号按钮出来的小宫格的菜单栏)
  • EaseEmojiconMenu(表情栏)

xml 中使用示例:

<com.hyphenate.easeui.widget.EaseChatInputMenu
	android:id="@+id/input_menu"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:layout_alignParentBottom="true" />

EaseChatPrimaryMenu 扩展:

考虑到 EaseChatPrimaryMenu 变动的复杂性,EaseUI 未提供具体修改的 API,但是提供了一个 API 让开发者替换成自己写的控件。

/**
 * 设置自定义的表情栏,该控件需要继承自EaseEmojiconMenuBase,
 * 以及回调你想要回调出去的事件给设置的EaseEmojiconMenuListener
 * @param customEmojiconMenu
 */
public void setCustomEmojiconMenu(EaseEmojiconMenuBase customEmojiconMenu){
	this.emojiconMenu = customEmojiconMenu;
}

通过 inputmenu 对象调用此方法就行。

EaseChatExtendMenu 扩展:

扩展菜单栏默认是不包含任何按钮的(EaseChatFragment 中会默认加上拍照、图片、位置),通过调用 registerExtendMenuItem 就行。

inputMenu = (EaseChatInputMenu) getView().findViewById(R.id.input_menu);
//注册底部菜单扩展栏item
//传入item对应的文字,图片及点击事件监听,extendMenuItemClickListener实现EaseChatExtendMenuItemClickListener
inputMenu.registerExtendMenuItem(R.string.attach_video, R.drawable.em_chat_video_selector, ITEM_VIDEO, extendMenuItemClickListener);
inputMenu.registerExtendMenuItem(R.string.attach_file, R.drawable.em_chat_file_selector, ITEM_FILE, extendMenuItemClickListener);
...

EaseEmojiconMenu扩展:

EaseEmojiconMenu 默认包含一套默认的表情,通过 API 可替换或增加表情。

两种方法:

  • 调用 inputmenu init 方法的时候传入表情组列表,传 null 会显示一套默认表情,inputMenu.init(null);
  • 通过获取到 EmojiconMenu 对象添加或删除表情组
((EaseEmojiconMenu)inputMenu.getEmojiconMenu()).addEmojiconGroup(EmojiconExampleGroupData.getData()),
((EaseEmojiconMenu)inputMenu.getEmojiconMenu()).removeEmojiconGroup(1)

如果想完全自己实现这套表情的布局,通过调用 setCustomEmojiconMenu 实现。

/**
 * 设置自定义的表情栏,该控件需要继承自EaseEmojiconMenuBase,
 * 以及回调你想要回调出去的事件给设置的EaseEmojiconMenuListener
 * @param customEmojiconMenu
 */
public void setCustomEmojiconMenu(EaseEmojiconMenuBase customEmojiconMenu){
	this.emojiconMenu = customEmojiconMenu;
}

整体代码示例:

inputMenu = (EaseChatInputMenu) getView().findViewById(R.id.input_menu);
//注册底部菜单扩展栏item
//传入item对应的文字,图片及点击事件监听,extendMenuItemClickListener实现EaseChatExtendMenuItemClickListener
inputMenu.registerExtendMenuItem(R.string.attach_video, R.drawable.em_chat_video_selector, ITEM_VIDEO, extendMenuItemClickListener);
inputMenu.registerExtendMenuItem(R.string.attach_file, R.drawable.em_chat_file_selector, ITEM_FILE, extendMenuItemClickListener);

//初始化,此操作需放在registerExtendMenuItem后
inputMenu.init();
//设置相关事件监听
inputMenu.setChatInputMenuListener(new ChatInputMenuListener() {

	@Override
	public void onSendMessage(String content) {
		// 发送文本消息
		sendTextMessage(content);
	}

	@Override
	public boolean onPressToSpeakBtnTouch(View v, MotionEvent event) {
		////把touch事件传入到EaseVoiceRecorderView 里进行录音
		return voiceRecorderView.onPressToSpeakBtnTouch(v, event, new EaseVoiceRecorderCallback() {
			@Override
			public void onVoiceRecordComplete(String voiceFilePath, int voiceTimeLength) {
				// 发送语音消息
				sendVoiceMessage(voiceFilePath, voiceTimeLength);
			}
		});
	}
});

会话列表 EaseConversationList 使用

可在 xml 中设置 listview 的 item 的文字颜色、大小等,具体可查看 attrs 定义的 EaseConversationList 里的属性。

示例:

<com.hyphenate.easeui.widget.EaseConversationList
	android:id="@+id/list"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:background="@android:color/transparent"
	android:cacheColorHint="#00000000"
	android:divider="@null"
	hyphenate:cvsListPrimaryTextSize="16sp"/>

API 调用示例:

//会话列表控件
conversationListView = (EaseConversationList) getView().findViewById(R.id.list);
//初始化,参数为会话列表集合
conversationListView.init(conversationList);
//刷新列表
conversationListView.refresh();

其他方法参照 listview 使用即可。

联系人列表控件 EaseContactList 使用

可直接在 xml 里设置 list item 文字颜色、大小等等,详细可设置的属性可查看 attrs 文件。

示例:

<com.hyphenate.easeui.widget.EaseContactList
	android:id="@+id/contact_list"
	android:layout_width="match_parent"
	android:layout_height="match_parent" 
	hyphenate:ctsListInitialLetterBg="#abc"/>            

API 调用示例:

contactListLayout = (EaseContactList) getView().findViewById(R.id.contact_list);        
//初始化时需要传入联系人list
contactListLayout.init(contactList);
//刷新列表
contactListLayout.refresh();

EaseImageView使用

自定义的ImageView,默认是矩形,支持设置ImageView形状、倒角大小等, 在xml和java文件中都可以设置

示例:

xml:

<com.hyphenate.easeui.widget.EaseImageView
    android:id="@+id/iv_userhead"
	android:layout_width="@dimen/size_avatar"
	android:layout_height="@dimen/size_avatar"
	android:src="@drawable/ease_default_avatar"
	app:ease_shape_type="round"
	android:scaleType="fitXY" />

app:ease_shape_type=“round”表示将控件设置成圆形的,更多选项可以通过AS提示查看

java:

EaseImageView avatarView = (EaseImageView) findViewById(R.id.iv_userhead);
//设置倒角
imageView.setRadius(5);
//设置成圆形,设成2为矩形
imageView.setShapeType(1);
//设置边框
imageView.setBorderWidth();
imageView.setBorderColor();

开发者可以直接启动fragment,或者继承easeui中的fragment扩展自己所需的功能

启动聊天会话 fragment

new 出 EaseChatFragment 或者其子类,调用 setArguments 方法传入 chatType(会话类型)和 userId(用户或群id),通过 getSupportFragmentManager() 启动 fragment。

//new出EaseChatFragment或其子类的实例
 EaseChatFragment chatFragment = new EaseChatFragment();
 //传入参数
 Bundle args = new Bundle();
 args.putInt(EaseConstant.EXTRA_CHAT_TYPE, EaseConstant.CHATTYPE_GROUP);
 args.putString(EaseConstant.EXTRA_USER_ID, "zw123");
 chatFragment.setArguments(args);
 getSupportFragmentManager().beginTransaction().add(R.id.container, chatFragment).commit();

继承 EaseChatFragment 实现会话页面

继承 EaseChatFragment扩展自己所需要的功能

由于聊天页面比较复杂,EaseUI 把 fragment 中常见的扩展功能放到一个 interface——EaseChatFragmentHelper 中,在setUpView()方法中调用setChatFragmentListener实现需要的功能,具体代码可参考 EaseUIDemo。

public interface EaseChatFragmentHelper{
	/**
	 * 设置消息扩展属性
	 */
	void onSetMessageAttributes(EMMessage message);
	/**
	 * 进入会话详情
	 */
	void onEnterToChatDetails();
	/**
	 * 用户头像点击事件
	 * @param username
	 */
	void onAvatarClick(String username);
	/**
	 * 消息气泡框点击事件
	 */
	boolean onMessageBubbleClick(EMMessage message);
	/**
	 * 消息气泡框长按事件
	 */
	void onMessageBubbleLongClick(EMMessage message);
	/**
	 * 扩展输入栏item点击事件,如果要覆盖EaseChatFragment已有的点击事件,return true
	 * @param view 
	 * @param itemId 
	 * @return
	 */
	boolean onExtendMenuItemClick(int itemId, View view);
	/**
	 * 设置自定义chatrow提供者
	 * @return
	 */
	EaseCustomChatRowProvider onSetCustomChatRowProvider();
}

虽然标题栏控件提供了修改的 API,但是如果完全不想要时,可以调用隐藏方法(所有 fragment 都提供此方法)。

//隐藏标题栏
hideTitleBar();
//显示标题栏
showTitleBar();

其他可根据自己需求调用或者覆盖某些方法。

直接启动 EaseConversationListFragment

示例:

conversationListFragment = new EaseConversationListFragment();
conversationListFragment.setConversationListItemClickListener(new EaseConversationListItemClickListener() {
            
	@Override
	public void onListItemClicked(EMConversation conversation) {
		startActivity(new Intent(MainActivity.this, ChatActivity.class).putExtra(EaseConstant.EXTRA_USER_ID, conversation.getUserName()));
	}
});
//通过getSupportFragmentManager启动fragment即可

继承 EaseConversationListFragment 扩展 fragment

此页面比较简单,调用 conversationListView 设置 item 点击事件,其余按自己需求编写即可,譬如 listview 长按事件,可参考 Demo。

//conversationListView为EaseConversationList
conversationListView.setOnItemClickListener(new OnItemClickListener() {})

直接启动EaseContactListFragment

示例:

contactListFragment= new EaseContactListFragment();
//需要设置联系人列表才能启动fragment
contactListFragment.setContactsMap(getContacts());
//设置item点击事件
contactListFragment.setContactListItemClickListener(new EaseContactListItemClickListener() {
            
            @Override
            public void onListItemClicked(EaseUser user) {
                startActivity(new Intent(MainActivity.this, ChatActivity.class).putExtra(EaseConstant.EXTRA_USER_ID, user.getUsername()));
            }
        });

继承自 EaseContactListListFragment

同 EaseConversationListFragment 一样,此 fragment 比较简单,注意在setUpView()里调用setContactsMap即可,其余按需求自由实现,可参考 ContactListFragment。

设置用户信息提供者

设置了此提供者后,EaseUI 里的 fragment 及相关控件就会自动显示用户头像和昵称了,当然前提是你设置的 provider 返回的 user 对象设置了昵称和头像地址。

示例(具体可参考 demohelper 类):

//get easeui instance
easeUI = EaseUI.getInstance();
//需要EaseUI库显示用户头像和昵称设置此provider
easeUI.setUserProfileProvider(new EaseUserProfileProvider() {
            
    @Override
    public EaseUser getUser(String username) {
       return getUserInfo(username);
    }
});

设置声音振动等提示的提供者(不设置则使用 EaseUI 默认的)

easeUI.setSettingsProvider(new EaseSettingsProvider() {})

设置表情信息提供者

表情的显示,通过设置此 provider 实现。

//设置表情provider
easeUI.setEmojiconInfoProvider(new EaseEmojiconInfoProvider() {
	
	@Override
	public EaseEmojicon getEmojiconInfo(String emojiconIdentityCode) {
		//通过表情id返回具体表情数据
		EaseEmojiconGroupEntity data = EmojiconExampleGroupData.getData();
		for(EaseEmojicon emojicon : data.getEmojiconList()){
			if(emojicon.getIdentityCode().equals(emojiconIdentityCode)){
				return emojicon;
			}
		}
		return null;
	}

	@Override
	public Map<String, Object> getTextEmojiconMapping() {
		//返回文字表情emoji文本和图片(resource id或者本地路径)的映射map
		return null;
	}
});

设置通知栏内容提供者(不设置则使用默认的)

示例:

easeUI.getNotifier().setNotificationInfoProvider(new EaseNotificationInfoProvider() {
	
	@Override
	public String getTitle(EMMessage message) {
	  //修改标题,这里使用默认
		return null;
	}
	
	@Override
	public int getSmallIcon(EMMessage message) {
	  //设置小图标,这里为默认
		return 0;
	}
	
	@Override
	public String getDisplayedText(EMMessage message) {
		// 设置状态栏的消息提示,可以根据message的类型做相应提示
		String ticker = EaseCommonUtils.getMessageDigest(message, appContext);
		if(message.getType() == Type.TXT){
			ticker = ticker.replaceAll("\\[.{2,3}\\]", "[表情]");
		}
		EaseUser user = getUserInfo(message.getFrom());
		if(user != null){
			return getUserInfo(message.getFrom()).getNick() + ": " + ticker;
		}else{
			return message.getFrom() + ": " + ticker;
		}
	}
	
	@Override
	public String getLatestText(EMMessage message, int fromUsersNum, int messageNum) {
		return null;
		// return fromUsersNum + "个基友,发来了" + messageNum + "条消息";
	}
	
	@Override
	public Intent getLaunchIntent(EMMessage message) {
		//设置点击通知栏跳转事件
		Intent intent = new Intent(appContext, ChatActivity.class);
		//有电话时优先跳转到通话页面
		if(isVideoCalling){
			intent = new Intent(appContext, VideoCallActivity.class);
		}else if(isVoiceCalling){
			intent = new Intent(appContext, VoiceCallActivity.class);
		}else{
			ChatType chatType = message.getChatType();
			if (chatType == ChatType.Chat) { // 单聊信息
				intent.putExtra("userId", message.getFrom());
				intent.putExtra("chatType", Constant.CHATTYPE_SINGLE);
			} else { // 群聊信息
				// message.getTo()为群聊id
				intent.putExtra("userId", message.getTo());
				if(chatType == ChatType.GroupChat){
					intent.putExtra("chatType", Constant.CHATTYPE_GROUP);
				}else{
					intent.putExtra("chatType", Constant.CHATTYPE_CHATROOM);
				}
				
			}
		}
		return intent;
	}
});

上一页:Demo 介绍