我想单纯靠一个文本实现微信回复评论的效果,在一列回复文本中点击某一行,然后该行的背景色改变并且弹出对话框,如下图,我们想要回复A,那么就点击A所在的那一行(A回复B:哈哈哈)。
注意,这里两行包括下面一系列的回复文本都是在一个textView中。
网上查了许久,结合自己的一些知识,终于实现了。
揭晓答案(步骤如下):
/** *
对于第二行来说
commentName为A
replyName为B,
commentContent为内容
* **/
1.
SpannableString commentReplyNameContent = null;
commentReplyNameContent = new SpannableString(commentName + "回复" + replyName + ":" + commentContent);
commentReplyNameContent.setSpan(new ClickableSpan() //设置点击时候的效果(在这里只是弹出键盘而已) { @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); ds.setUnderlineText(false); //取消下划线 } @Override public void onClick(View widget) { showKeyBoard(comment.getComentName()); //弹出键盘 //或者进行其他操作,comment.getComentName()为要回复的人的名字,即点击这二行的话,comment.getComentName()就为A } }, 0, commentName.length() + replyName.length() + commentContent.length() + 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); commentReplyNameContent.setSpan //设置A的颜色 (new ForegroundColorSpan(Color.BLUE), 0, commentName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); commentReplyNameContent.setSpan //设置整一行的背景为黑色 (new ForegroundColorSpan(Color.BLACK), commentName.length(), commentName.length() + replyName.length() + commentContent.length() + 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); /** * replyContent为此textView * **/ replyContent.append("\n"); //换行 replyContent.append(commentReplyNameContent);// 把这一行追加在textView后面 replyContent.setMovementMethod(new MyLinkMovementMethod());//这句话是为了响应点击效果。
2.点击改变那一行的背景色,重写LinkMovementMethod
private class MyLinkMovementMethod extends LinkMovementMethod { @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft();// 返回textView的偏移量,如textView设置了padding=3px,则返回3 y -= widget.getTotalPaddingTop(); /** * 左侧超出屏幕的偏移量,如一个view可左右滑动,由于此view比较大,左侧的view被挡住了, * 被挡住的偏移量就是getScrollX(),同理getScrollY() */ x += widget.getScrollX(); y += widget.getScrollY(); // 上述的目的是定位出点击的位置 在整个view组件的绝对坐标(不是屏幕的相对坐标) Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); // 获取点击位置的 text的行数 int off = layout.getOffsetForHorizontal(line, x);// 获取点击位置的偏移量 // 通过偏移量来获取span (具体是通过偏移量对应的span来确定) ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); buffer.setSpan(new BackgroundColorSpan(Color.TRANSPARENT), buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Selection.removeSelection(buffer); } else if (action == MotionEvent.ACTION_DOWN) { buffer.setSpan(new BackgroundColorSpan(Color.GRAY), buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } else if (action == MotionEvent.ACTION_MOVE) { buffer.setSpan(new BackgroundColorSpan(Color.TRANSPARENT), buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Selection.removeSelection(buffer); } return true; } else { Selection.removeSelection(buffer); } } //必须returnsuper.onTouchEvent(widget, buffer, event); //否则因为重写了onTouchEvent,导致在action_up的时候无法调用ClickableSpan return super.onTouchEvent(widget, buffer, event); } }
3.弹出键盘
/** * 弹出软键盘 */ private void showKeyBoard(String name) { commentEdit.setHint("回复"+name); //输入框显示要回复谁 commentEdit.requestFocus(); (new Handler()).postDelayed(new Runnable() { public void run() { ((InputMethodManager) (commentEdit.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE))) .toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); } }, 100); }
时间: 2024-10-06 07:57:28