你知道TextView中可以“塞入”图片么?
之前项目需求,做一个类似QQ的点赞评论功能,效果图如下:
本文主要讲解评论这一块,至于点赞和表情帖,后续再说。
评论功能的介绍:评论内容显示:“发表评论用户”+评论内容+翻译图标。点击“发表评论用户”跳转到该用户的个人空间。点击“评论内容”,回复“发表评论用户”。点击“翻译图标”,弹出翻译对话框。
功能难点:不能用TextView和ImageView去拼凑整个评论的item,如果评论内容过多,就会出现布局问题,所以想到了图文混排来实现该功能。
功能实现:
评论的item布局我就不写了,就是一个Textview。
Textview中是可以塞入Span的,至于Span中要添加的内容,可以是字符串,也可以是图片。
TextView.BufferType并不是TextView的内部类,是一个枚举类型,设置有三个枚举值,分别为NORMAL,EDITABLE,SPANNAABLE。
SpannableString的使用:
各种的Span就是通过SpannableString来封装样式的,设置完Span之后需要将Span放入到SpannableString类中,然后SpannableString设置到TextView中去。
comment_nickname_one.setText(addClickablePart(comment,position,dynamicId,i), TextView.BufferType.SPANNABLE);
下面我们来看一下addClickablePart方法:
/**
* 拼接评论那一行算法
* @param comment 评论集合
* @param position 新鲜事的position
* @param dynamicId 新鲜事id
* @param i 评论的下标
*
* @return 评论视图
*/
private SpannableStringBuilder addClickablePart(final CommentBean comment, final int position, final String dynamicId,final int i) {
SpannableString spanStr = new SpannableString("");
// spanStr.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
SpannableStringBuilder ssb = new SpannableStringBuilder(spanStr);
String poseterName = comment.getPosterName();
/**
* 发表评论的人名长度
*/
int poseterNameLength = poseterName.length();
/**被评论的人名长度*/
int ReplyNameLength = comment.getReplyName().length();
/**评论内容的长度*/
int wordsLength = comment.getWords().length();
//把评论发送者名字添加进去
ssb.append(poseterName);
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
// TODO Auto-generated method stub
Intent intent = new Intent(context, OtherPageActivity.class);
Contants.friendId = comment.getPosterId();
Contants.friendName = comment.getPosterName();
Contants.friendIcon = comment.getPosterIcon();
((NoteActivity)context).startActivity(intent);
}
@Override
public void updateDrawState(TextPaint ds) {
// TODO Auto-generated method stub
super.updateDrawState(ds);
ds.setColor(context.getResources().getColor(R.color.note_praiseblue_name));
// // 去掉下划线
ds.setUnderlineText(false);
}
}, 0, poseterNameLength, 0);
String reply = " "+context.getResources().getString(R.string.reply)+" ";
//添加“回复”二字
ssb.append(reply);
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
// TODO Auto-generated method stub
}
@Override
public void updateDrawState(TextPaint ds) {
// TODO Auto-generated method stub
super.updateDrawState(ds);
ds.setColor(0xFF5e5d5d);
// 去掉下划线
ds.setUnderlineText(false);
}
}, poseterNameLength, reply.length()+poseterNameLength, 0);
//把被回复的名字添加进去
ssb.append(comment.getReplyName());
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Intent intent = new Intent(context, OtherPageActivity.class);
Contants.friendId = comment.getReplyId();
Contants.friendName = comment.getReplyName();
Contants.friendIcon = comment.getReplyIcon();
((NoteActivity)context).startActivity(intent);
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(context.getResources().getColor(R.color.note_praiseblue_name));
// 去掉下划线
ds.setUnderlineText(false);
}
}, reply.length()+poseterNameLength, reply.length()+poseterNameLength+ReplyNameLength, 0);
SpannableString spannableString1 = FaceConversionUtil.getInstace().getExpressionString(context, comment.getWords());
ssb.append(" : ");
ssb.append(spannableString1);
// ssb.append(" : "+comment.getWords());
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
//如果是自己发表的评论,可以删除
if(comment.getPosterId().equals(Contants.userID)){
//弹出删除对话框
ShowPickDialog(comment.getId(), dynamicId, i, position);
}else{
// TODO 点击评论内容,回复这条评论,传发表评论人的id
//弹出一个Activity
String replyId = comment.getPosterId();
Intent intent = new Intent(context,CommentActivity.class);
String isReply = "1";
intent.putExtra("type", isReply);
intent.putExtra("name", comment.getPosterName());
intent.putExtra("replyId", replyId);
intent.putExtra("dynamicId", dynamicId);
String positionString = position+"";
intent.putExtra("position", positionString);
int IsNote = 1;
//是从哪个页面传过去的
intent.putExtra("commentFrom", IsNote+"");
((NoteActivity)context).startActivityForResult(intent,IsNote);
}
}
@Override
public void updateDrawState(TextPaint ds) {
// TODO Auto-generated method stub
super.updateDrawState(ds);
ds.setColor(context.getResources().getColor(R.color.login_regist));
// 去掉下划线
ds.setUnderlineText(false);
}
}, reply.length()+3+poseterNameLength+ReplyNameLength, reply.length()+3+poseterNameLength+ReplyNameLength+wordsLength, 0);
if(!comment.getTrans().equals("") && comment.getTrans() != null){
//添加翻译内容
ssb.append(comment.getTrans());
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
}
@Override
public void updateDrawState(TextPaint ds) {
// TODO Auto-generated method stub
super.updateDrawState(ds);
ds.setColor(context.getResources().getColor(R.color.note_praiseblue_name));
// 去掉下划线
ds.setUnderlineText(false);
}
}, reply.length()+3+poseterNameLength+ReplyNameLength+wordsLength, reply.length()+3+poseterNameLength+ReplyNameLength+wordsLength+comment.getTrans().length(), 0);
}else{
comment.setTrans("");
}
//设置翻译图标的大小
// Drawable drawable = context.getResources().getDrawable(R.drawable.comment_translation);
// drawable.setBounds(0, 0, 35, 35);
ssb.append("p");
//添加翻译图标
ImageSpan span = new ImageSpan(context, R.drawable.comment_translation);
// ImageSpan span = new ImageSpan(drawable);
ssb.setSpan(span, reply.length()+3+poseterNameLength+ReplyNameLength+wordsLength+comment.getTrans().length(), reply.length()+4+poseterNameLength+ReplyNameLength+wordsLength+comment.getTrans().length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
//评论的翻译和新鲜事的翻译不同,注意
commentTransPopu.initPopuwindow(comment.getWords(), dynamicId, Contants.userID,i);
}
}, reply.length()+3+poseterNameLength+ReplyNameLength+wordsLength+comment.getTrans().length(), reply.length()+4+poseterNameLength+ReplyNameLength+wordsLength+comment.getTrans().length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
// spanStr.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
// //截取
// String[] likeUsers = str.split("、");
// if (likeUsers.length > 0) {
// // 最后一个
// for (int i = 0; i < likeUsers.length; i++) {
// String names = likeUsers[i];
// if(i == 1){
// names = " 2"+names;
// }
// final String name = names;
//
// final int start = str.indexOf(name) + spanStr.length();
// //添加到后面
// ssb.setSpan(new ClickableSpan() {
//
// @Override
// public void onClick(View widget) {
// Toast.makeText(context, name,
// Toast.LENGTH_SHORT).show();
// }
//
// @Override
// public void updateDrawState(TextPaint ds) {
// super.updateDrawState(ds);
if(name.equals("username-1")){
ds.setColor(Color.RED); // 设置文本颜色
}
// ds.setColor(context.getResources().getColor(R.color.note_praiseblue_name));
// // 去掉下划线
// ds.setUnderlineText(false);
// }
//
// }, start, start + name.length(), 0);
// }
// }
return ssb;
}
void android.text.SpannableStringBuilder.setSpan(Object what, int start, int end, int flags)
Object what:你要塞入的内容。
int start:从几个字符开始。
int end:到第几个字符结束。
int flags:setSpan时需要指定的 flag,它是用来标识在 Span 范围内的文本前后输入新的字符时是否把它们也应用这个效果。分别有 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)、Spanned.SPAN_INCLUSIVE_EXCLUSIVE(前面包括,后面不包括)、Spanned.SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,后面包括)、Spanned.SPAN_INCLUSIVE_INCLUSIVE(前后都包括)。
setSpan可以设置点击时间:new ClickableSpan()