Android(安卓)ClickableRoundedBackground Span实现(初版)
16lz
2021-12-04
一、自定义圆角背景span
import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;import android.text.style.ReplacementSpan;import android.view.View;public abstract class RoundedBackgroundSpan extends ReplacementSpan { private static int CORNER_RADIUS = 10; private int backgroundColor = 0; private int textColor = 0; public RoundedBackgroundSpan(int backgroundColor, int textColor) { this.backgroundColor = backgroundColor; this.textColor = textColor; } @Override public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { return Math.round(paint.measureText(text, start, end)); } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { RectF rectF = new RectF(x , top - 8, x + measureText(paint, text, start, end) - 10, y + 16); paint.setColor(backgroundColor); canvas.drawRoundRect(rectF, CORNER_RADIUS, CORNER_RADIUS, paint); paint.setColor(textColor); canvas.drawText(text, start, end, x, y, paint); } private float measureText(Paint paint, CharSequence text, int start, int end) { return paint.measureText(text, start, end); } public abstract void onClick(View view);}
二、集成ClickableMovementMethod
import android.text.Layout;import android.text.Selection;import android.text.Spannable;import android.text.method.LinkMovementMethod;import android.text.style.ClickableSpan;import android.view.MotionEvent;import android.widget.TextView;public class ClickableMovementMethod extends LinkMovementMethod{ private static ClickableMovementMethod sInstance; public static ClickableMovementMethod getInstance() { if (sInstance == null) { sInstance = new ClickableMovementMethod(); } return sInstance; } @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || 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); RoundedBackgroundSpan[] roundedBackgroundSpans = buffer.getSpans(off, off, RoundedBackgroundSpan.class); if (roundedBackgroundSpans.length != 0) { if (action == MotionEvent.ACTION_UP) { roundedBackgroundSpans[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection(buffer, buffer.getSpanStart(roundedBackgroundSpans[0]), buffer.getSpanEnd(roundedBackgroundSpans[0])); } return true; } else { Selection.removeSelection(buffer); } } return false; }}
三、将2者融合起来
import android.view.View;/** * Created by ningdai.cx on 15/11/26. */public class ClickableRoundedBackgroundSpan extends RoundedBackgroundSpan { public ClickableRoundedBackgroundSpan(int backgroundColor, int textColor) { super(backgroundColor, textColor); } @Override public void onClick(View view) { }}
四、具体使用场景
TextView mTipContentTextView = (TextView) mActivity.findViewById(R.id.tip_content_text); ...... // 设置MovementMethod; mTipContentTextView.setMovementMethod(ClickableMovementMethod.getInstance()); // 新增SpannableString SpannableString tagSpan = new SpannableString(tipContent); int spanStartIndex; int spanEndIndex; int textColor = Color.parseColor("#666666"); int bgColor = Color.parseColor("#F5F5F5"); // 遍历需要变成圆角点击的tag列表 for (final String tag : tagArray) { spanStartIndex = tipContent.indexOf(tag); spanEndIndex = spanStartIndex + tag.length(); // 为SpannableString设置Span样式及点击事件 tagSpan.setSpan(new ClickableRoundedBackgroundSpan(bgColor, textColor) { @Override public void onClick(View view) { Toast.makeText(mActivity.getApplicationContext(), "U clicked " + tag, Toast.LENGTH_SHORT).show(); mTagClickListener.onTagClick(tag); } }, spanStartIndex, spanEndIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } mTipContentTextView.setText(tagSpan); mTipContentTextView.setLineSpacing(0, 1.5f);
先把实现方案记录下来,具体原理可参见Android API 都讲的比较详细。
更多相关文章
- Android中带分割线的九宫格
- Android编程中的常见小问题ZZ
- Android系统自带样式Theme总结
- android 设置Button或者ImageButton的背景透明
- android 之 selector
- android——xml drawable实现背景样式
- android 设计比较美观的登录界面
- Android(安卓)Drawable系列(1):自定义背景以及注意事项
- 【Android开发基础】应用界面主题Theme使用方法