SpannableString中的ClickableSpan和Textview点击事件冲突解决

来源:互联网 发布:神仙道失却之阵数据 编辑:程序博客网 时间:2024/05/01 22:00

背景描述:项目中有这样的需求:在展示评论内容的Textview中展示文字,其中包含3种类型数据:
1、普通文字:评论内容或者回复内容。因为这个Textview是展示评论或者回复的,点击后,要展示软键盘(popupwindow等忽略)
2、股票代码:该类型文字显示另一种颜色,并且点击后去到展示webView的activity展示股票网页
3、关联的人名:如:@123,显示不同于普通文字的颜色,点击后去到这个人的个人详情页

出现问题:在用SpannableString中的ClickableSpan的时候,会出现问题:点击了股票代码或者人名后,虽然会跳转,但是,会在跳转过程中出现软键盘,到底目标activity后,软键盘消失。这样展示不美观

解决方法:需要将点击的关键字的点击事件(即:ClickableSpan的点击事件和Textview的点击事件分开)

效果图:
图1:
这里写图片描述

———————————————————————————————————–
图2:
这里写图片描述

——————————————————————————————————–
代码:
1、activity:

package com.chen.customviewdemo.activity;import android.content.Context;import android.view.View;import android.view.inputmethod.InputMethodManager;import com.chen.customviewdemo.R;import com.chen.customviewdemo.bean.KeyBean;import com.chen.customviewdemo.view.MyTextView_1;import com.chen.customviewdemo.view.MyTextView_2;import java.util.ArrayList;/** * 一个Textview中,有需要点击后专门处理的关键字,也有Textview自己的点击事件, * 如:点击关键字跳转到其他activity中,点击非关键字后出现软键盘 * 有时候,会出现这样的情况:点击关键字后,跳转过程中,软键盘会弹出一瞬间。影响美观. */public class MainActivity_34_Maching_ClickableSpan extends BaseActivity {    /**     * 说明:     * MyTextView_1:没有对关键字区域专门处理,点击后,非关键字区域还是会得到点击事件     * MyTextView_2:对关键字区域专门处理,点击后,非关键字区域没有获得点击事件     * 点击MyTextView_1中的关键字区域去跳转,没有出现软键盘闪现问题。但是项目中确实出现过。建议使用MyTextView_2     * 这里,为了说明情况,没有使用跳转。而是点击后弹出吐司。     * 在MyTextView_1中,点击关键字,弹出吐司,并且出现软键盘     * 在MyTextView_2中,点击关键字,仅弹出吐司,不出现软键盘     */    MyTextView_1 my_textview_1;    MyTextView_2 my_textview_2;    @Override    void initview() {        setContentView(R.layout.activity_main_34);        my_textview_1 = (MyTextView_1) findViewById(R.id.my_textview_1);        my_textview_2 = (MyTextView_2) findViewById(R.id.my_textview_2);        ArrayList<KeyBean> keyBeanList = new ArrayList<KeyBean>();        keyBeanList.add(new KeyBean("我", "我"));        keyBeanList.add(new KeyBean("你", "你"));        keyBeanList.add(new KeyBean("他", "他"));        keyBeanList.add(new KeyBean("哦", "哦"));        keyBeanList.add(new KeyBean("哈哈", "哈哈"));        keyBeanList.add(new KeyBean("605", "605"));        keyBeanList.add(new KeyBean("@嗯嗯", "嗯嗯"));        String content = "我们123哈哈哦缴费基数机诶@嗯嗯5623";        String redStr = "123";        my_textview_1.insertData(content, redStr, keyBeanList);        my_textview_1.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                showKeyBoard();            }        });        my_textview_2.insertData(content, redStr, keyBeanList);        my_textview_2.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                showKeyBoard();            }        });    }    /**     * 展示软键盘     */    public void showKeyBoard() {        InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);        inputManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);    }}

2、布局:activity_main_34

<?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="match_parent"              android:background="#ffffff"              android:orientation="vertical"    >    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dp"        android:gravity="center"        android:padding="5dp"        android:text="Activity34_ClickableSpan和Textview点击事件冲突"        android:textColor="#ec434b"        android:textSize="20sp"/>    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dp"        android:gravity="center"        android:padding="5dp"        android:text="tv_1"        android:textSize="20sp"/>    <com.chen.customviewdemo.view.MyTextView_1        android:id="@+id/my_textview_1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dp"        android:background="#f6f6f6"        android:padding="10dp"/>    <View        android:layout_width="match_parent"        android:layout_height="1dp"        android:layout_marginTop="20dp"        android:background="#000000"        />    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dp"        android:gravity="center"        android:padding="5dp"        android:text="tv_2"        android:textSize="20sp"/>    <com.chen.customviewdemo.view.MyTextView_2        android:id="@+id/my_textview_2"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dp"        android:background="#f6f6f6"        android:padding="10dp"/></LinearLayout>

3、MyTextView_1:没有对关键字区域专门处理,点击后,非关键字区域还是会得到点击事件

package com.chen.customviewdemo.view;import android.content.Context;import android.text.SpannableString;import android.text.Spanned;import android.text.TextPaint;import android.text.TextUtils;import android.text.method.LinkMovementMethod;import android.text.style.ClickableSpan;import android.util.AttributeSet;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.chen.customviewdemo.R;import com.chen.customviewdemo.bean.KeyBean;import java.util.ArrayList;public class MyTextView_1 extends TextView {    private Context context;    private String toRedWord = "";    public MyTextView_1(Context context) {        this(context, null);    }    public MyTextView_1(Context context, AttributeSet attrs) {        this(context, attrs, -1);    }    public MyTextView_1(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.context = context;        myTextViewInit();    }    /**     * 初始化     */    private void myTextViewInit() {    }    public void insertData(String str, String redStr, final ArrayList<KeyBean> keyBeanList) {        toRedWord = redStr;        //        final SpannableString spannableString = ExpressionUtil.getSpannableString(str, context);        SpannableString spannableString = new SpannableString(str);        String content = spannableString.toString();        //处理文本中的关键字        if (keyBeanList != null && keyBeanList.size() > 0) {            for (int i = 0; i < keyBeanList.size(); i++) {                final String data = keyBeanList.get(i).getContent();                final String hide_content = keyBeanList.get(i).getHide_content();                String temp = content;                int startNew = 0;                int startOld = 0;                if (temp.contains(data)) {                    while (temp.contains(data)) {                        spannableString.setSpan(new ClickableSpan() {                                                    @Override                                                    public void updateDrawState(TextPaint ds) {                                                        // TODO Auto-generated method stub                                                        super.updateDrawState(ds);                                                        ds.setColor(context.getResources().getColor(R.color.linkcolor));                                                        ds.setUnderlineText(false);                                                    }                                                    @Override                                                    public void onClick(View widget) {                                                        Toast.makeText(context, hide_content, Toast.LENGTH_SHORT).show();                                                        //Intent intent = null;                                                        //if (data.startsWith("@")) {                                                        //   intent = new Intent(context, PersonActivity.class);                                                        //} else {                                                        //    intent = new Intent(context, WebActivity.class);                                                        //}                                                        //intent.putExtra("hide_content", hide_content);                                                        //context.startActivity(intent);                                                    }                                                }, startOld + temp.indexOf(data), startOld + temp.indexOf(data) + data.length(),                                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                        setText(spannableString);                        setMovementMethod(LinkMovementMethod.getInstance());                        startNew = temp.indexOf(data) + data.length();                        startOld += startNew;                        temp = temp.substring(startNew);                    }                } else {                    setText(spannableString);                }            }        } else {            setText(spannableString);        }        //处理要变红的字        if (!TextUtils.isEmpty(toRedWord)) {            //只要把关键字变红就行了,不需要加点击事件。如果需要,可以自己加            String temp = content;            int startNew = 0;            int startOld = 0;            while (temp.contains(toRedWord)) {                spannableString.setSpan(new ClickableSpan() {                                            @Override                                            public void updateDrawState(TextPaint ds) {                                                // TODO Auto-generated method stub                                                super.updateDrawState(ds);                                                ds.setColor(0xffff0000);                                                ds.setUnderlineText(false);                                            }                                            @Override                                            public void onClick(View widget) {                                            }                                        }, startOld + temp.indexOf(toRedWord), startOld + temp.indexOf(toRedWord) + toRedWord.length(),                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                setText(spannableString);                setMovementMethod(LinkMovementMethod.getInstance());                startNew = temp.indexOf(toRedWord) + toRedWord.length();                startOld += startNew;                temp = temp.substring(startNew);            }        } else {            setText(spannableString);        }    }}

4、MyTextView_2:对关键字区域专门处理,点击后,非关键字区域没有获得点击事件

package com.chen.customviewdemo.view;import android.content.Context;import android.text.Layout;import android.text.Selection;import android.text.Spannable;import android.text.SpannableString;import android.text.Spanned;import android.text.TextPaint;import android.text.TextUtils;import android.text.method.LinkMovementMethod;import android.text.method.Touch;import android.text.style.ClickableSpan;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.chen.customviewdemo.R;import com.chen.customviewdemo.bean.KeyBean;import java.util.ArrayList;public class MyTextView_2 extends TextView {    private Context context;    private String toRedWord = "";    public MyTextView_2(Context context) {        this(context, null);    }    public MyTextView_2(Context context, AttributeSet attrs) {        this(context, attrs, -1);    }    public MyTextView_2(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.context = context;        myTextViewInit();    }    /**     * 初始化     */    private void myTextViewInit() {    }    public void insertData(String str, String redStr, final ArrayList<KeyBean> keyBeanList) {        toRedWord = redStr;        //        final SpannableString spannableString = ExpressionUtil.getSpannableString(str, context);        SpannableString spannableString = new SpannableString(str);        String content = spannableString.toString();        //处理文本中的关键字        if (keyBeanList != null && keyBeanList.size() > 0) {            for (int i = 0; i < keyBeanList.size(); i++) {                final String data = keyBeanList.get(i).getContent();                final String hide_content = keyBeanList.get(i).getHide_content();                String temp = content;                int startNew = 0;                int startOld = 0;                if (temp.contains(data)) {                    while (temp.contains(data)) {                        spannableString.setSpan(new ClickableSpan() {                                                    @Override                                                    public void updateDrawState(TextPaint ds) {                                                        // TODO Auto-generated method stub                                                        super.updateDrawState(ds);                                                        ds.setColor(context.getResources().getColor(R.color.linkcolor));                                                        ds.setUnderlineText(false);                                                    }                                                    @Override                                                    public void onClick(View widget) {                                                        Toast.makeText(context, hide_content, Toast.LENGTH_SHORT).show();                                                        //Intent intent = null;                                                        //if (data.startsWith("@")) {                                                        //     intent = new Intent(context, PersonActivity.class);                                                        //} else {                                                        //     intent = new Intent(context, WebActivity.class);                                                        //}                                                        //intent.putExtra("hide_content", hide_content);                                                        //context.startActivity(intent);                                                    }                                                }, startOld + temp.indexOf(data), startOld + temp.indexOf(data) + data.length(),                                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                        setText(spannableString);                        setMovementMethod(CustomLinkMovementMethod.getInstance());                        startNew = temp.indexOf(data) + data.length();                        startOld += startNew;                        temp = temp.substring(startNew);                    }                } else {                    setText(spannableString);                }            }        } else {            setText(spannableString);        }        //处理要变红的字        if (!TextUtils.isEmpty(toRedWord)) {            //只要把关键字变红就行了,不需要加点击事件。如果需要,可以自己加            String temp = content;            int startNew = 0;            int startOld = 0;            while (temp.contains(toRedWord)) {                spannableString.setSpan(new ClickableSpan() {                                            @Override                                            public void updateDrawState(TextPaint ds) {                                                // TODO Auto-generated method stub                                                super.updateDrawState(ds);                                                ds.setColor(0xffff0000);                                                ds.setUnderlineText(false);                                            }                                            @Override                                            public void onClick(View widget) {                                            }                                        }, startOld + temp.indexOf(toRedWord), startOld + temp.indexOf(toRedWord) + toRedWord.length(),                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                setText(spannableString);                setMovementMethod(CustomLinkMovementMethod.getInstance());                startNew = temp.indexOf(toRedWord) + toRedWord.length();                startOld += startNew;                temp = temp.substring(startNew);            }        } else {            setText(spannableString);        }    }    //-------------------------------------------------------------    public boolean linkHit;//内部链接是否被点击    @Override    public boolean performClick() {        if (linkHit) {            return true;        }        return super.performClick();    }    @Override    public boolean onTouchEvent(MotionEvent event) {        linkHit = false;        return super.onTouchEvent(event);    }    public static class CustomLinkMovementMethod extends LinkMovementMethod {        static CustomLinkMovementMethod 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);                ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);                if (link.length != 0) {                    if (action == MotionEvent.ACTION_UP) {                        link[0].onClick(widget);                    } else if (action == MotionEvent.ACTION_DOWN) {                        Selection.setSelection(buffer,                                buffer.getSpanStart(link[0]),                                buffer.getSpanEnd(link[0]));                    }                    if (widget instanceof MyTextView_2) {                        ((MyTextView_2) widget).linkHit = true;                    }                    return true;                } else {                    Selection.removeSelection(buffer);                    super.onTouchEvent(widget, buffer, event);                    return false;                }            }            return Touch.onTouchEvent(widget, buffer, event);        }        public static CustomLinkMovementMethod getInstance() {            if (sInstance == null) {                sInstance = new CustomLinkMovementMethod();            }            return sInstance;        }    }}

5、KeyBean

package com.chen.customviewdemo.bean;/** * 关键字bean。 * 包含显式内容和隐式内容。 * 如:在界面上显示“百度”,点击了它,就去一个界面打开百度的网页。要打开网页,肯定需要Url。这就需要,在点击的时候,把Url传递过去。 * 这个时候,这个Url,就是隐式内容了。不必让用户看到,只是在触发后,隐含的做一定操作就行 */public class KeyBean {    public KeyBean(String content, String hide_content) {        this.content = content;        this.hide_content = hide_content;    }    /**     * 内容     */    public String content;    /**     * 隐藏的内容,点击内容后,要传递的值或者要做的事     */    public String hide_content;    public String getContent() {        return content;    }    public void setContent(String content) {        this.content = content;    }    public String getHide_content() {        return hide_content;    }    public void setHide_content(String hide_content) {        this.hide_content = hide_content;    }}
0 0