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
- SpannableString中的ClickableSpan和Textview点击事件冲突解决
- TextView ClickableSpan onClickListener点击事件冲突
- SpannableString的点击事件以及颜色设置ClickableSpan
- SpannableString中的LinkMovementMethod和ClickableSpan的实现安卓可点击有颜色文字使用
- SpannableString中的LinkMovementMethod和ClickableSpan的实现安卓可点击有颜色文字使用
- textView autolink 和onclick 点击事件冲突
- 可滚动textView 和点击事件冲突
- ListView的Item里的TextView设置ClickableSpan和LinkMovementMethod导致ListView无法响应点击事件
- 在ListView中的Text添加spannableString 点击事件与ListView的OnItemClick事件冲突的解决办法
- 使用SpannableString,ClickableSpan,文字部分可点击
- listview和checkbox点击事件冲突解决
- SpannableString、ClickableSpan
- 使用Spannablestring和ClickableSpan实现仿手机qq评论点击效果
- 设置TextView下划线并响应点击事件(SpannableString)
- [android篇]textview中片段响应点击事件(SpannableString)
- Android篇textview中片段响应点击事件(SpannableString)
- 设置TextView部分文字下划线并响应点击事件(SpannableString)
- RecyclerView添加点击事件和textView的超链接点击事件冲突
- SpringMVC 3(数据处理、显示modelview/modelmap,乱码及Restful)
- 后端框架中,如Hibernate框架,为什么老是喜欢在XXdao.java的类中设置一个static成员变量
- mysql给root开启远程访问权限,修改root密码
- 【链接】制作苹果推送通知APNS服务器证书文件
- 手机适配
- SpannableString中的ClickableSpan和Textview点击事件冲突解决
- SVN
- MATLAB2016下载安装及破解
- 【JAVA】5.标识符、关键字
- 程序员面试金典第一章:数组与字符串(7)清除行列
- set_include_path和get_include_path用法详解
- 编程遇到的一些问题
- BeanUtils.copyProperties支持Date类型
- Wox:高效的快速启动器工具