zoukankan      html  css  js  c++  java
  • 解决SpannableString在Android组件间传递时显示失效的问题

    问题:在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传递对象是需要实现序列化接口的。

  • 相关阅读:
    linux安装skype
    (转)程序员最应该读的图书
    Smarty 学习笔记六 缓存
    Smarty 学习笔记二 常用内置变量
    Smarty 学习笔记七 debug
    文本文件与二进制文件区别
    zz 通用线程:Awk 实例,第 2部分
    MIT墙上的格言
    AWK学习笔记
    zz SED单行脚本快速参考 以及 AWK版本
  • 原文地址:https://www.cnblogs.com/sqchen/p/10660941.html
Copyright © 2011-2022 走看看