由 TextView.BufferType.EDITABLE 引發的血案

來源:互聯網
上載者:User

提示: 注意到 TextView 控制項設定文本時的參數有TextView.BufferType.EDITABLE 和 TextView.BufferType.SPANNABLE
但是不知道具體啥差別, 於是決定窺探 Google 代碼,看個究竟。

一、在 TextView 類中找到 setText 方法關於 BufferType 的主要代碼:

Java代碼 
// Editable 是一個介面,作者巧妙的在介面中實現了Factory 方法。  
private Editable.Factory mEditableFactory = Editable.Factory.getInstance();  
    private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance(); 

// Editable 是一個介面,作者巧妙的在介面中實現了Factory 方法。
private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
    private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();

Java代碼 
if (type == BufferType.EDITABLE || mInput != null ||  
            needEditableForNotification) {  
            Editable t = mEditableFactory.newEditable(text);  
            text = t;  
            setFilters(t, mFilters);  
            InputMethodManager imm = InputMethodManager.peekInstance();  
            if (imm != null) imm.restartInput(this);  
        } else if (type == BufferType.SPANNABLE || mMovement != null) {  
            text = mSpannableFactory.newSpannable(text);  
        } else if (!(text instanceof CharWrapper)) {  
            text = TextUtils.stringOrSpannedString(text);  
        } 

if (type == BufferType.EDITABLE || mInput != null ||
            needEditableForNotification) {
            Editable t = mEditableFactory.newEditable(text);
            text = t;
            setFilters(t, mFilters);
            InputMethodManager imm = InputMethodManager.peekInstance();
            if (imm != null) imm.restartInput(this);
        } else if (type == BufferType.SPANNABLE || mMovement != null) {
            text = mSpannableFactory.newSpannable(text);
        } else if (!(text instanceof CharWrapper)) {
            text = TextUtils.stringOrSpannedString(text);
        }

可以看出根據不同 BufferType ,用類工廠的模式建立控制項,那麼為什麼不直接 new 一個控制項呢?首先想到的是減少與實作類別的耦合,提高可維護性。

二、帶著上面的問題,在 TextView 類中找到下面的代碼,提供了更換 Factory 的可能,使得開發人員方便做不同的控制項實現。
    Java代碼 
public final void setEditableFactory(Editable.Factory factory) {  
        mEditableFactory = factory;  
        setText(mText);  
    }  
    public final void setSpannableFactory(Spannable.Factory factory) {  
        mSpannableFactory = factory;  
        setText(mText);  
    } 

public final void setEditableFactory(Editable.Factory factory) {
        mEditableFactory = factory;
        setText(mText);
    }
    public final void setSpannableFactory(Spannable.Factory factory) {
        mSpannableFactory = factory;
        setText(mText);
    }

三、那麼如何自訂控制項的實現呢,需要新寫一個介面繼承 Editable, 並且覆蓋掉 Editable 中下面的方法:

Java代碼 
public static class Factory {  
        private static Editable.Factory sInstance = new Editable.Factory();  
public static Editable.Factory getInstance() {  
            return sInstance;  
        }  
public Editable newEditable(CharSequence source) {  
            return new SpannableStringBuilder(source);  
        }  
    } 

public static class Factory {
        private static Editable.Factory sInstance = new Editable.Factory();
public static Editable.Factory getInstance() {
            return sInstance;
        }
public Editable newEditable(CharSequence source) {
            return new SpannableStringBuilder(source);
        }
    }

四、TextView.BufferType.EDITABLE 和 TextView.BufferType.SPANNABLE
有什麼區別呢?我們透過UML瞧一下, Editable 類似於StringBuilder可追加字元,
也就是說getText後可調用append方法設定常值內容。Spannable 則可在給定的字元地區使用樣式。有意思的是 Editable 繼承了 Spannable 所以具備較多的功能。


摘自 藍色理想——帥子


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.