本文已参与「新人创作礼」活动,一起开启掘金创作之路。
IM聊天中如何实现红包,转账,分享等功能。
其实红包,转账,和一些自定义的消息都是给予IM的自定义消息实现。
我们知道IM的消息类型分为C2C和Group类型。那比如我在C2C中自定义一个Message对象继承IMMessage,再对自定义的Message对象设置指定的类型,封装样式与解析样式,数据的封装格式,和解析格式就大致完成了红包的定义。
大致实现效果如下:
而红包的定义比较复杂,分为几种红包,红包又分几种状态,我们先看看简单的分享和转账实现。
一、自定义分享的实现
先定义一个自定义的类型枚举
public enum CustomType {
TYPING,
INVALID,
EANGBAO,
TRANSFER,
EANGBAO_RECEIVE,
PARTTIME,
FULLTIME,
PROMOTION,
REWARDS,
JOBTIPS,
}
复制代码
自定义的Message用于装载IM消息体和一些显示的逻辑
/**
* 消息数据基类
*/
public abstract class Message implements Serializable {
TIMMessage message;
private boolean hasTime;
/**
* 消息描述信息
*/
private String desc;
public TIMMessage getMessage() {
return message;
}
/**
* 显示消息
*
* @param viewHolder 界面样式
* @param context 显示消息的上下文
*/
public abstract void showMessage(ChatRVAdapter.ViewHolder viewHolder, Context context, boolean isShowing);
/**
* 获取显示气泡
*
* @param viewHolder 界面样式
*/
public FrameLayout getBubbleView(ChatRVAdapter.ViewHolder viewHolder) {
//用于展示Chat页面的气泡布局,左右布局的判断与显示
}
/**
* 显示消息状态
*
* @param viewHolder 界面样式
*/
public void showStatus(ChatRVAdapter.ViewHolder viewHolder) {
//用于展示Chat页面的布局状态,发送中,已发送,发送成功,发送失败等。
}
/**
* 判断是否是自己发的
*/
public boolean isSelf() {
return message.isSelf();
}
//对话的类型是单聊还是群聊
public boolean isC2C() {
return message.getConversation().getType() == TIMConversationType.C2C;
}
/**
* 获取消息摘要
*/
public abstract String getSummary();
/**
* 获取撤回之后的文本显示
*/
String getRevokeSummary() {
return "Recall";
}
/**
* 保存消息或消息文件
*/
public abstract void save();
/**
* 删除消息
*/
public void remove() {
//调用SDK删除消息
TIMMessageExt ext = new TIMMessageExt(message);
ext.remove();
}
/**
* 是否需要显示时间获取
*/
public boolean getHasTime() {
return hasTime;
}
/**
* 是否需要显示时间设置
*
* @param message 上一条消息
*/
public void setHasTime(TIMMessage message) {
if (message == null) {
hasTime = true;
return;
}
hasTime = this.message.timestamp() - message.timestamp() > 300;
}
/**
* 消息是否发送失败
*/
public boolean isSendFail() {
return message.status() == TIMMessageStatus.SendFail;
}
/**
* 清除气泡原有数据
*/
protected void clearView(ChatRVAdapter.ViewHolder viewHolder) {
//清除聊天页面的数据
}
/**
* 显示撤回的消息
*/
boolean checkRevoke(ChatRVAdapter.ViewHolder viewHolder) {
//判断是否撤回消息
}
/**
* 获取发送者
*/
public String getSender() {
if (message.getSender() == null) {
return "";
}
return message.getSender();
}
/**
* 获取发送者NickName
*/
public String getSenderNickName() {
if (message.getSender() == null) {
return "";
}
return message.getSenderNickname();
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
private void showDesc(ChatRVAdapter.ViewHolder viewHolder) {
//展示详情,
}
}
复制代码
上面的Message是对全部的消息的自定义,我们继承这个Message,实现自己的消息类型,默认的类型TextMessage,ImageMessage就是显示出来的文本与图片展示,VoiceMessage与VideoMessage就是我们平常使用的语音消息与视频消息,而我们的分享,转账,红包等,都是类似的实现:
例如Promotion的分享类型:
public class CustomPromotionMessage extends Message {
public static int TYPE_PROMOTION = 21;
private CustomType type; //当前消息的类型
//优惠券
public String mPromotionId;
private String mPromotionImage;
private String mPromotionTitle;
private String mPromotionPlatform;
private String mPromotionOrginalPrice;
private String mPromotionPrice;
private String mPromotionPercent;
private String mSenderName; //全部消息的发送方名字
public CustomPromotionMessage(TIMMessage message) {
this.message = message;
TIMCustomElem elem = (TIMCustomElem) message.getElement(0);
parse(elem.getData());
}
//优惠券
public CustomPromotionMessage(CustomType type, String promotion_id, String sender_name, String promotion_image, String promotion_title, String promotion_platform,
String promotion_original_price, String promotion_price, String promotion_discount_percent) {
message = new TIMMessage();
String data = "";
JSONObject dataJson = new JSONObject();
try {
if (type == CustomType.PROMOTION) {
//创建消息对象的时候赋值,优惠券的数据
dataJson.put("userAction", TYPE_PROMOTION);
dataJson.put("promotion_id", promotion_id);
dataJson.put("sender_name", sender_name);
dataJson.put("promotion_image", promotion_image);
dataJson.put("promotion_title", promotion_title);
dataJson.put("promotion_platform", promotion_platform);
dataJson.put("promotion_original_price", promotion_original_price);
dataJson.put("promotion_price", promotion_price);
dataJson.put("promotion_discount_percent", promotion_discount_percent);
data = dataJson.toString();
}
} catch (JSONException e) {
YYLogUtils.e("generate json error");
}
TIMCustomElem elem = new TIMCustomElem();
elem.setData(data.getBytes());
message.addElement(elem);
}
/**
* 解析数据
*/
private void parse(byte[] data) {
try {
String str = new String(data, "UTF-8");
JSONObject jsonObj = new JSONObject(str);
int action = jsonObj.getInt("userAction");
if (action == TYPE_PROMOTION) {
//优惠券
type = CustomType.PROMOTION;
mPromotionId = jsonObj.getString("promotion_id");
mSenderName = jsonObj.getString("sender_name");
mPromotionImage = jsonObj.getString("promotion_image");
mPromotionTitle = jsonObj.getString("promotion_title");
mPromotionPlatform = jsonObj.getString("promotion_platform");
mPromotionOrginalPrice = jsonObj.getString("promotion_original_price");
mPromotionPrice = jsonObj.getString("promotion_price");
mPromotionPercent = jsonObj.getString("promotion_discount_percent");
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void showMessage(ChatRVAdapter.ViewHolder viewHolder, Context context, boolean isShowing) {
clearView(viewHolder);
if (checkRevoke(viewHolder)) return;
if (getType() == CustomType.PROMOTION) {
clearView(viewHolder);
FrameLayout bubbleView = getBubbleView(viewHolder);
bubbleView.setBackgroundColor(Color.TRANSPARENT);
View inflate = CommUtils.inflate(R.layout.item_layout_promotion);
ImageView iv_promotion_image = inflate.findViewById(R.id.iv_promotion_image);
TextView tv_promotion_title = inflate.findViewById(R.id.tv_promotion_title);
TextView tv_promotion_plate = inflate.findViewById(R.id.tv_promotion_plate);
TextView tv_promotion_oprice = inflate.findViewById(R.id.tv_promotion_oprice);
TextView tv_promotion_price = inflate.findViewById(R.id.tv_promotion_price);
TextView tv_promotion_percent = inflate.findViewById(R.id.tv_promotion_percent);
tv_promotion_oprice.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); //中划线
GlideImageEngine.get().imageLoad(iv_promotion_image, mPromotionImage, R.drawable.home_list_plachholder);
tv_promotion_title.setText(mPromotionTitle);
tv_promotion_plate.setText(mPromotionPlatform);
tv_promotion_oprice.setText(mPromotionOrginalPrice);
tv_promotion_price.setText(mPromotionPrice);
tv_promotion_percent.setText(mPromotionPercent);
getBubbleView(viewHolder).addView(inflate);
showStatus(viewHolder);
}
}
@Override
public String getSummary() {
String str = getRevokeSummary();
if (str != null) return str;
if (isC2C()) {
return "[Promotion]";
} else {
return mSenderName + " : [Promotion]";
}
}
@Override
public void save() {
}
public CustomType getType() {
return type;
}
}
复制代码
这样的消息很简单,只需要定义封装数据,解析数据,与展示的样式即可。
展示的时候由于我们都是继承Message,在ChatAdapter中我们直接调用 message.showMessage()
即可展示Item的布局与点击事件
final Message message = getItem(position);
message.showMessage(holder, mContext, false);
//如果是自定义消息红包或转账在这里特殊处理和其他的分享
if (message instanceof CustomEAngbaoMessage
|| message instanceof CustomTransferMessage
|| message instanceof CustomPartTimeMessage
|| message instanceof CustomFullTimeMessage
|| message instanceof CustomPromotionMessage
|| message instanceof CustomRewardsMessage
|| message instanceof CustomJobTipsMessage) {
//处理点击点事件
message.getBubbleView(holder).setOnClickListener(v -> handleCustomClick(position, message));
}
...
//优惠券
} else if (message instanceof CustomPromotionMessage) {
if (mListener != null) mListener.onPromotionClick(((CustomPromotionMessage) message).mPromotionId);
}
复制代码
展示出来的效果如下:
二、转账的实现
转账比分享稍微多一步就是转账消息的状态判断。判断对方收取了金额没有。
public class CustomTransferMessage extends Message {
public static int TYPE_TRANSFER = 17;
private CustomType type; //当前消息的类型
//转账
public String mTransferId;
public String mTransferAmount;
public String mTransferTargetName;
public int mTransferStatus = 1;
public CustomTransferMessage(TIMMessage message) {
this.message = message;
TIMCustomElem elem = (TIMCustomElem) message.getElement(0);
parse(elem.getData());
}
//发送转账
public CustomTransferMessage(CustomType type, String id, String amount, String targetName) {
message = new TIMMessage();
String data = "";
JSONObject dataJson = new JSONObject();
try {
if (type == CustomType.TRANSFER) {
//创建消息对象的时候赋值,转账的数据
dataJson.put("userAction", TYPE_TRANSFER);
dataJson.put("tramsfer_id", id);
dataJson.put("tramsfer_amount", amount);
dataJson.put("tramsfer_traget_name", targetName);
dataJson.put("tramsfer_status", 1);
data = dataJson.toString();
}
} catch (JSONException e) {
YYLogUtils.e("generate json error");
}
TIMCustomElem elem = new TIMCustomElem();
elem.setData(data.getBytes());
message.addElement(elem);
}
/**
* 解析数据
*/
private void parse(byte[] data) {
try {
String str = new String(data, "UTF-8");
JSONObject jsonObj = new JSONObject(str);
int action = jsonObj.getInt("userAction");
if (action == TYPE_TRANSFER) {
//转账信息
type = CustomType.TRANSFER;
mTransferId = jsonObj.getString("tramsfer_id");
mTransferAmount = jsonObj.getString("tramsfer_amount");
mTransferTargetName = jsonObj.getString("tramsfer_traget_name");
mTransferStatus = jsonObj.getInt("tramsfer_status");
}
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressLint("SetTextI18n")
@Override
public void showMessage(ChatRVAdapter.ViewHolder viewHolder, Context context, boolean isShowing) {
clearView(viewHolder);
if (checkRevoke(viewHolder)) return;
if (getType() == CustomType.TRANSFER) {
clearView(viewHolder);
FrameLayout bubbleView = getBubbleView(viewHolder);
bubbleView.setBackgroundColor(Color.TRANSPARENT);
View redpackView = CommUtils.inflate(R.layout.item_layout_transfer);
TextView tv_transfer_amount = redpackView.findViewById(R.id.tv_transfer_amount);
TextView tv_transfer_member_name = redpackView.findViewById(R.id.tv_transfer_member_name);
tv_transfer_amount.setText(SalaryUtils.getCurrencySignByCountry(true) + " " + NumberUtils.formatMoney(mTransferAmount));
tv_transfer_member_name.setText(isSelf() ? "Transfer to " + mTransferTargetName : "Transfer to You");
getBubbleView(viewHolder).addView(redpackView);
showStatus(viewHolder);
}
}
@Override
public String getSummary() {
String str = getRevokeSummary();
if (str != null) return str;
return "[Transfer] Accepted";
}
@Override
public void save() {
}
public CustomType getType() {
return type;
}
}
复制代码
其他的步骤都是和分享类型一致的,内部我们可以根据状态判断是否收取金额,展示不同的布局与状态。
三、红包的实现
红包的状态比较为复杂:
- 消息类型分为个人红包与群组红包
- 群组红包分为随机红包和等额红包,
- 红包状态分为已发送,已领取,已过期等状态。
- 红包的封面又分为默认红包,封面红包,根据不同的状态我们还要改变封面红包的封面图。
消息内的红包只是涉及到静态的展示,并不涉及到撕红包动画与红包封面图片切换等效果,我们还是定义相关的消息与布局,再定义对应状态的对应的处理:
public class CustomEAngbaoMessage extends Message {
public static final int TYPE_EANGBAO = 16;
private CustomType type; //当前消息的类型
public String mRedpackId;
public String mRedpackRemark;
public String mRedpackCover;
public String mRedpackOpened;
public int mRedpackStatus = 1;
private ImageView mIvRedpackOpen;
private View mViewDisenable;
private ProgressBar mProgressBar;
private ImageView mIvRedpackCover;
private TextView mTvRedpackStatusText;
private TextView mTvRedpackRemark;
public CustomEAngbaoMessage(TIMMessage message) {
this.message = message;
TIMCustomElem elem = (TIMCustomElem) message.getElement(0);
parse(elem.getData());
}
//发送红包消息构造
public CustomEAngbaoMessage(CustomType type, String id, String remark, String cover, String opened) {
message = new TIMMessage();
String data = "";
JSONObject dataJson = new JSONObject();
try {
if (type == CustomType.EANGBAO) {
//创建消息对象的时候赋值,红包的数据
dataJson.put("userAction", TYPE_EANGBAO);
dataJson.put("eangbao_id", id);
dataJson.put("eangbao_remark", remark);
dataJson.put("eangbao_cover", cover);
dataJson.put("eangbao_opened", opened);
dataJson.put("eangbao_status", 1);
data = dataJson.toString();
}
} catch (JSONException e) {
YYLogUtils.e("generate json error");
}
TIMCustomElem elem = new TIMCustomElem();
elem.setData(data.getBytes());
message.addElement(elem);
}
//解析红包数据
private void parse(byte[] data) {
try {
String str = new String(data, "UTF-8");
JSONObject jsonObj = new JSONObject(str);
int action = jsonObj.getInt("userAction");
if (action == TYPE_EANGBAO) {
//红包信息
type = CustomType.EANGBAO;
mRedpackId = jsonObj.getString("eangbao_id");
mRedpackRemark = jsonObj.getString("eangbao_remark");
mRedpackCover = jsonObj.getString("eangbao_cover");
mRedpackOpened = jsonObj.getString("eangbao_opened");
mRedpackStatus = jsonObj.getInt("eangbao_status");
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void showMessage(ChatRVAdapter.ViewHolder viewHolder, Context context, boolean isShowing) {
clearView(viewHolder);
if (checkRevoke(viewHolder)) return;
//红包的样式展示
if (getType() == CustomType.EANGBAO) {
clearView(viewHolder);
FrameLayout bubbleView = getBubbleView(viewHolder);
bubbleView.setBackgroundColor(Color.TRANSPARENT);
View redpackView = CommUtils.inflate(R.layout.item_layout_redpack);
mIvRedpackCover = redpackView.findViewById(R.id.iv_redpack_cover);
mProgressBar = redpackView.findViewById(R.id.progress_bar);
mTvRedpackRemark = redpackView.findViewById(R.id.tv_redpack_remark);
mViewDisenable = redpackView.findViewById(R.id.view_disenable);
mIvRedpackOpen = redpackView.findViewById(R.id.iv_redpack_open);
mTvRedpackStatusText = redpackView.findViewById(R.id.tv_redpack_status_text);
//统一赋值动态变化的数据
showRedpackData();
getBubbleView(viewHolder).addView(redpackView);
showStatus(viewHolder);
}
}
/**
* 刷新红包的状态
*/
public void notifyRedpack() {
showRedpackData();
}
/**
* 红包的布局是动态的可以变换
*/
private void showRedpackData() {
if (mIvRedpackOpen != null) {
String statusText = "";
String imgUrl;
if (mRedpackStatus == 2) {
statusText = "Opened";
} else if (mRedpackStatus == 3) {
statusText = "Expired";
} else if (mRedpackStatus == 4) {
statusText = "None left";
}
if (mRedpackStatus == 1) {
imgUrl = mRedpackCover;
mIvRedpackOpen.setVisibility(View.VISIBLE);
mViewDisenable.setVisibility(View.GONE);
mTvRedpackStatusText.setVisibility(View.GONE);
} else {
imgUrl = mRedpackStatus == 5 ? mRedpackCover : mRedpackOpened;
mIvRedpackOpen.setVisibility(View.GONE);
mViewDisenable.setVisibility(View.VISIBLE);
mTvRedpackStatusText.setVisibility(View.VISIBLE);
mTvRedpackStatusText.setText(statusText);
}
if (!CheckUtil.isEmpty(imgUrl)) {
mProgressBar.setVisibility(View.VISIBLE);
GlideImageEngine.get().imageLoad(mIvRedpackCover, imgUrl, R.drawable.shape_redpack_img_bg, () -> {
mProgressBar.setVisibility(View.GONE);
});
} else {
mIvRedpackCover.setBackgroundResource(R.drawable.shape_redpack_img_bg);
}
//如果是自己发的 并且 状态为1 并且是单聊 隐藏Open的图片
if (mRedpackStatus == 1 && isSelf() && isC2C()) {
mIvRedpackOpen.setVisibility(View.GONE);
}
//如果是自己发的 状态为5 隐藏灰色蒙层 显示Open按钮
if (mRedpackStatus == 5 && isSelf() && isC2C()) {
mIvRedpackOpen.setVisibility(View.VISIBLE);
mViewDisenable.setVisibility(View.GONE);
}
mTvRedpackRemark.setVisibility(!CheckUtil.isEmpty(mRedpackRemark) ? View.VISIBLE : View.GONE);
mTvRedpackRemark.setText(mRedpackRemark);
}
}
@Override
public String getSummary() {
String str = getRevokeSummary();
if (str != null) return str;
return "eAngBao";
}
@Override
public void save() {
}
public CustomType getType() {
return type;
}
}
复制代码
我们发给别人的红包,我们只能查看详情,看是否领取了红包,而我们需要监听消息类型,看别人是否领取了红包,如果监听到消息别人领取了红包,我们需要发送Event修改这个红包的状态。
如果是别人发给我的红包,那么红包的状态是由我们的红包弹窗中自己手动触发的,触发打开红包之后我们同样需要发送一个消息,告诉对方我接收红包了,对方收到消息我领取了红包,对方一样需要在消息列表上刷新这个红包消息的状态。
所以我们还需要一个红包接收的消息:
public class CustomEAngbaoReceiveMessage extends Message {
public static int TYPE_EANGBAO_RECEIVE = 18;
private CustomType type; //当前消息的类型
//接红包
public String mRedpackId;
private String mSenderName; //全部消息的发送方名字
private String mSenderMemberId;
private String mRedpackReceiveName;
private String mRedpackReceiveMemberId;
private String mRedpackReceiveAmount;
private String mRedpackReceiveTargetType;
public CustomEAngbaoReceiveMessage(TIMMessage message) {
this.message = message;
TIMCustomElem elem = (TIMCustomElem) message.getElement(0);
parse(elem.getData());
}
//解析红包接收数据
private void parse(byte[] data) {
try {
String str = new String(data, "UTF-8");
JSONObject jsonObj = new JSONObject(str);
int action = jsonObj.getInt("userAction");
if (action == TYPE_EANGBAO_RECEIVE) {
//红包信息
type = CustomType.EANGBAO_RECEIVE;
mRedpackId = jsonObj.getString("eangbao_id");
mRedpackReceiveName = jsonObj.getString("receive_name");
mSenderName = jsonObj.getString("sender_name");
mRedpackReceiveAmount = jsonObj.getString("receive_amount");
mRedpackReceiveTargetType = jsonObj.getString("target_type");
if (jsonObj.has("receive_member_id")) {
mRedpackReceiveMemberId = jsonObj.getString("receive_member_id");
}
if (jsonObj.has("sender_member_id")) {
mSenderMemberId = jsonObj.getString("sender_member_id");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void showMessage(ChatRVAdapter.ViewHolder viewHolder, Context context, boolean isShowing) {
clearView(viewHolder);
if (checkRevoke(viewHolder)) return;
if (getType() == CustomType.EANGBAO_RECEIVE) {
if (!CheckUtil.isEmpty(mSenderMemberId) && !CheckUtil.isEmpty(mRedpackReceiveMemberId)) {
String myUserId = SPUtils.getInstance(CommUtils.getContext()).getString(YYConstants.CACHE_USER_ID, "");
if (!myUserId.equals(mSenderMemberId) && !myUserId.equals(mRedpackReceiveMemberId)) {
//如果不相等,那么不做展示
viewHolder.leftPanel.setVisibility(View.GONE);
viewHolder.rightPanel.setVisibility(View.GONE);
viewHolder.systemMessage.setVisibility(View.GONE);
return;
}
}
viewHolder.leftPanel.setVisibility(View.GONE);
viewHolder.rightPanel.setVisibility(View.GONE);
viewHolder.systemMessage.setVisibility(View.VISIBLE);
Drawable tips = CommUtils.getDrawable(R.drawable.redpack_reveive_tips_iocn);
tips.setBounds(0, 0, tips.getMinimumWidth(), tips.getMinimumHeight());
viewHolder.systemMessage.setCompoundDrawables(tips, null, null, null);
String content = "<font color=\"#777777\">" + mRedpackReceiveName + " opened " + mSenderName + "'s </font>" +
"<font color=\"#FF2F15\">eAngBao</font>";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
viewHolder.systemMessage.setText(Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY));
} else {
viewHolder.systemMessage.setText(Html.fromHtml(content));
}
}
}
@Override
public String getSummary() {
String str = getRevokeSummary();
if (str != null) return str;
return "eAngBao is opened";
}
@Override
public void save() {
}
public CustomType getType() {
return type;
}
}
复制代码
关于红包的消息展示和分享的消息展示类似,只是我们的消息中多一个了更新的方法,重新根据状态来展示对应的布局。
public void notifyRedpack() {
showRedpackData();
}
复制代码
关于撕红包和展示金额,详情等页面其实都是与这个消息展示无关的,分别是红包弹窗和红包详情页面。我们大部分动画都是lottie效果,这个大家应该都不会有问题。
发送红包效果:
打开自己发送的红包与对方接收红包的消息效果:
Ok,红包模块在IM中的使用大致就是如此了!
定义消息-> 定义自定义消息类型 ->定义各个状态的不同布局展示 ->处理自己的红包 ->处理别人的红包 ->监听红包打开的消息。
至于群组红包和个人红包只是发送消息的时候区别type为C2C还是Group就行了,关于红包处理的
Bundle bundle = new Bundle();
bundle.putString("identify", identify);
bundle.putString("redpackId", redpackId);
bundle.putString("remark", remark);
bundle.putString("cover", cover);
bundle.putString("opened", opened);
if (type == 2) {
bundle.putSerializable("type", TIMConversationType.Group);
} else {
bundle.putSerializable("type", TIMConversationType.C2C);
}
YYChatSuperActivity.startInstance(ChatFragment.class, bundle);
复制代码
一样的通过sendMessage方法发送消息,只是这个会话变成了group类型而已
conversation.sendMessage(message, new TIMValueCallBack<TIMMessage>() {
@Override
public void onError(int code, String desc) {
//发送消息失败
view.onSendMessageFail(code, desc, message);
}
@Override
public void onSuccess(TIMMessage msg) {
//发送消息成功,消息状态已在sdk中修改,此时只需更新界面
MessageEvent.getInstance().onNewMessage(null); //这里在observe中接受到通知,会去刷新adapter的
}
});
复制代码
群组红包还剩下多少红包,当前红包的状态等,这些都是与消息本身无关的,我们拿到红包的id,请求服务器数据展示对应的数据,根据状态刷新对应的布局即可。
大致逻辑如下:
/**
* 根据状态展示不同的数据
*/
private void showDataWithStatus(int status) {
if (mRedpackInfoStatus == null) return;
String redpackImage = "";
String message = "";
if (status == 1) {
//可以领
changeStatus(STATUS_CEN_OPEN);
redpackImage = mRedpackInfoStatus.cover.cover;
message = mRedpackInfoStatus.remark;
mTvViewDetails.setVisibility(GONE);
} else if (status == 2) {
//已经领了
changeStatus(STATUS_OPENED);
redpackImage = mRedpackInfoStatus.cover.opened;
message = mRedpackInfoStatus.remark;
mTvViewDetails.setVisibility(VISIBLE);
} else if (status == 3) {
//已经过期
changeStatus(STATUS_EXPIRED);
redpackImage = mRedpackInfoStatus.cover.cover;
message = "The eAngBao has been expired!";
mTvViewDetails.setVisibility(VISIBLE);
} else if (status == 4) {
//已被领光
changeStatus(STATUS_NEXT_TIME);
redpackImage = mRedpackInfoStatus.cover.cover;
message = "Better luck next time!";
mTvViewDetails.setVisibility(VISIBLE);
}
if (!CheckUtil.isEmpty(redpackImage)) {
//加载红包图片
GlideImageEngine.get().imageLoad(mIvRedpackTop, redpackImage, R.drawable.yypay_redpack_top_red, () -> {
mProgressBar.setVisibility(GONE);
});
mLlRedpaclInfo.setVisibility(GONE);
mTvRedpackTips.setVisibility(GONE);
} else {
mProgressBar.setVisibility(GONE);
}
...
复制代码
以接口的数据和状态为主,我们会把当前红包的状态同步到会话列表上。
具体的效果图在最上面,就不重复发图了。到处红包,转账,分享等自定义消息就大致完成!具体的细节都是细枝末节一些UI的布局和动画效果之类的,都是比较基础的。
本文测试机为华为畅想3 5寸大屏 已是我司最低端手机了。
本文的效果基于腾讯TIM的实现,如果大家使用的环信或者阿里的IM-SDK,大家都是大差不差逻辑思想都是一样的。当然如果你们是自研的通讯SDK,那更好了,都不需要使用自定义消息来开发了,你们可以直接把这些类型定义为消息类型。
源码关联了业务代码不便开源,其实只要思路是对的,使用哪一个IM工具都是类似的。希望对大家有所帮助。
如有不同的思路,欢迎讨论,如果有疑问也可以评论区指出,还请大家多多点赞支持!