先上效果图:

一、创建xml

1.android_ceshi_activity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rvAndroid"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:paddingBottom="12dp"app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"tools:itemCount="4"tools:listitem="@layout/android_ceshi_item" /></LinearLayout>

2.android_ceshi_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/tvName"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:minHeight="46dp"android:padding="10dp"android:text="测试灯虎试试看"android:textColor="@color/black"android:textSize="@dimen/sp_14" /><TextViewandroid:id="@+id/btnPinglun"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center_vertical"android:minHeight="46dp"android:padding="10dp"android:layout_alignParentEnd="true"android:text="评论"android:textColor="@color/black"android:textSize="@dimen/sp_14" /></RelativeLayout><com.june.wt.commentview.CommentsViewandroid:id="@+id/commentView"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginStart="15dp"android:layout_marginEnd="15dp"/><TextViewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="@color/gray" /></LinearLayout>

二、创建评论相关的实体类

1.CeshiBean

package com.june.wt.commentviewclass CeshiBean {var name = ""var commentList: List<CommentsBean>? = null}

2.CommentsBean

package com.june.wt.commentview;import java.io.Serializable;public class CommentsBean implements Serializable {// 评论IDprivate String id;// 园地IDprivate String scopeId;// 发布评论人的IDprivate String userId;// 回复人ID()private String userCodeId;// 评论内容private String commentCount;// 发布评论人的 姓名private String createBy;// 回复人的 姓名private String updateBy;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getScopeId() {return scopeId;}public void setScopeId(String scopeId) {this.scopeId = scopeId;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getUserCodeId() {return userCodeId;}public void setUserCodeId(String userCodeId) {this.userCodeId = userCodeId;}public String getCommentCount() {return commentCount;}public void setCommentCount(String commentCount) {this.commentCount = commentCount;}public String getCreateBy() {return createBy;}public void setCreateBy(String createBy) {this.createBy = createBy;}public String getUpdateBy() {return updateBy;}public void setUpdateBy(String updateBy) {this.updateBy = updateBy;}@Overridepublic String toString() {return "CommentsBean{" +"id='" + id + '\'' +", scopeId='" + scopeId + '\'' +", userId='" + userId + '\'' +", userCodeId='" + userCodeId + '\'' +", commentCount='" + commentCount + '\'' +", createBy='" + createBy + '\'' +", updateBy='" + updateBy + '\'' +'}';}
}

三、自定义View

1.CommentsView

package com.june.wt.commentview;import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;import androidx.annotation.Nullable;import java.util.List;public class CommentsView extends LinearLayout {private Context mContext;private List<CommentsBean> mDatas;private onItemClickListener listener;public CommentsView(Context context) {this(context, null);}public CommentsView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public CommentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);setOrientation(VERTICAL);this.mContext = context;}/*** 设置评论列表信息** @param list*/public void setList(List<CommentsBean> list) {mDatas = list;}public void setOnItemClickListener(onItemClickListener listener) {this.listener = listener;}/*** 设置刷新评论数据的方法*/public void notifyDataSetChanged() {removeAllViews(); //清空布局if (mDatas == null || mDatas.size() <= 0) {return;}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("listview item layout is null, please check getView()...");}addView(view, i, layoutParams);}}//赋值与颜色设置private View getView(final int position) {CommentsBean item = mDatas.get(position);String replyId = item.getUserCodeId();boolean hasReply = false;   // 是否有回复if (!TextUtils.isEmpty(replyId)) {hasReply = true;}TextView textView = new TextView(mContext);textView.setTextSize(15);textView.setTextColor(0xff686868); //回复与冒号 字体颜色SpannableStringBuilder builder = new SpannableStringBuilder();String name = item.getCreateBy();if (hasReply) {builder.append(setClickableSpan(item.getUpdateBy()));builder.append(" 回复 ");builder.append(setClickableSpan(name));} else {builder.append(setClickableSpan(name));}builder.append(" : ");builder.append(setClickableSpanContent(position, item));builder.append(" ");textView.setText(builder);// 设置点击背景色textView.setHighlightColor(getResources().getColor(android.R.color.transparent));
//        textView.setHighlightColor(0xff000000);final CircleMovementMethod method = new CircleMovementMethod(0xffcccccc, 0xffcccccc);textView.setMovementMethod(method);//        textView.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                if (method.isParseTv()) {if (listener != null) {listener.onItemClick(position, item);}
//                }
//            }
//        });return textView;}/*** 设置评论内容点击事件** @param item* @param position* @return*/public SpannableString setClickableSpanContent(final int position, final CommentsBean commentBean) {final SpannableString string = new SpannableString(commentBean.getCommentCount());ClickableSpan span = new ClickableSpan() {@Overridepublic void onClick(View widget) {if (listener != null) {listener.onItemClick(position, commentBean);}}@Overridepublic 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 SpannableString string = new SpannableString(item);ClickableSpan span = new ClickableSpan() {@Overridepublic void onClick(View widget) {// TODO: 2017/9/3 评论用户名字点击事件
//                Toast.makeText(mContext, "评论用户名字点击事件", Toast.LENGTH_SHORT).show();}@Overridepublic void updateDrawState(TextPaint ds) {super.updateDrawState(ds);// 设置显示的用户名文本颜色ds.setColor(0xff387dcc);ds.setUnderlineText(false);}};string.setSpan(span, 0, string.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);return string;}/*** 定义一个用于回调的接口*/public interface onItemClickListener {void onItemClick(int position, CommentsBean bean);}
}

2.背景色类 CircleMovementMethod

package com.june.wt.commentview;import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.BaseMovementMethod;
import android.text.method.Touch;
import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan;
import android.view.MotionEvent;
import android.widget.TextView;public class CircleMovementMethod extends BaseMovementMethod {private final static int DEFAULT_COLOR_ID = android.R.color.transparent;/*** 整个textView的背景色*/private int textViewBgColor;/*** 点击部分文字时部分文字的背景色*/private int clickableSpanBgClor;private BackgroundColorSpan mBgSpan;private ClickableSpan[] mClickLinks;private boolean isParseTv = false;public boolean isParseTv() {return isParseTv;}public void setParseTv(boolean parseTv) {isParseTv = parseTv;}/*** @param clickableSpanBgClor 点击选中部分时的背景色*/public CircleMovementMethod(int clickableSpanBgClor) {this.clickableSpanBgClor = clickableSpanBgClor;}/*** @param clickableSpanBgClor 点击选中部分时的背景色* @param textViewBgColor     整个textView点击时的背景色*/public CircleMovementMethod(int clickableSpanBgClor, int textViewBgColor) {this.textViewBgColor = textViewBgColor;this.clickableSpanBgClor = clickableSpanBgClor;}public boolean onTouchEvent(TextView widget, Spannable buffer,MotionEvent event) {int action = event.getAction();if (action == MotionEvent.ACTION_DOWN) {int x = (int) event.getX();int y = (int) event.getY();x -= widget.getTotalPaddingLeft();y -= widget.getTotalPaddingTop();x += widget.getScrollX();y += widget.getScrollY();Layout layout = widget.getLayout();int line = layout.getLineForVertical(y);int off = layout.getOffsetForHorizontal(line, x);mClickLinks = buffer.getSpans(off, off, ClickableSpan.class);if (mClickLinks.length > 0) {setParseTv(false);// 点击的是Span区域,不要把点击事件传递Selection.setSelection(buffer,buffer.getSpanStart(mClickLinks[0]),buffer.getSpanEnd(mClickLinks[0]));//设置点击区域的背景色mBgSpan = new BackgroundColorSpan(clickableSpanBgClor);buffer.setSpan(mBgSpan,buffer.getSpanStart(mClickLinks[0]),buffer.getSpanEnd(mClickLinks[0]),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);} else {setParseTv(true);// textview选中效果
//                widget.setBackgroundColor(textViewBgColor);widget.setBackgroundResource(DEFAULT_COLOR_ID);}} else if (action == MotionEvent.ACTION_UP) {if (mClickLinks.length > 0) {mClickLinks[0].onClick(widget);if (mBgSpan != null) {//移除点击时设置的背景spanbuffer.removeSpan(mBgSpan);}} else {}Selection.removeSelection(buffer);widget.setBackgroundResource(DEFAULT_COLOR_ID);} else if (action == MotionEvent.ACTION_MOVE) {//这种情况不用做处理} else {if (mBgSpan != null) {//移除点击时设置的背景spanbuffer.removeSpan(mBgSpan);}widget.setBackgroundResource(DEFAULT_COLOR_ID);}return Touch.onTouchEvent(widget, buffer, event);}}

四、使用

1.CeshiAdapter

package com.june.wt.commentviewimport android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.june.wt.Rclass CeshiAdapter(val context: Context) : RecyclerView.Adapter<CeshiAdapter.YuanDiHolder>() {var mDatas: List<CeshiBean>? = nullset(value) {field = valueif (value != null) {notifyDataSetChanged()}}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CeshiAdapter.YuanDiHolder {//LayoutInflater.from指定写法val view =LayoutInflater.from(parent.context).inflate(R.layout.android_ceshi_item, parent, false)return CeshiAdapter.YuanDiHolder(view)}override fun onBindViewHolder(holder: CeshiAdapter.YuanDiHolder, position: Int) {/*** 数据操作*/val ceshiBean = mDatas!![position]val comList = ceshiBean.commentListholder.tvName.text = ceshiBean.nameholder.commentView.setList(comList)holder.commentView.setOnItemClickListener { _, bean ->Log.e("++++++", "content = " + bean.commentCount)refushCommentLisitenner.setItemRefushComment(position, holder.commentView)}holder.commentView.notifyDataSetChanged()holder.btnPinglun.setOnClickListener {refushCommentLisitenner.setItemRefushComment(position, holder.commentView)}}override fun getItemCount(): Int {return if (mDatas != null) mDatas!!.size else 0}/*** 创建ViewHolder* 元素声明*/class YuanDiHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {var tvName: TextView = itemView.findViewById(R.id.tvName)var btnPinglun: TextView = itemView.findViewById(R.id.btnPinglun)var commentView: CommentsView = itemView.findViewById(R.id.commentView)}/*** 刷新新的评论页面* */lateinit var refushCommentLisitenner: RefushCommentLisitennerinterface RefushCommentLisitenner {fun setItemRefushComment(position: Int, commentView: CommentsView)}fun setRefushCommentClick(refushClick: RefushCommentLisitenner) {refushCommentLisitenner = refushClick}
}

2.CommentViewActivity

package com.june.wt.commentviewimport com.june.wt.R
import com.june.wt.base.BaseUnNeedVPActivity
import kotlinx.android.synthetic.main.android_ceshi_activity.*class CommentViewActivity : BaseUnNeedVPActivity() {lateinit var ceshiAdapter: CeshiAdapteroverride fun getLayout(): Int {return R.layout.android_ceshi_activity}override fun initView() {ceshiAdapter = CeshiAdapter(mContext)rvAndroid.adapter = ceshiAdapterceshiAdapter.setRefushCommentClick(object : CeshiAdapter.RefushCommentLisitenner {override fun setItemRefushComment(position: Int, commentView: CommentsView) {var newCommentList = ceshiList[position].commentList as MutableList<CommentsBean>var commBean = CommentsBean()commBean.id = "1"commBean.scopeId = "17"commBean.commentCount = "的点点滴滴多多多多多"commBean.userId = "208"commBean.createBy = "贾宝玉"commBean.userCodeId = "108"commBean.updateBy = "玉帝"newCommentList.add(commBean)commentView.setList(newCommentList)commentView.notifyDataSetChanged()}})}override fun initData() {getCeshiDatas()ceshiAdapter.mDatas = ceshiList}/*** 添加测试数据* */lateinit var ceshiList: MutableList<CeshiBean>fun getCeshiDatas() {ceshiList = mutableListOf()var ceshiBean = CeshiBean()ceshiBean.name = "账单上符合"var commentList = mutableListOf<CommentsBean>()var commBean = CommentsBean()commBean.id = "1"commBean.scopeId = "17"commBean.commentCount = "剑少的花费时间客户反馈司机电话副书记等回复"commBean.userId = "205"commBean.createBy = "张琪"commBean.userCodeId = "105"commBean.updateBy = "名企"commentList.add(commBean)ceshiBean.commentList = commentListceshiList.add(ceshiBean)ceshiBean = CeshiBean()ceshiBean.name = "就分号结束分角色"commentList = mutableListOf<CommentsBean>()commBean = CommentsBean()commBean.id = "2"commBean.scopeId = "18"commBean.commentCount = "噢噢噢噢偶偶偶偶偶偶偶偶多扩付所扩付或说所扩"commBean.userId = "206"commBean.createBy = "柯南"commBean.userCodeId = "106"commBean.updateBy = "鸣人"commentList.add(commBean)ceshiBean.commentList = commentListceshiList.add(ceshiBean)}
}

最后是交流公众号,大家可以关注一下

Android 自定义评论回复view相关推荐

  1. android自定义LinearLayout和View

    自定义线性布局经常用到: 第一种是在扩展的LinearLayout构造函数中使用Inflater加载一个布局,并从中提取出相关的UI组件进行封装,形成一个独立的控件.在使用该控件时,由于它所有的子元素 ...

  2. android自定义验证码倒计时View

    关于自定义View的构造方法里面的参数的含义可以参考: http://www.cnblogs.com/angeldevil/p/3479431.html 代码: 倒计时类: public class ...

  3. android自定义空的view,ListView android中的自定义空视图

    如果ListView适配器中没有数据,我想显示刷新Button和TextView.我还希望能够向将重新加载列表的按钮添加单击侦听器.以下是我定义当前活动的方式: protected void onCr ...

  4. Android 自定义手势解锁View

    直接上代码了: /****@ClassName:GraphicsView*@author:WYL*@Date:2022/9/29*/ class GraphicsView : View {privat ...

  5. Android 自定义数字角标

    需要显示购物车数量,网上看了一些实现方式,有的是通过把页面view控件作为子view添加的,但是会改变我已有的样式和操作,因此决定自己编写 实现显示角标的功能. 我这里的需求是使用FloatingAc ...

  6. Android 自定义 圆环,Android自定义view实现圆环效果实例代码

    先上效果图,如果大家感觉不错,请参考实现代码. 重要的是如何实现自定义的view效果 (1)创建类,继承view,重写onDraw和onMesure方法 public class CirclePerc ...

  7. Android仿支付宝UI功能开发,Android 自定义view仿支付宝咻一咻功能

    支付宝上有一个咻一咻的功能,就是点击图片后四周有水波纹的这种效果,今天也写一个类似的功能. 效果如下所示: 思路: 就是几个圆的半径不断在变大,这个可以使用动画缩放实现,还有透明动画 还有就是这是好几 ...

  8. android可以定义函数吗,Android自定义view 你所需要知道的基本函数总结

    Android自定义view 你所需要知道的基本函数 首先 往Canvas上面draw需要一个Paint. 画笔常用的函数有哪些呢.由于木有调试环境,函数基本上默写,有错请评论提出,蟹蟹! Paint ...

  9. android自定义view案例,Android自定义View的实现方法实例详解

    一.自绘控件 下面我们准备来自定义一个计数器View,这个View可以响应用户的点击事件,并自动记录一共点击了多少次.新建一个CounterView继承自View,代码如下所示: 可以看到,首先我们在 ...

最新文章

  1. python的工资为什么这么低-你拿着3k的工资,不明白为什么别人年薪 200万
  2. fs_struct和file_struct关系
  3. 模电这么学,谁还会说不懂晶体管?
  4. caffe 框架梳理(待续)
  5. AtCoder Beginner Contest 084(AB)
  6. socket编程初级
  7. 2016年的云计算安全趋势
  8. 《电脑报》:中国“人肉搜索第一案”幕后之谜
  9. [芯片] 2、接口技术·实验二·定时/计数器8253
  10. CCF NOI1031 等腰三角形
  11. 语音识别技术发展史与行业最佳实践全解析
  12. springmvc中校验框架(hibernate)
  13. MyBatis官方文档-简介
  14. 数字证书及 CA 的扫盲介绍
  15. android 语音播报,android实现语音播报textToSpeech
  16. 机器学习-分类Classification
  17. 中外合作办学硕士—社科院杜兰金融管理硕士,给23考研加一重保险
  18. 软件工程毕业设计课题(34)基于JAVA毕业设计JAVA医院预约挂号系统毕设作品项目
  19. C51 - DS18B20
  20. flutterdio_强大的Flutter http请求库dio

热门文章

  1. TCP/IP详解(卷1)勘误表
  2. php mysql开发实战 光盘_随书光盘-PHP开发实战1200例 | 软件库
  3. 光电设计竞赛国赛经历及感悟
  4. 反射望远镜的发展历程(4)
  5. 治疗性经颅磁刺激后大规模脑电图神经网络的变化
  6. office2003 安装步骤及注意事项
  7. html文件能放病毒吗,防火墙能防病毒吗?
  8. 用Multisim仿真设计有源、无源,二阶、四阶滤波器
  9. 易飞ERP进货单源码——复制报价单
  10. 计算机ata考试教案,ATA办公软件考级教案(四).docx