| 位置 | 定制点 | 定制方式 |
|---|---|---|
| 顶部标题栏 | 整个标题栏(支持隐藏) | 实现接口 |
| 消息气泡 | 文本消息和语音消息 | 实现接口 |
| 消息中URL | URL点击事件 | 实现接口 |
| 消息中数字字符串 | 点击事件 | 实现接口 |
| 底部消息栏“+” | +”内增加选项 | 实现接口 |
| 自定义消息 | 展示、点击和长按事件 | 实现接口 |
| 地理位置消息 | 消息展示、点击和长按事件 | 实现接口 |
| 语音消息播放 | 使用听筒或者扬声器模式播放语音消息 | 实现接口 |
| 自定义消息展示 | 不包含头像的自定义消息展示 | 实现接口 |
| 背景 | 背景颜色或图片 | 实现接口 |
| 聊天界面头像样式 | 圆角正方形、直角正方形、圆形 | 实现接口 |
| 聊天底部工具栏(ChattingReplyBar) | 允许自定义高度,隐藏语音表情发送按钮 | 实现接口 |
| 聊天底部工具栏扩展(ChattingReplyBar) | 允许自定义插件item位置,添加新的item,修改原有item,设置是否隐藏,设置点击事件 | 实现接口 |
| 表情扩展 | 可以添加自定义Emoji表情或者图片表情 | 方法调用 |
| 默认头像修改 | 默认头像图片 | 实现接口 |
| 聊天窗口顶部 | 聊天窗口顶部悬浮自定义view | 实现接口 |
| 商品消息 | 自定义商品消息展示样式 | 实现接口 |
| 文本消息文字颜色 | 自定义文本消息的文字颜色 | 实现接口 |
| 会话列表和聊天窗口dimens | 自定义会话列表和聊天窗口部分dimens | 修改资源文件 |
| 打开聊天窗口 | 打开聊天窗口自动发送一条消息,支持本地隐藏 | 实现接口 |
| 消息时间 | 自定义时间文案 | 实现接口 |
聊天窗口:IMChattingPageUI, IMChattingPageOperateion

具体请参考工程NotificationInitSampleHelper
//设置消息的聊天气泡背景处理器,可以自定义设置文本以及图片消息的背景图,详细参见demo中的 ChattingUICustomSample 类
//第一步:新增类 ChattingUICustomSample
public class ChattingUICustomSample extends IMChattingPageUI{
/**
* 设置消息气泡背景图,需要.9图
* @param conversation 当前消息所在会话
* @param message 需要设置背景的消息
* @param self 是否是自己发送的消息,true:自己发送的消息, false:别人发送的消息
* @return 0: 默认背景 -1:透明背景(无背景) >0:使用用户设置的背景图
*/
@Override
public int getMsgBackgroundResId(YWConversation conversation, YWMessage message, boolean self) {
int msgType = message.getSubType();
if (msgType == YWMessage.SUB_MSG_TYPE.IM_TEXT || msgType == YWMessage.SUB_MSG_TYPE.IM_AUDIO){
if (self){
return R.drawable.demo_talk_pop_r_bg;
} else {
return R.drawable.demo_talk_pop_l_bg;
}
} else if (msgType == YWMessage.SUB_MSG_TYPE.IM_IMAGE){
if (self){
return R.drawable.demo_talk_pic_pop_r_bg;
} else {
return R.drawable.demo_talk_pic_pop_l_bg;
}
} else if (msgType == YWMessage.SUB_MSG_TYPE.IM_VIDEO){
if (self){
return R.drawable.demo_talk_pic_pop_r_bg;
} else {
return R.drawable.demo_talk_pic_pop_l_bg;
}
} else if (msgType == YWMessage.SUB_MSG_TYPE.IM_GEO){
if (self){
return R.drawable.aliwx_comment_r_bg;
} else {
return R.drawable.aliwx_comment_l_bg;
}
} else if (msgType == YWMessage.SUB_MSG_TYPE.IM_P2P_CUS || msgType == YWMessage.SUB_MSG_TYPE.IM_TRIBE_CUS){
if (self){
return -1;
} else {
return -1;
}
}
return super.getMsgBackgroundResId(conversation, message, self);
//第二步:在Applicatoin类里将这个自定义接口绑定到单聊界面,加入以下代码(对于单聊界面的所有自定义UI定制只需要加一次)
AdviceBinder.bindAdvice(PointCutEnum.CHATTING_FRAGMENT_UI_POINTCUT,ChattingCustomAdviceSample.class);
新增根据会话类型选择性隐藏ChattingReplyBar的接口,其它item隐藏请使用adjustCustomInputViewPlugins()方法
示例代码在ChattingUICustomSample.java中
/**
* 是否隐藏底部ChattingReplyBar
* @param conversation
* @return
*/
@Override
public boolean needHideChattingReplyBar(YWConversation conversation) {
return false;
}
/**
* 返回自定义ChattingReplyBar高度(单位为dp)
* @return
* 如果返回值小于等于0,则使用默认值
*/
@Override
public int getCustomChattingReplyBarHeight() {
return 0;
}
/**
* 返回自定义聊天输入框高度(单位为dp)
* @return
* 如果返回值小于等于0,则使用默认值
*/
@Override
public int getCustomChattingInputEditTextHeight() {
return 0;
}
/**
* 修改ChattingReplyBar上的item,可以修改属性或者新增。如果开发者相同类型的会话plugin一样,则可以缓存pluginItems,
* 在该方法调用时直接用缓存pluginItems替换掉参数中的pluginItems,替换方式为先removeAll,再addAll
* 可以修改的属性包括:
* 顺序,setIndex(int)方式
* 是否显示(YWInputViewPlugin#setNeedHide(boolean))
* Item对应的View的基本操作,
*
* SDK默认按钮的id为:
* YWChattingPlugin.ReplyBarPlugin#VOICE_VIEW
* YWChattingPlugin.ReplyBarPlugin#INPUT_EDIT_TEXT
* YWChattingPlugin.ReplyBarPlugin#FACE_VIEW
* YWChattingPlugin.ReplyBarPlugin#EXPAND_VIEW
*
*
* 如果新增则创建一个{@link YWInputViewPlugin}并添加到replyBarItems。
* @param conversation ChattingReplyBar所在会话,如果开发者需要可以根据会话类型对ChattingReplyBar的item进行调整
* @param pluginItems item列表,初始是包含sdk默认提供的4个item:语音按钮、输入框、表情按钮、”+号“按钮,顺序索引为0,1,2,3
* @return 使用sdk默认顺序则无需任何操作
*/
@Override
public List<YWInputViewPlugin> adjustCustomInputViewPlugins(final Fragment fragment, YWConversation conversation, List<YWInputViewPlugin> pluginItems) {
if (pluginItems != null && pluginItems.size() > 0) {
//对默认项进行操作,可以使用id判断具体是哪一个
for (YWInputViewPlugin plugin : pluginItems) {
if (plugin.getId() == YWChattingPlugin.ReplyBarPlugin.VOICE_VIEW) {
plugin.setNeedHide(true);//隐藏语音输入按钮
}
}
//自定义新增的plugin只需要在布局中设置marginLeft即可
final View plugin = LayoutInflater.from(fragment.getActivity()).inflate(R.layout.demo_extra_item_layout, null);
//TODO 新增项id必须从4开始
final YWInputViewPlugin pluginToAdd = new YWInputViewPlugin(plugin, 4);
plugin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(fragment.getActivity(), "你点击了Id为:" + pluginToAdd.getId() + "的新增item", Toast.LENGTH_LONG).show();
}
});
pluginToAdd.setIndex(0);//在设置index时,如果新增项和默认pluginItem一样则开发者添加的显示在前
pluginItems.add(pluginToAdd);
}
}
示例代码在ChattingUICustomSample.java中
/**
* 返回单聊默认头像资源Id
* @return
* 0:使用SDK默认提供的
*/
@Override
public int getDefaultHeadImageResId() {
return 0;
}
开发者可以替换整个聊天窗口的标题栏。
具体参考demo工程ChattingUICustomSample

默认提供“拍照”,“选择图片”两种方式。开发者可以根据需求新增item
详细参见demo中的 ChattingCustomAdviceSample 类 实现方法:
//第一步:新增类,返回自定义的View
public class ChattingOperationCustomSample extends IMChattingPageOperateion
public List<ReplyBarItem> getReplybarItems(Fragment pointcut,YWConversation conversation) {
List<ReplyBarItem> replyBarItems = new ArrayList<ReplyBarItem>();
if(conversation.getConversationType()==YWConversationType.P2P){
ReplyBarItem replyBarItem = new ReplyBarItem();
replyBarItem.setItemId(1);
replyBarItem.setItemImageRes(R.drawable.aliwx_s001);
replyBarItem.setItemLabel("自定义的item1");
replyBarItems.add(replyBarItem1);
}
return replyBarItems;
}
//当自定义的item点击时的回调
public void onReplyBarItemClick(Fragment pointcut,ReplyBarItem item,YWConversation conversation) {
Toast.makeText(pointcut.getActivity(), "title button click!"+item.getItemId(), Toast.LENGTH_SHORT).show();
}
//第二步:在Applicatoin类里将这个自定义接口绑定到单聊界面,加入以下代码(对于单聊界面的所有自定义UI定制只需要加一次)
AdviceBinder.bindAdvice(PointCutEnum.CHATTING_FRAGMENT_OPERATION_POINTCUT,ChattingOperationCustomSample.class);
此功能可实现开发者希望自己处理消息中点击URL的点击响应,比如用内部webview打开,而非默认三方浏览器 详细参见demo中的 ChattingOperationCustomSample类 实现方法:
//第一步:新增类并继承自 IMChattingPageOperateion,同时重写onUrlClick方法
public class ChattingCustomAdviceSample extends IMChattingPageOperateion
public boolean onUrlClick(Fragment fragment, YWMessage message, String url,YWConversation conversation) {
Toast.makeText(fragment.getActivity(),"用户点击了url:"+url, Toast.LENGTH_LONG).show();
return false;
}
//第二步:在Applicatoin类里将这个自定义接口绑定到单聊界面,加入以下代码(对于单聊界面的所有自定义UI定制只需要加一次)
AdviceBinder.bindAdvice(PointCutEnum.CHATTING_FRAGMENT_OPERATION_POINTCUT,ChattingOperationCustomSample.class);
此功能可实现开发者希望自己处理地理位置消息的显示、点击和长按行为 详细参见demo中的 ChattingOperationCustomSample 类 实现方法:
//第一步:新增类,实现地理位置消息的显示、点击和长按行为
public class ChattingCustomAdviceSample extends IMChattingPageOperateion{
@Override
public View getCustomGeoMessageView(Fragment fragment, YWMessage msg) {
YWGeoMessageBody messageBody = (YWGeoMessageBody)message.getMessageBody();
String content = "纬度: " + messageBody.getLatitude() + ", 经度: " + messageBody.getLongitude() + ", 地址: " + messageBody.getAddress();
LinearLayout layout = (LinearLayout) View.inflate(
DemoApplication.getApplication(),
R.layout.demo_custom_tribe_msg_layout, null);
TextView textView = (TextView) layout.findViewById(R.id.msg_content);
textView.setText(content);
return layout;
}
//第二步:在Applicatoin类里将这个自定义接口绑定到单聊界面,加入以下代码(对于单聊界面的所有自定义UI定制只需要加一次)
AdviceBinder.bindAdvice(PointCutEnum.CHATTING_FRAGMENT_OPERATION_POINTCUT,ChattingOperationCustomSample.class);
此功能可实现开发者希望自己处理自定义消息的显示和点击行为 详细参见demo中的 ChattingOperationCustomSample类 实现方法:
//第一步:用户创建自定义消息
public static YWMessage createCustomMessage(YWConversationType type) {
// 发送自定义消息
YWMessageBody messageBody = new YWMessageBody();
// 请注意这里不一定要是JSON格式,这里纯粹是为了演示的需要
JSONObject object = new JSONObject();
try {
object.put("myData1", "自定义数据" + count++);
object.put("type", 1);
} catch (JSONException e) {
e.printStackTrace();
}
messageBody.setContent(object.toString());// 用户要发送的自定义消息,SDK不关心具体的格式,比如用户可以发送JSON格式
messageBody.setSummary("消息摘要");// 可以理解为消息的标题,用于显示会话列表和消息通知栏
// 注意,这里是群自定义消息
if (type == YWConversationType.Tribe) {
return YWMessageChannel.createTribeCustomMessage(messageBody);
}
// 注意,这里是单聊自定义消息
return YWMessageChannel.createCustomMessage(messageBody);
}
//第二步:新增类,实现自定义消息的显示
public class ChattingOperationCustomSampleextends IMChattingPageOperateion{
@Override
public View getCustomMessageView(Fragment fragment, YWMessage msg) {
String data = "";
if (msg.getMessageBody().getExtraData() != null) {
// 这里的ExtraData主要是方便用户在内存中存储数据,这样有些复杂的消息就不需要反复地去解析
data = (String) msg.getMessageBody().getExtraData();
} else {
// 没有解析过,则解析一遍,然后临时存储到Extradata中
String content = msg.getMessageBody().getContent();
JSONObject object = JSON.parseObject(content);
data = object.getString("myData1");
msg.getMessageBody().setExtraData(data);
}
LinearLayout layout = (LinearLayout) View.inflate(
DemoApplication.getContext(),
R.layout.demo_custom_tribe_msg_layout, null);
TextView textView = (TextView) layout.findViewById(R.id.msg_content);
textView.setText(data);
return layout;
}
//第三步:在Applicatoin类里将这个自定义接口绑定到单聊界面,加入以下代码(对于单聊界面的所有自定义UI定制只需要加一次)
AdviceBinder.bindAdvice(PointCutEnum.CHATTING_FRAGMENT_OPERATION_POINTCUT,ChattingOperationCustomSample.class);
/**
* 定制点击消息事件, 每一条消息的点击事件都会回调该方法,开发者根据消息类型,对不同类型的消息设置不同的点击事件
* @param fragment 聊天窗口fragment对象
* @param message 被点击的消息
* @return true:使用用户自定义的消息点击事件,false:使用默认的消息点击事件
*/
@Override
public boolean onMessageClick(Fragment fragment, YWMessage message) {
Notification.showToastMsg(fragment.getActivity(), "触发了自定义MessageClick事件");
if (message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_GEO){
Notification.showToastMsg(fragment.getActivity(), "你点击了地理位置消息消息");
return true;
} else if (message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_P2P_CUS || message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_TRIBE_CUS){
Notification.showToastMsg(fragment.getActivity(), "你点击了自定义消息");
return true;
}
return false;
}
/**
* 定制长按消息事件,每一条消息的长按事件都会回调该方法,开发者根据消息类型,对不同类型的消息设置不同的长按事件
* @param fragment 聊天窗口fragment对象
* @param message 被点击的消息
* @return true:使用用户自定义的长按消息事件,false:使用默认的长按消息事件
*/
@Override
public boolean onMessageLongClick(final Fragment fragment, final YWMessage message) {
if (message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_IMAGE || //自定义图片长按的事件处理,无复制选项。
message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_GIF
) {
new YWAlertDialog.Builder(fragment.getActivity()).setTitle(getShowName(WXAPI.getInstance().getConversationManager().getConversationByConversationId(message.getConversationId()))).setItems(new String[]{"删除"}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
WXAPI.getInstance().getConversationManager().getConversationByConversationId(message.getConversationId()).getMessageLoader().deleteMessage(message);
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).create().show();
return true;
} else if (message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_AUDIO) {
String[] items = new String[1];
if (mUserInCallMode) { //当前为听筒模式
items[0] = "使用扬声器模式";
} else { //当前为扬声器模式
items[0] = "使用听筒模式";
}
new YWAlertDialog.Builder(fragment.getActivity()).setTitle(getShowName(WXAPI.getInstance().getConversationManager().getConversationByConversationId(message.getConversationId()))).setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (mUserInCallMode) {
mUserInCallMode = false;
} else {
mUserInCallMode = true;
}
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).create().show();
return true;
} else if (message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_GEO){
Notification.showToastMsg(fragment.getActivity(), "你长按了地理位置消息");
return true;
} else if (message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_P2P_CUS || message.getSubType() == YWMessage.SUB_MSG_TYPE.IM_TRIBE_CUS){
Notification.showToastMsg(fragment.getActivity(), "你长按了自定义消息");
return true;
}
return false;
}
此功能可实现开发者希望自己处理某些URL的点击响应
//如果聊天消息的内容是url.点击url会回调给设置ChattingMsgUrlHandler处理。
ChattingHandlerManager.getInstance().setChattingMsgUrlHandler(new ChattingMsgUrlHandler() {
@Override
public boolean onInterceptClick(String url, YWMessage message,Activity chattingContext) {
Toast.makeText(OpenImUiActivity.this, url+" "+message.getAuthorUserId(), Toast.LENGTH_LONG).show();
chattingContext.finish();
return false;
}
});
此功能允许开发者自定义对数字串的操作,之前版本SDK对疑似号码的数字字符串,点击默认打开拨号界面。
示例代码在ChattingOperationCustomSample.java中
/**
* 数字字符串点击事件
* @param activity
* @param clickString 被点击的数字string
* @return false:不处理
* true:需要开发者在return前添加自己实现的响应逻辑代码
*/
@Override
public boolean onNumberClick(Activity activity, String clickString) {
return false;
}
SDK允许替换SDK默认表情或者新增表情,新增表情包括Emoji表情和图片表情。Emoji表情不是指系统的Emoji表情,而是开发者自定义含义和对应图片的表情,图片表情就是在点击时直接以图片形式发送,不会出现在输入框。
先约定一下几个概念:
表情初始化相关的方法请在ApplicationOncreate中调用,并在initNotify中进行
YWSmilyMgr.setSmilyInitNotify(new YWSmilyMgr.SmilyInitNotify() {
@Override
public void onDefaultSmilyInitOk() {
//这里进行表情的初始化
//最后要清空通知,防止memory leak
YWSmilyMgr.setSmilyInitNotify(null);
}
});
/**
* 添加新的表情包,该方法添加的表情是图片类型,开发者无需考虑多端解析问题
* @param smileyResArray
* 表情资源数组
* @param horizontalCount
* 水平展示个数
* @param verticalCount
* 垂直展示个数
* <br>
* 注:该方法添加的表情属于自定义Image表情,表情会当做图片发送
*/
public static void addImageSmiley(int[] smileyResArray, int horizontalCount, int verticalCount) {
YWIMSmiley smiley = new YWIMSmiley(smileyResArray);
smiley.setHorizontalCount(horizontalCount);
smiley.setVerticalCount(verticalCount);
YWSmilyMgr.addNewSmiley(smiley);
}
/**
* 添加新的表情包,该方法会在原有表情包的基础上扩充(没有指定水平和垂直方向上的个数,则使用默认---水平:7 垂直:3)
* @param smileyResArray
* drawable资源id数组
* @param shortCuts
* 快捷方式数组
* @param meanings
* 含义数组
* <br>
* 注:该方法添加的表情属于自定义Emoji表情,填加后的展示需要开发者自己考虑多端解析的实现
*/
public static void addEmojiSmiley(int[] smileyResArray, String[] shortCuts, String[] meanings) {
YWIMSmiley smiley = new YWIMSmiley(smileyResArray, shortCuts, meanings);
YWSmilyMgr.addNewSmiley(smiley);
}
/**
* 添加新的表情包,该方法会在原有表情包的基础上扩充
* @param smileyResArray
* drawable资源id数组
* @param shortCuts
* 快捷方式数组
* @param meanings
* 含义数组
* @param horizontalCount
* 水平方向上的展示个数
* @param verticalCount
* 垂直方向上的展示个数
*
* <br>
* 注:该方法添加的表情属于自定义Emoji表情,填加后的展示需要开发者自己考虑多端解析的实现
*/
public static void addEmojiSmiley(int[] smileyResArray, String[] shortCuts, String[] meanings, int verticalCount, int horizontalCount) {
YWIMSmiley smiley = new YWIMSmiley(smileyResArray, shortCuts, meanings, horizontalCount, verticalCount);
YWSmilyMgr.addNewSmiley(smiley);
}
**注:表情图标目前默认大小是32*32,单位为dp,如果需要修改请在aliwx_smily_item.xml中修改 **
//打开聊天窗口前调用以下代码 //参数view:自定义view,返回null则不显示自定义view mIMKit.showCustomView(View view);
mIMKit.hideCustomView(View view);
//第一步:在Applicatoin类里将这个自定义接口绑定到单聊界面,加入以下代码(对于单聊界面的所有自定义UI定制只需要加一次)
AdviceBinder.bindAdvice(PointCutEnum.CHATTING_FRAGMENT_OPERATION_POINTCUT,ChattingOperationCustomSample.class);
//第二步,继承IMChattingPageOperateion,根据需求覆盖getGoodsInfoFromUrl()或者getCustomUrlView(),具体覆盖方式如下:
/**
* 获取url对应的商品详情信息,当openIM发送或者接收到url消息时会首先调用getCustomUrlView(Fragment, YWMessage, String, YWConversation),若getCustomUrlView()返回null,才会回调用该方法获取商品详情,若getCustomUrlView()返回非null的view对象,则直接用此view展示url消息,不再回调该方法。因此,如果希望该方法被调用,请确保getCustomUrlView(Fragment, YWMessage, String, YWConversation)返回null。
* @param fragment 可以通过 fragment.getActivity拿到Context
* @param message url所属的message
* @param url url
* @param ywConversation message所属的conversion
* @return 商品信息
*/
@Override
public GoodsInfo getGoodsInfoFromUrl(Fragment fragment, YWMessage message, String url, YWConversation ywConversation) {
if (url.equals("https://www.taobao.com/ ")) {
Bitmap bitmap = BitmapFactory.decodeResource(fragment.getResources(), R.drawable.pic_1_18);
//GoodsInfo的四个参数分别为:宝贝名称,当前价格,原始价格,运费,商品图片;
GoodsInfo info = new GoodsInfo("我的淘宝宝贝", "60.03", "86.25", "8.00", bitmap);
return info;
}
return null;
}
/**
* 获取url对应的自定义view,当openIM发送或者接收到url消息时会回调该方法获取该url的自定义view。若开发者实现了该方法并且返回了一个view对象,openIM将会使用该view展示对应的url消息。
* @param fragment 可以通过 fragment.getActivity拿到Context
* @param message url所属的message
* @param url url
* @param ywConversation message所属的conversion
* @return 自定义Url view
*/
@Override
public View getCustomUrlView(Fragment fragment, YWMessage message, String url, YWConversation ywConversation) {
if (url.equals("https://www.baidu.com/ ")) {
LinearLayout layout = (LinearLayout) View.inflate(
DemoApplication.getContext(),
R.layout.demo_custom_tribe_msg_layout, null);
TextView textView = (TextView) layout.findViewById(R.id.msg_content);
textView.setText("I'm from getCustomUrlView!");
return layout;
}
return null;
}
/**
* 获取文本消息中的文字颜色,该接口可以设置文本、链接和数字的颜色
* @param conversation 当前会话
* @param isSelf 是否是自己发送的消息,true:自己发送的消息,false:别人发送的消息
* @param type 文本类型,1:普通文本,2:链接,3:数字
* @return 颜色资源Id
*/
@Override
public int getCustomTextColor(YWConversation conversation, boolean isSelf, int type) {
if (type == 1){
//普通文字颜色
} else if (type == 2){
//超链接颜色
} else if (type == 3){
//数字颜色
}
return super.getCustomTextColor(conversation, isSelf, type);
}
拷贝OneSDK工程中的res/values/custom_values.xml文件到你的主工程的res/values目录下,然后根据需求修改你的主工程中的custom_values.xml文件中的对应变量即可。
/**
* 聊天窗口初始化完成,开发者可以使用 {@link IMChattingBizService}接口来进行获取聊天窗口更多的对象
* @param bizService
*/
void onInitFinished(IMChattingBizService bizService);
/**
* 提供给开发者可以主动调用的一些方法集合,来操作聊天窗口
*/
public interface IMChattingBizService {
/**
* 获取聊天窗口输入框
* @return
* @deprecated 该方法已废弃, 后续请使用{@link IYWChattingReplyBar#getInputEditTextView()}
*/
EditText getInputEditTextView();
/**
* 获取聊天窗口对应的会话
* @return
*/
YWConversation getConversation();
/**
* 获取Fragment
* @return
*/
Fragment getFragment();
/**
* 获取聊天窗口回复框
* @return
*/
IYWChattingReplyBar getChattingReplyBar();
/**
* 获取当前聊天窗口对应的YWIMKit对象
* @return
*/
YWIMKit getIMKit();
/**
* 停止播放语音消息
*/
void stopAudio();
}
/**
* 开发者主动操作聊天窗口回复框
*/
public interface IYWChattingReplyBar {
/**
* 设置回复框的背景色
* @param colorId
*/
void setBackgroundColor(int colorId);
/**
* 获取回复框中的输入框
* @return
*/
EditText getInputEditTextView();
/**
* 设置回复框的输入框内右侧drawable和对应的点击事件
* @param drawable 输入框内右侧drawable
* @param listener 右侧drawable的点击事件
*/
void setInputEditTextRightDrawable(Drawable drawable, OnEditTextDrawableClickListener listener);
/**
* 展示回复框下方区域,即表情区域
* @param fragment 需要展示的fragment
* @param height fragment高度, 如果开发者不想控制高度请传
*/
void showReplyFragment(Fragment fragment, int height);
/**
* 隐藏回复框下方区域,即表情区域
*/
void hideReplyFragment();
/**
* 显示软键盘
*/
void showKeyboard();
/**
* 隐藏软键盘
*/
void hideKeyBoard();
/**
* 显示录音按钮
*/
void showRecordWindow();
/**
* 隐藏录音按钮
*/
void hideRecordWindow();
}
/**
* 设置声音播放ImageView
* @param view
* @param index 0,1,2,3,分别表示动画第一帧,第二帧,第三帧,及静态的图片
* @param direction 0,自己,1,对方
*/
@Override
public void onSetAudioContentImage(ImageView view, int index, int direction){
//这里对view进行图片的设置
}
/** * 自绘录制按钮 * @param canvas * @param button */ void onCustomDrawRecordButton(Canvas canvas, RecordButton button);
允许自定义插件item位置,添加新的item,修改原有item,设置是否隐藏,设置点击事件
/** * * 用于增加聊天窗口 下方回复栏的操作区的item * * ReplyBarItem: * itemId:唯一标识 建议从1开始 * ItemImageRes:显示的图片 * ItemLabel:文字 * needHide:是否隐藏 默认: false , 显示:false , 隐藏:true * OnClickListener: 自定义点击事件, null则使用默认的点击事件 * 参照示例返回List<ReplyBarItem>用于操作区显示item列表,可以自定义顺序和添加item * * @param pointcut 聊天窗口fragment * @param conversation 当前会话,通过conversation.getConversationType() 区分个人单聊,与群聊天 * @param replyBarItemList 默认的replyBarItemList,如拍照、选择照片、短视频等 * @return */ @Override public List<ReplyBarItem> getCustomReplyBarItemList(final Fragment pointcut,final YWConversation conversation, List<ReplyBarItem> replyBarItemList)
replyBarItemList会包含默认的ReplyBarItem,如拍照、选择照片、短视频等,开发者使用可以新建自己的replyBarItemList,将原replyBarItemList中的item根据自己想要的次序放入,也可以添加自己的item,也可以设置拍照、选择照片、短视频等默认item的显示隐藏和点击事件。具体示例请参考:
openIMDemo/src/com/taobao/openimui/sample/ChattingOperationCustomSample.java
| 可设置点 | 设置方式 |
|---|---|
| 设置唯一ID | 请设置ReplyBarItem的itemId,注意根据注释不要和默认Item的ID重合(具体ID请查看YWChattingPlugin.ReplyBarItem中的数值) |
| 设置文字 | 请设置ReplyBarItem的ItemLabel |
| 设置图标 | 请设置ReplyBarItem的ItemImageRes |
| 设置隐藏 | 请设置ReplyBarItem的needHide为true,默认值为false不隐藏 |
| 设置自定义点击事件 | 请设置ReplyBarItem的OnClickListener,默认值null使用默认点击事件。item的点击事件通常要startActivityForResult结合onActivityResult一起使用,开发者可以灵活使用requestcode和setData(intent)做数据传递。 |
首先设置自定义拍照或选择照片replyBarItem的点击事件,然后startActivityForResult启动自己的拍照或选择照片activity。请参照如下要求发送照片.
在startActivityForResult[包含欲发送图片的Activity]时,requestcode请传YWImageHandler.YWImageSender.YW_REQUESTCODE_MULIT_PIC_WITH_DATA。在finish时需要在intent中放入发送图片所需的信息,参照下面示例:
Intent intent = new Intent(); ArrayList<String> selectedList = new ArrayList<String>(); selectedList.add(oriImageUrl); // selectedList:欲发送的图片本地路径list,类型ArrayList<String> intent.putStringArrayListExtra(YWImageHandler.YWImageSender.YW_RESULT_LIST, selectedList); // compress : 是否适当压缩图片,类型boolean intent.putExtra(YWImageHandler.YWImageSender.YW_NEED_COMPRESS,compress); getActivity().setResult(Activity.RESULT_OK, intent); getActivity().finish();
这样,当退回聊天窗口时,就会发送出图片了.
打开聊天窗口自动发送一条消息给对方。需要注意的是,仅支持本地隐藏。当用户切换手机或清楚数据后,会漫游消息下这些消息并出现在用户的聊天界面上!需要覆写IMChattingPageOperateion中下面的API
@Override
public YWMessage ywMessageToSendWhenOpenChatting(Fragment fragment, YWConversation conversation, boolean isConversationFirstCreated) {
return null;
}
示例代码如下,可参考ChattingOperationCustomSample:
/**
* 当打开聊天窗口时,自动发送该消息给对方
* @param fragment 聊天窗口fragment
* @param conversation 当前会话
* @param isConversationFirstCreated 是否是首次创建会话
* @return 自动发送的消息(注意,内容empty则不自动发送)
*/
@Override
public YWMessage ywMessageToSendWhenOpenChatting(Fragment fragment, YWConversation conversation, boolean isConversationFirstCreated) {
//与客服的会话
if(conversation.getConversationId().contains("openim官方客服")){
final SharedPreferences defalultSprefs = fragment.getActivity().getSharedPreferences(
"ywPrefsTools", Context.MODE_PRIVATE);
long lastSendTime = defalultSprefs.getLong("lastSendTime_"+conversation.getConversationId(), -1);
//24小时后再次发送本地隐藏消息
if(System.currentTimeMillis()-lastSendTime>24*60*60*1000){
YWMessage textMessage = YWMessageChannel.createTextMessage("你好");
//添加发送的消息不显示在对方界面上的本地标记
textMessage.setLocallyHideMessage(true);
//保存发送时间戳
SharedPreferences.Editor edit = defalultSprefs.edit();
edit.putLong("lastSendTime_"+conversation.getConversationId(),System.currentTimeMillis());
edit.commit();
return textMessage;
}
}
//返回null,则不发送
return null;
}
需要覆写IMChattingPageOperateion中下面的API
/**
* @param fragment 聊天窗口fragment
* @param conversation 当前聊天窗口对应的会话
* @param time 默认时间文案
* @return 如果是NULL,则不显示,如果是空字符串,则使用SDK默认的文案,如果返回非空串,则使用用户自定义的
*/
@Override
public String getCustomTimeString(Fragment fragment, YWConversation conversation, String time) {
return "";
}