前言:既然前面两篇文章记录了两种点赞列表的实现方式,那么这篇文章记录一下评论列表的实现吧。其实,评论列表的实现与第二种点赞列表的实现方式是相似的,都是利用自定义VIEW实现。不同的是点赞是自定义TextView,而这次的评论是自定义的线性布局(当然,自定义TextView也可以实现的)。这次评论列表采用自定义View继承LinearLayout,并动态添加TextView实现。
正如上图所示,本篇文章记录一下这个简单demo的实现过程:
第一步,自定义View
创建Class-CommentView继承LinearLayout,并重写构造方法。与前面提到的点赞列表类似的,我们也是定义一个List和一个Context的属性,同样的定义一个bindData与notifyDataSetChanged方法。根据List的大小而动态添加TextView,TextView与前面的点赞是一样的都是利用ClickableSpan,StringBuilder等拼接字符串,代码如下:
public class CommentView extends LinearLayout{ private Context mContext; private List<Comment> mDatas; public CommentView(Context context) { this(context, null); } public CommentView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public CommentView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOrientation(VERTICAL); this.mContext = context; } /** * 设置评论列表信息 * * @param list */ public void bindData(List<Comment> list) { mDatas = list; } public void notifyDataSetChanged() { removeAllViews(); if (mDatas == null || mDatas.size() <= 0) { return; } LinearLayout.LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); layoutParams.setMargins(0, 10, 0, 10); for (int i = 0; i < mDatas.size(); i++) { View view = getView(i); if (view == null) { throw new NullPointerException("error"); } addView(view, i, layoutParams); } } private View getView(final int position) { final Comment item = mDatas.get(position); boolean hasReply = false; // 是否有回复 if (item.getTag() != null) { if(!item.getTag().equals("false")) { hasReply = true; } } TextView textView = new TextView(mContext); textView.setTextSize(12); textView.setTextColor(0xff686868); String fromName = item.getFromName(); String fromId = item.getFromId(); String toName = item.getToName(); String toId = item.getToId(); SpannableStringBuilder builder = new SpannableStringBuilder(); if (hasReply) { builder.append(setClickableSpan(fromName, item)); builder.append(" 回复 "); builder.append(setClickableSpan(toName,item)); } else { builder.append(setClickableSpan(fromName,item)); } builder.append(" : "); builder.append(setClickableSpanContent(item.getContent(), item,position)); builder.append(" "); textView.setText(builder); // 设置点击背景色 textView.setHighlightColor(getResources().getColor(android.R.color.transparent)); textView.setMovementMethod(LinkMovementMethod.getInstance()); return textView; } /** * 设置评论内容点击事件 * * @param item * @param bean * @param position * @return */ public SpannableString setClickableSpanContent(final String item, final Comment bean,final int position) { final SpannableString string = new SpannableString(item); ClickableSpan span = new ClickableSpan() { @Override public void onClick(View widget) { //点击内容 Toast.makeText(mContext,item,Toast.LENGTH_SHORT).show(); } @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); // 设置显示的内容文本颜色 ds.setColor(0xff686868); ds.setUnderlineText(false); } }; string.setSpan(span, 0, string.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return string; } /** * 设置评论用户名字点击事件 * * @param item * @param bean * @return */ public SpannableString setClickableSpan(final String item, final Comment bean) { final SpannableString string = new SpannableString(item); ClickableSpan span = new ClickableSpan() { @Override public void onClick(View widget) { //点击名字 Toast.makeText(mContext,item,Toast.LENGTH_SHORT).show(); } @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); // 设置显示的用户名文本颜色 ds.setColor(Color.parseColor("#3CB371")); ds.setUnderlineText(false); } }; string.setSpan(span, 0, string.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return string; } }
第二步,在界面布局中定义CommentView
第三步,数据绑定与界面渲染
lvPl = findViewById(R.id.lv_pl); List<Comment> list = new ArrayList(); for(int i =0;i<10;i++){ Comment com; if(i%2==0) { com = new Comment(i + "", "用户" + i, (i + 10) + "", "用户" + (i + 10),"测试回复" ,"true"); }else{ com = new Comment(i + "", "用户" + i, (i + 10) + "", "用户" + (i + 10),"测试评论" ,"false"); } list.add(com); } lvPl.bindData(list); lvPl.notifyDataSetChanged();
注意:其实看起来与点赞列表的实现是相似的,只不过评论列表的实现逻辑比起点赞来稍微麻烦一点,因为它涉及到评论与回复是不一样的,我们在JavaBean中定义一个tag字段用于区分是评论还是回复。
public class Comment { private String content; private String fromId,toId; private String fromName,toName; private String tag; public Comment(String fromId,String fromName,String toId,String toName,String content){ this.fromId = fromId; this.fromName = fromName; this.toId = toId; this.toName = toName; this.content = content; this.tag = "false"; } public Comment(String fromId,String fromName,String toId,String toName,String content,String tag){ this.fromId = fromId; this.fromName = fromName; this.toId = toId; this.toName = toName; this.content = content; this.tag = tag; } public String getTag() { return tag; } public void setContent(String content,String tag) { this.tag = tag; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getFromId() { return fromId; } public void setFromId(String fromId) { this.fromId = fromId; } public String getToId() { return toId; } public void setToId(String toId) { this.toId = toId; } public String getFromName() { return fromName; } public void setFromName(String fromName) { this.fromName = fromName; } public String getToName() { return toName; } public void setToName(String toName) { this.toName = toName; } }