问题:在A activity中传递一个SpannableString到B activity中,并最终传递到B activity中的TextView中,但是没有展示出Span效果。

解决:阅读TextView.setText()方法

 // If suggestions are not enabled, remove the suggestion spans from the text
if (!isSuggestionsEnabled()) {
text = removeSuggestionSpans(text);
} ... if (type == BufferType.EDITABLE || getKeyListener() != null
|| needEditableForNotification) {
//略
} else if (precomputed != null) {
//略
} else if (type == BufferType.SPANNABLE || mMovement != null) {
text = mSpannableFactory.newSpannable(text);
} else if (!(text instanceof CharWrapper)) {
text = TextUtils.stringOrSpannedString(text);
}

看到会根据BufferType对传入的text重新赋值,于是回溯找到传入BufferType的地方:

public void setText(CharSequence text, BufferType type) {
setText(text, type, true, 0); if (mCharWrapper != null) {
mCharWrapper.mChars = null;
}
}

公有方法,传入BufferType,查看BufferType:

/**
* Type of the text buffer that defines the characteristics of the text such as static,
* styleable, or editable.
*/
public enum BufferType {
NORMAL, SPANNABLE, EDITABLE
}

可以看到BufferType是枚举类型,有三种类型,SpannableString实现了Spannable接口,那么这里选择SPANNABLE,尝试后还是没有span效果,又注意到setText方法中mSpannableFactory.newSpannable会重新生成一个SpannableString:

public SpannableString(CharSequence source) {
this(source, false /* ignoreNoCopySpan */);
} public SpannableString(CharSequence source, boolean ignoreNoCopySpan) {
super(source, 0, source.length(), ignoreNoCopySpan);
}

可以看到,默认将整个source作为一个span,这显然不是我们想要的。

重新阅读setText源码,发现:

// If suggestions are not enabled, remove the suggestion spans from the text
if (!isSuggestionsEnabled()) {
text = removeSuggestionSpans(text);
}

如果没有开启suggestions,传递进去的text将被移除自身已有的span,看下 isSuggestionsEnabled()方法:

public boolean isSuggestionsEnabled() {
if (mEditor == null) return false;
if ((mEditor.mInputType & InputType.TYPE_MASK_CLASS) != InputType.TYPE_CLASS_TEXT) {
return false;
}
if ((mEditor.mInputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) > 0) return false; final int variation = mEditor.mInputType & EditorInfo.TYPE_MASK_VARIATION;
return (variation == EditorInfo.TYPE_TEXT_VARIATION_NORMAL
|| variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT
|| variation == EditorInfo.TYPE_TEXT_VARIATION_LONG_MESSAGE
|| variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE
|| variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
}

可以看到该方法的返回值都与mEditor有关,再看下mEditor:

/**
* {@link EditText} specific data, created on demand when one of the Editor fields is used.
* See {@link #createEditorIfNeeded()}.
*/
private Editor mEditor;

mEditor是特定数据,在使用编辑器字段之一时按需创建,再看下注释中mEditor的创建方法:

private void createEditorIfNeeded() {
if (mEditor == null) {
mEditor = new Editor(this);
}
}

啊哦,创建mEditor的唯一方法是私有方法,也就是说没法通过改变isSuggestionsEnabled()返回值来取消移除已有的span。

回过头看SpannableString源码,发现SpannableString没有实现任何序列化接口,而我是把SpannableString作为CharSequence通过Intent来传递的,它将作为普通的CharSequence实现类对象传递到TextView.setText()中,所以,解决方法有两种:

1)在setText()需要传递SpannableString的地方,重新创建一个SpannableString;

2)重写SpannableString,继承自SpannableString并实现序列化接口,将自定义的SpannableString作为对象通过Intent来传递;

总结:在Android组件间进行数据传递时,如果是传递对象,通常都会考虑到数据是否实现了序列化接口,但在这种情况下,试图将SpannableString作为CharSequence的实现类在组件之间进行传递,在接收端获取到的CharSequence将不再是传递之前的实现类对象,同时也容易忽略掉我们真正需要的是传递一个对象,而通过Intent传递对象是需要实现序列化接口的。

解决SpannableString在Android组件间传递时显示失效的问题的更多相关文章

  1. Android消息传递之组件间传递消息

    前言: 上篇学习总结了Android通过Handler消息机制实现了工作线程与UI线程之间的通信,今天来学习一下如何实现组件之间的通信.本文依然是为学习EventBus做铺垫,有对比才能进步,今天主要 ...

  2. 【Android开发日记】之入门篇(十二)——Android组件间的数据传输

    组件我们有了,那么我们缺少一个组件之间传递信息的渠道.利用Intent做载体,这是一个王道的做法.还有呢,可以利用文件系统来做数据共享.也可以使用Application设置全局数据,利用组件来进行控制 ...

  3. Android 组件间通信--事件驱动

    在android中,组件间通信常用的方式: 1.使用广播机制:在主页面中监听特定的广播事件,进行业务逻辑的操作,其他页面只需要根据需求发送广播即可 例如:常用app结构中,左边通常为菜单栏,点击菜单栏 ...

  4. Android组件间交互

    四大组件相信大家都不陌生了吧,今天咱们就组件间通信做个说明: 首先: 主要今天的目的是为了说明Android 提供的一个ResultReceiver类,这个类相信大家都不陌生吧>?但是你们层深入 ...

  5. android组件间共享数据的常用方法

    使用Intent在激活组件的时候携带数据,以进行数据的传递 使用广播进行组件间数据的伟递 使用外部存储(sharedPreference,文件,数据库,网络)进行组件间数据共享 使用Static静态成 ...

  6. PHP跨页面传递时session失效

    一直都是使用wamp作为本地的PHP集成开发环境 今天遇到一个很奇怪的问题,就是在跨页面传递时session竟然失效了,而之前从来没有出现过这种问题 因为使用的是开源的php框架为了测试方便就新建了两 ...

  7. Android组件间的数据传输

    组件我们有了,那么我们缺少一个组件之间传递信息的渠道.利用Intent做载体,这是一个王道的做法.还有呢,可以利用文件系统来做数据共享.也可以使用Application设置全局数据,利用组件来进行控制 ...

  8. Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)

    在上一篇中介绍了Andorid中的进程间的通信方式AIDL,本篇文章将介绍传递复杂数据的AIDL Service 下面通过一个示例说明: 本例子中用到了两个自定义类型:Person与Pet, 其中Pe ...

  9. 解决eclipse中android添加重载函数时参数为arg0,arg1的问题

    遇到同样的问题,发现有人已经解决了,大体意思就是为android sdk 添加 src,以下是文章链接 http://blog.csdn.net/u014084081/article/details/ ...

随机推荐

  1. IE条件注释,为IE单独写js

    <!--[if IE ]> <body class="ie"> <![endif]--> <!--[if !IE]>--> & ...

  2. python 要掌握面向对象,你得会做这些题吗?

    1,面向对象三大特性,各有什么用处,说说你的理解. 继承:解决代码重用问题 多态:多态性,可以在不考虑对象类型的情况下而直接使用对象 封装:明确的区分内外,控制外部对隐藏属性的操作行为,隔离复杂度 2 ...

  3. jquery和ajax的关系详细介绍【转】

    jquery和ajax的关系详细介绍 http://www.jb51.net/article/43965.htm

  4. python_黑洞数

    >>> def main(n): start = 10**(n-1)+2 end = start*10-20 for i in range(start,end): i = str(i ...

  5. 深入理解.net - 4.你必须知道的String

    为什么要单独写string,主要是它太常用了,同时又太特殊了,特殊到CLR对它的处理都和其它对象不一样.简直可以称为VIP用户啊.本文并不是一篇介绍如何使用string的文章,而是旨在阐述string ...

  6. 使用EHCache需要注意的几个问题(转)

    最近做一个小项目,需要对一批数据进行缓存,且要求持久化到磁盘.使用ehcache非常简单和直观,一般来说只需要配置ehcache.xml文件,接着直接使用@Cacheable, @Cacheput, ...

  7. Visual Studio的常用快捷键

    项目相关的快捷键 Ctrl + Shift + B   生成项目 Ctrl + Alt + L   显示Solution Explorer(解决方案资源管理器) Shift + Alt+ C   添加 ...

  8. Day1 《机器学习》第一章学习笔记

    <机器学习>这本书算是很好的一本了解机器学习知识的一本入门书籍吧,是南京大学周志华老师所著的鸿篇大作,很早就听闻周老师大名了,算是国内机器学习领域少数的大牛了吧,刚好研究生做这个方向相关的 ...

  9. centos6.9 升级内核版本

    想在centos6.9上安装docket,不过因为内核版本是2.6的故而想升级到最新的内核版本 晚上有编译升级的比较麻烦,不过有助于理解内核升级,我使用的直接升级到最新版方法 1. 导入public ...

  10. win7 telnet命令无法开启的解决方案(不是内部命令或外部命令)

    如果你想在win 7上直接使用 telnet命令,却不能开启那怎么办呢?记得在Wingdows XP上telnet都是已经安装好的,直接就可用,但是Win7是没有这个功能的,都需要后来自己安装的,下面 ...