TextView contiene enlaces parcialmente en los que se puede hacer clic y hay eventos de clic correspondientes en otras partes del enlace. El formato se define en el texto, public void setSpan(Object what, int start, int end, int flags) {} Haga clic para saber dónde Es necesario hacer clic en las palabras del texto.
Ejemplos 格式:Hola Android <b>Haga clic en Detalle # https://www.baidu.com</b>
Requisitos:
(1) <b> --- # Mostrar: fuente en la que se puede hacer clic en azul.
(2) # --- </b> No mostrar: URL en la que se puede hacer clic en fuente azul.
(3) La fuente predeterminada es negra.
1. De acuerdo con el proceso, primero obtenga el texto de <b> a </b>, interceptelo y empalme en el texto original. La URL usa setSpan (nuevo ClickableSpan()) para configurar el evento de clic para que salte. Algunos Los expertos han dicho, substring(
) Es tan fácil interceptar clics a través de ClickableSpan que no puedes decirlo, mira a continuación:
Si el formato de los ejemplos no es fijo:<b>ClickableSpan nos permite responder a eventos de clic cuando haga clic en el texto correspondiente de TextView # https://www.baidu.com </b>, como el URLSpan de uso común, se abrirá el enlace correspondiente cuando se haga clic. Para que TextView responda a los clics de ClickableSpan, <b>necesitamos configurar LinkMovementMethod, # https://www.baidu.com</b> Pero este\n\n" <b>LinkMovementMethod tiene muchos Pit# https://www.csdn.net</b> <b>LinkMovementMethod tiene otro gran hoyo# https://www.baidu.com</b>¿Cómo se resuelve? Hay muchos, setMovementMethod(LinkMovementMethod .getInstance()) deslizante, espacio, nueva línea.
Representación:
//Establece el hipervínculo en TextView para que se pueda hacer clic en spannableTextView.setMovementMethod(LinkMovementMethod.getInstance());
*Soporta Textview para establecer clics en texto enriquecido
*Establece la configuración del texto medio en Textview para que se pueda hacer clic y cambie de color,
*Establece setMovementMethod(LinkMovementMethod. getInstance()) Hay un conflicto entre hacer clic y deslizarse en Textview.
* Resuelva el problema de hacer clic en el área en blanco y aún tener eventos de clic.
//1. 截取并设置点击 Help class
public class MyDataHelp {
public static final String TAG = MyDataHelp.class.getSimpleName();
private static String start_label = "<b>", sub_label = "#", end_label = "</b>", http = "http";//设置截取的格式
//处理数据
public static void dealWithContent(String with_content, final CallBack callBack) {
Log.i(TAG, "获取到的content: " + with_content);
try {
final ArrayList<String> list = new ArrayList<>();
//按照</b>截取,看看有几个可以点击需要进行数据处理
String[] split = with_content.split(end_label);
for (String split_content : split) {
if (split_content.contains(start_label) && split_content.contains(sub_label)) {
String substring = split_content.substring(split_content.indexOf(start_label), split_content.length());
Log.i(TAG, "substring : " + substring);
list.add(substring);
}
}
ArrayList<String> list_title = new ArrayList<>(); //截取<b> --- # 显示的文字 list
final ArrayList<String> list_url = new ArrayList<>(); //截取<b> --- # URL
for (int i = 0; i < list.size(); i++) {
if (with_content.contains(list.get(i))) {
String list_content = list.get(i);
String sub_title = list_content.substring(list_content.indexOf(start_label) + 3, list_content.indexOf(sub_label));
final String url;
if (list_content.contains(http)) {
url = list_content.substring(list_content.indexOf(http), list_content.length());
} else {
url = list_content.substring(list_content.indexOf(sub_label) + 2, list_content.length());
}
String start = with_content.substring(0, with_content.indexOf(start_label));
String end = with_content.substring(with_content.indexOf(end_label) + 4, with_content.length());
String all_text = start + sub_title + end;
with_content = all_text;
Log.i(TAG, "all_text : " + all_text);
list_title.add(sub_title);
list_url.add(url);
Log.i(TAG, "sub_title : " + sub_title + " url: " + url);
}
}
SpannableStringBuilder ssb = new SpannableStringBuilder(with_content);//进行拼接和设置点击事件
int indexOf = 0;
for (int i = 0; i < list_title.size(); i++) {
String list_text = list_title.get(i);
list_text.replaceAll(" ", "");//替换中间的空格
final String URL = list_url.get(i);
Log.i(TAG, "list_text : " + list_text + " URL: " + URL);
//为了解决重复<b>Click Detail # https://www.baidu.com</b> 好多相同的indexOf默认只取第一个,接着往下遍历.
indexOf = with_content.indexOf(list_text, i == 0 ? 0 : indexOf + list_text.length());
if (indexOf == -1) {//找不到会返回-1,只好再重新查找
indexOf = with_content.indexOf(list_text);
}
//设置点击文字的click和颜色
ssb.setSpan(new ForegroundColorSpan(Color.parseColor("#2497df")), indexOf, indexOf + list_text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
Log.i(TAG, "click url: " + URL);
callBack.dealUrl(URL);
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
ds.setUnderlineText(false); //去除超链接的下划线
}
}, indexOf, indexOf + list_text.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //list_text.length() - 1为了解决点击空白区域依然有点击事件
Log.i(TAG, "ssb : " + ssb);
}
callBack.dealText(ssb);
} catch (Exception e) {
Log.i(TAG, "e.getMessage(): " + e.getMessage());//必要时走try
}
}
public interface CallBack {
void dealText(SpannableStringBuilder text);
void dealUrl(String URL);
}
}
// 2. 解决布局clcik与TextView本身滑动冲突
public class MyTextView extends TextView {
private static String TAG = "MyTextView";
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public boolean linkHit;//内部富文本是否被点击
private static long lastClickTime;
private static final long CLICK_DELAY = 500l;
@Override
public boolean performClick() { //最后响应3
if (linkHit) {
return true; //这样textView的OnClick事件不会响应
}
return super.performClick(); //调用监听的onClick方法
}
@Override
public boolean onTouchEvent(MotionEvent event) { //textView的OnClick事件响应,首先响应1
linkHit = false;
return super.onTouchEvent(event);
}
public static class CustomLinkMovementMethod extends LinkMovementMethod { //次之2
static CustomLinkMovementMethod sInstance;
//手指按下的点为(x1, y1)手指离开屏幕的点为(x2, y2)
float x1 = 0;
float x2 = 0;
float y1 = 0;
float y2 = 0;
@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); //水平偏移,第几个字
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
//解决拦截滑动时触发Textview link 点击事件
if (action == MotionEvent.ACTION_UP) {
//当手指离开的时候
x2 = event.getX();
y2 = event.getY();
if (y1 - y2 > 50) {
Log.i(TAG, "向上滑");
link = new ClickableSpan[0];
} else if (y2 - y1 > 50) {
Log.i(TAG, "向下滑");
link = new ClickableSpan[0];
}
} else {
//当手指按下的时候
x1 = event.getX();
y1 = event.getY();
}
//不是滑动、link.length != 0,拦截处理 Textview link 点击事件 ,证明点击了
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
link[0].onClick(widget);
return true;
}
} else {
Selection.removeSelection(buffer);
}
}
return Touch.onTouchEvent(widget, buffer, event);
}
public static CustomLinkMovementMethod getInstance() {
if (sInstance == null) {
sInstance = new CustomLinkMovementMethod();
}
return sInstance;
}
}
}
// 3. Textview 赋值
MyDataHelp.dealWithContent(content, new MyDataHelp.CallBack() {//处理富文本格式数据
@Override
public void dealText(SpannableStringBuilder ssb) {
tv_content.setText(ssb);
tv_content.setMovementMethod(MyTextView.CustomLinkMovementMethod.getInstance());//解决点击事件与Textview本身滑动冲突
tv_content.setHighlightColor(ContextCompat.getColor(getContext(), R.color.white));//去掉点击后的背景颜色为透明
}
@Override
public void dealUrl(String URL) {
clickListenerInterface.doLink(URL);
}
});
Si tiene otras soluciones, dígame
la dirección de descarga de la demostración.