前言
距离上一次发布文章又沉静了一段时间了,想到要写什么又感觉有点简单了,拖着拖着又不想写了。最近需求有个类似微信朋友圈的评论列表功能,
所以就静下心来写一下,写段代码,大神勿喷,可能有可能地方存在漏洞,看出问题的哥们也可以留言指出我的问题,大家共同进步。
正文:
那么接下来先看一下效果,看看是不是你想要的效果,(当然如果是鄙人的话,看到效果不是自己想要的或者说不是类似的我就会懒得看了)
当然这个做的还有很多需要优化的地方,有很多可以改进的地方。大家做为参考学习使用。
直接上图
效果呢就是这么一个效果,low 呢是有那么一点low。
不过这个不重要,这都是文本颜色字体的问题,调一调就好了。
Demo地址:https://download.csdn.net/download/qq_35070105/10352996
好那么接下来就给大家先整理出来了怎么去使用
(简单用的才爽)
先说一下设置值显示的方法这里就简单的看一下 两个方法(下面会给完整的代码的)
/** * 设置显示数据 * * @param commentator 回复人 * @param content 回复内容 */ public void setTextContent(String commentator,String content){ setTextContent(commentator,null ,content); } /** * 设置显示数据 * * @param commentator 回复人 * @param criticised 被回复人 * @param content 回复内容 */ public void setTextContent(String commentator,String criticised,String content){ SpannableStringBuilder ssb = new SpannableStringBuilder(); setMovementMethod(LinkTouchMovementMethod.getInstance()); if (commentator != null){ ssb.append(commentator); ssb.setSpan(new TouchableSpan(REPLY),0,commentator.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (criticised != null){ ssb.append(REPLY_HINT); ssb.append(criticised); ssb.setSpan(new TouchableSpan(REPLY_TO), commentator.length()+REPLY_HINT.length(), commentator.length()+REPLY_HINT.length()+criticised.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (content != null){ ssb.append(":"+content); } this.setText(ssb,BufferType.NORMAL); }
<com.example.peng.butterknifetest.UICommentTextView android:id="@+id/ui_comment_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#333333" android:textSize="24sp" app:comment_IsLongClickCopyOf="true" app:comment_UserHintColor="#ff0000" app:comment_UserHintBgNormalColor="@android:color/transparent" app:comment_UserHintBgPressedColor="#e0e0e0" app:comment_ViewBackgroundNormalColor="@android:color/transparent" app:comment_ViewBackgroundPressedColor="#e0e0e0"/>
那么我在这就介绍一下这个熟悉分别代表的是什么意思
效果如果都设置好了,样式也调式到美美的状态,那么下面应该是做点,点击事件了
(我们在Xml 布局文件写完,在java 文件中找到控件,
findViewbyId 还是使用 ButterKnife 这个就根据你自己喜欢咯)
这里就三个方法,可以根据你自己需要重写
uiCommentTextView.setCommentTextViewListener(new CommentTextViewListener(){ @Override public void OnLongClick(Context context, UICommentTextView textView) { Toast.makeText(MainActivity.this,"OnLongClick",Toast.LENGTH_SHORT).show(); } @Override public void OnReplyClick(Context context) { Toast.makeText(MainActivity.this,"OnReplyClick",Toast.LENGTH_SHORT).show(); } @Override public void OnReplyToClick(Context context) { Toast.makeText(MainActivity.this,"OnReplyToClick",Toast.LENGTH_SHORT).show(); } });
那么接下来我就直接贴代码了(不在做过多的介绍咯)
/** * Created by Peng on 2018/1/13. */ @SuppressLint("AppCompatCustomView") public class UICommentTextView extends TextView { private final static int REPLY = 0x1; private final static int REPLY_TO = 0x2; private static boolean mIsInteriorClick = false;//内部是否被点击 private static boolean mIsLongClick = false;//是否是长按 private static final int COMMENTATOR_USER_HINT_COLOR = 0xFF0000FF; private static final int COMMENTATOR_HINT_BG_PRESSED = 0xFFE0E0E0; private static final int COMMENTATOR_HINT_BG_NORMAL = 0x00000000; private static final int UI_BACKGROUND_RESOURCE_PRESSED_COLOR = 0xFFE0E0E0; private static final int UI_BACKGROUND_RESOURCE_NORMAL_COLOR = 0x00000000; private static int mUserHintColor = COMMENTATOR_USER_HINT_COLOR; private static int mUserHintBgPressedColor = COMMENTATOR_HINT_BG_PRESSED; private static int mUserHintBgNormalColor = COMMENTATOR_HINT_BG_NORMAL; private static int mViewBackgroundPressedColor = UI_BACKGROUND_RESOURCE_PRESSED_COLOR; private static int mViewBackgroundNormalColor = UI_BACKGROUND_RESOURCE_NORMAL_COLOR; private static boolean mIsLongClickCopyOf = false; private String REPLY_HINT = "回复"; private CommentTextViewListener commentTextViewListener; public UICommentTextView(Context context) { super(context); } public UICommentTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); initAttr(context,attrs); } public UICommentTextView(final Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttr(context,attrs); } private void initAttr(Context context, AttributeSet attrs) { if (attrs == null) return; TypedArray type = getContext().obtainStyledAttributes(attrs, R.styleable.UICommentTextView); if (type == null) return; for (int i = 0; i < type.getIndexCount(); i++) { int attr = type.getIndex(i); if (attr == R.styleable.UICommentTextView_comment_UserHintColor){ mUserHintColor = type.getInteger(attr,COMMENTATOR_USER_HINT_COLOR); }else if (attr == R.styleable.UICommentTextView_comment_UserHintBgPressedColor){ mUserHintBgPressedColor = type.getInteger(attr,COMMENTATOR_HINT_BG_PRESSED); }else if (attr == R.styleable.UICommentTextView_comment_UserHintBgNormalColor){ mUserHintBgNormalColor = type.getInteger(attr,COMMENTATOR_HINT_BG_NORMAL); }else if (attr == R.styleable.UICommentTextView_comment_ViewBackgroundPressedColor){ mViewBackgroundPressedColor = type.getInteger(attr,UI_BACKGROUND_RESOURCE_PRESSED_COLOR); }else if (attr == R.styleable.UICommentTextView_comment_ViewBackgroundNormalColor){ mViewBackgroundNormalColor = type.getInteger(attr,UI_BACKGROUND_RESOURCE_NORMAL_COLOR); }else if (attr == R.styleable.UICommentTextView_comment_IsLongClickCopyOf){ mIsLongClickCopyOf = type.getBoolean(attr,false); } } type.recycle(); } /** * 设置显示数据 * * @param commentator 回复人 * @param content 回复内容 */ public void setTextContent(String commentator,String content){ setTextContent(commentator,null ,content); } /** * 设置显示数据 * * @param commentator 回复人 * @param criticised 被回复人 * @param content 回复内容 */ public void setTextContent(String commentator,String criticised,String content){ SpannableStringBuilder ssb = new SpannableStringBuilder(); setMovementMethod(LinkTouchMovementMethod.getInstance()); if (commentator != null){ ssb.append(commentator); ssb.setSpan(new TouchableSpan(REPLY),0,commentator.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (criticised != null){ ssb.append(REPLY_HINT); ssb.append(criticised); ssb.setSpan(new TouchableSpan(REPLY_TO), commentator.length()+REPLY_HINT.length(), commentator.length()+REPLY_HINT.length()+criticised.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (content != null){ ssb.append(":"+content); } this.setText(ssb,BufferType.NORMAL); } private class TouchableSpan extends ClickableSpan{ private boolean mIsPressed = false; private int clickType; public TouchableSpan(int clickType) { this.clickType = clickType; } public void setIsPressed(boolean mIsPressed) { this.mIsPressed = mIsPressed; } @Override public void onClick(View widget) { switch (clickType){ case REPLY: if (commentTextViewListener != null) { commentTextViewListener.OnReplyClick(getContext()); } break; case REPLY_TO: if (commentTextViewListener != null) { commentTextViewListener.OnReplyToClick(getContext()); } break; } } @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); ds.setColor(mUserHintColor); ds.bgColor = mIsPressed ? mUserHintBgPressedColor : mUserHintBgNormalColor; ds.setUnderlineText(false); } } /** * 自定义LinkMovementMethod */ public static class LinkTouchMovementMethod extends LinkMovementMethod{ static LinkTouchMovementMethod sInstance; private TouchableSpan mTouchableSpan; public static LinkTouchMovementMethod getInstance(){ if (sInstance == null){ sInstance = new LinkTouchMovementMethod(); } return sInstance; } @Override public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN){ mTouchableSpan = getPressedSpan(textView,spannable,event); if (mTouchableSpan != null){ mIsLongClick = false; mTouchableSpan.setIsPressed(true); Selection.setSelection(spannable,spannable.getSpanStart(mTouchableSpan), spannable.getSpanEnd(mTouchableSpan)); mIsInteriorClick = true; }else { textView.setBackgroundColor(mViewBackgroundPressedColor); } } else if (action == MotionEvent.ACTION_UP){ if (mTouchableSpan != null){ mTouchableSpan.setIsPressed(false); if (!mIsLongClick){ super.onTouchEvent(textView, spannable, event); } mIsInteriorClick = true; } textView.setBackgroundResource(mViewBackgroundNormalColor); mTouchableSpan = null; Selection.removeSelection(spannable); }else if (action == MotionEvent.ACTION_MOVE){ TouchableSpan touchableSpan = getPressedSpan(textView,spannable,event); if (mTouchableSpan != null && touchableSpan != mTouchableSpan){ mTouchableSpan.setIsPressed(false); Selection.removeSelection(spannable); } } return Touch.onTouchEvent(textView, spannable, event); } private TouchableSpan getPressedSpan(TextView textView,Spannable spannable,MotionEvent event){ int x = (int) event.getX(); int y = (int) event.getY(); x -= textView.getTotalPaddingLeft(); y -= textView.getTotalPaddingTop(); x += textView.getScrollX(); y += textView.getScrollY(); Layout layout = textView.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); TouchableSpan[] link = spannable.getSpans(off, off, TouchableSpan.class); TouchableSpan touchedSpan = null; if (link.length > 0) { touchedSpan = link[0]; } return touchedSpan; } } /** * ClickableSpan的点击事件会跟TexView的点击事件冲突, * TextView-onTouchEvent >> LinkMovementMethod-onTouchEvent >> TextView-performClick >> TextView-onClick * * 需要判断是否是内部点击了,如果是内部点击了则需要拦截事件再继续往下传。 * 否则就将事件继续传下去 */ @Override public boolean performClick() { if (mIsInteriorClick) { return true; } return super.performClick(); } /** * 监听长按事件 实现长按复制 * * @return */ @Override public boolean performLongClick() { mIsLongClick = true; this.setBackgroundColor(mViewBackgroundPressedColor); if (mIsLongClickCopyOf){ ClipboardManager copy = (ClipboardManager) getContext() .getSystemService(Context.CLIPBOARD_SERVICE); assert copy != null; copy.setPrimaryClip(ClipData.newPlainText(null, this.getText().toString())); Toast.makeText(getContext(), "复制成功", Toast.LENGTH_SHORT).show(); } if (commentTextViewListener != null){ commentTextViewListener.OnLongClick(getContext(),this); } return true; } @Override public boolean onTouchEvent(MotionEvent event) { mIsInteriorClick = false; return super.onTouchEvent(event); } public void setIsLongClickCopyOf(boolean mIsLongClickCopyOf) { this.mIsLongClickCopyOf = mIsLongClickCopyOf; } public void setCommentTextViewListener(CommentTextViewListener commentTextViewListener){ this.commentTextViewListener = commentTextViewListener; } }
接下来就是接口 。以及接口实现类
public interface CommentInterface{ void OnReplyClick(Context context); void OnReplyToClick(Context context); void OnLongClick(Context context,UICommentTextView textView); }
这里呢,可以根据自己做一些默认的操作
/** * Created by Peng on 2018/1/15. */ public abstract class CommentTextViewListener implements CommentInterface{ @Override public void OnReplyToClick(Context context) { } @Override public void OnReplyClick(Context context) { } @Override public void OnLongClick(Context context, UICommentTextView textView) { } }
接下来就是配置参数的了
(如图在values 资源文件下,创建attr_comment_text_view.xml)
然后将下列代码copy 进入即可
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="UICommentTextView"> <attr name="comment_UserHintColor" format="reference|color"/> <attr name="comment_UserHintBgPressedColor" format="reference|color"/> <attr name="comment_UserHintBgNormalColor" format="reference|color"/> <attr name="comment_ViewBackgroundPressedColor" format="reference|color"/> <attr name="comment_ViewBackgroundNormalColor" format="reference|color"/> <attr name="comment_IsLongClickCopyOf" format="reference|boolean"/> </declare-styleable> </resources>
ok! 到这就已经代码贴完了,欢迎大家吐槽我写的不足的地方。不懂的地方也可以留言,本人看到了会回复的。
Demo地址:https://download.csdn.net/download/qq_35070105/10352996