TextView使用技術點(一)

TextView作爲開發時候顯示最常用的控件之一,我們使用的頻率是非常高的,但是我們平時的使用都是怎麼使用的那些相關的屬性和方法呢?

內容:setText()

字體:TextSize、TextColor

寬度和高度:width、weigth

邊距:margin、padding

背景:background

......

常用的基本也就這些吧。

雖然基本都用,但是我們真的瞭解這些屬性和相關的方法,今天我們就從源碼角度看看Text相關的設置。

當我們實現如下相關的需求時候,我們是怎麼做的呢 ?

1)設置Text的時候數據爲String,char[],字符串資源。

2)在原有Text顯示基礎上追加特定的內容。

3)設置字體大小的時候指定單位,SP、DP、PT等。

4)設置內容的選中效果。

5)顯示內容中的中間某個字體顏色、大小變化。

...

這些效果該怎麼實現呢?

一、首先看第一個問題設置不同的數據爲顯示內容

截圖可以看出,設置文本內容的時候共有五個重載方法均可設置內容,第一個方法也就是我們最常用的方法設置內容,

第二個方法帶的參數爲緩存顯示的類型  總共三種類型,

源碼部分如下:

public enum BufferType {
    NORMAL, SPANNABLE, EDITABLE,
}

調用第一個方法的時候BufferType默認爲normal,如下:

public final void setText(CharSequence text) {
    setText(text, mBufferType);
}	
其實就是間接調用了第二個方法。

第三個方法就是將字符數組設置爲內容的方法,包含開始、結束下標,可以顯示指定的內容。

最後兩個方法類似前兩個,只是多了一步取資源字符串的操作。

其實多個方法否是在不同的轉換之後調用了設置內容的終極方法,:

private void setText(CharSequence text, BufferType type,
                     boolean notifyBefore, int oldlen)

第一個問題解決了,通過調用不同的重載方法就可以實現相關的操作,很簡單,就不上圖了。


二、接着看第二個問題在Text原有顯示基礎上追加顯示的內容:

從上述的bufferType可以看出內容的類型有三種,這裏就是用到了

EDITABLE

TextView存在方法append();

可以看出有兩個重載方法,一個是全部追加,一個是追加指定的內容,其實猜也能猜到了第一個方法就是調用的第二個方法,參數就是0和字符串的長度,看源碼,果然如此:

public final void append(CharSequence text) {
    append(text, 0, text.length());
}

再看追加的具體實現:

public void append(CharSequence text, int start, int end) {
    if (!(mText instanceof Editable)) {
        setText(mText, BufferType.EDITABLE);//如果不是EDITABLE類型設置成此類型
    }

    ((Editable) mText).append(text, start, end);

    if (mAutoLinkMask != 0) {
        boolean linksWereAdded = Linkify.addLinks((Spannable) mText, mAutoLinkMask);
        // Do not change the movement method for text that support text selection as it
        // would prevent an arbitrary cursor displacement.
        if (linksWereAdded && mLinksClickable && !textCanBeSelected()) {
            setMovementMethod(LinkMovementMethod.getInstance());
        }
    }
}
其實就是講內容設置成EDITABLE類型了,

其實是給Editable在追加內容,Editable是繼承於CharSequence的一個接口,對其進行了擴展,可進行追加等操作。

源碼先看到這裏,基本明白了是怎麼實現的,暫不深究。

看看我們的實現代碼,其實很簡單:

mTextView1.setText("默認單位爲SP");
mTextView2.setText("單位爲DP/DIP");
mTextView1.append("追加信息",0,2);
mTextView2.append("追加信息");

顯示如下:


可以看出已經進行了指定的追加效果。


三、接着看第三個問題設置字體大小的時候指定單位:

先看看設置字體大小的方法,如下:

兩個重載方法,和上述一樣的調用模式,就不用細看了,需要說明的是指定的參數默認爲SP,即可以隨着系統的設置調整大小的字體單位。

重點看我們都可以設置那些單位,源碼如下:

/**
 * Set the default text size to a given unit and value.  See {@link
 * TypedValue} for the possible dimension units.
 *
 * @param unit The desired dimension unit.
 * @param size The desired size in the given units.
 *
 * @attr ref android.R.styleable#TextView_textSize
 */
public void setTextSize(int unit, float size) {
    Context c = getContext();
    Resources r;

    if (c == null)
        r = Resources.getSystem();
    else
        r = c.getResources();

    setRawTextSize(TypedValue.applyDimension(
            unit, size, r.getDisplayMetrics()));
}

這裏直接看不出什麼,但是注意TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),不論設置什麼單位都會進行這一步的轉換,再看看轉換的方法內部:

public static float applyDimension(int unit, float value,
                                   DisplayMetrics metrics)
{
    switch (unit) {
    case COMPLEX_UNIT_PX://像素
        return value;
    case COMPLEX_UNIT_DIP://DP,不會隨着系統設置而變化
        return value * metrics.density;
    case COMPLEX_UNIT_SP://SP,會隨着系統設置而變化
        return value * metrics.scaledDensity;
    case COMPLEX_UNIT_PT://點
        return value * metrics.xdpi * (1.0f/72);
    case COMPLEX_UNIT_IN://英寸
        return value * metrics.xdpi;
    case COMPLEX_UNIT_MM://毫米
        return value * metrics.xdpi * (1.0f/25.4f);
    }
    return 0;
}

一目瞭然,我們可設置的單位有6種,除此之外會直接返回尺寸爲0。

再看看6中單位,常用的位DP,SP,由於Android的碎片化很嚴重,其他的單位也很少用到。

到這裏也就明白了該怎麼設置字體大小了。

看看具體設置的效果,如下:

mTextView1.setText("默認單位爲SP");
mTextView2.setText("單位爲DP/DIP");
mTextView3.setText("單位爲PX");
mTextView4.setText("單位爲PT");
mTextView5.setText("單位爲毫米");
mTextView6.setText("單位爲英寸");
//默認爲SP
mTextView1.setTextSize(14);
//單位爲DP/DIP
mTextView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP,14);
//單位爲PX
mTextView3.setTextSize(TypedValue.COMPLEX_UNIT_PX,14);
//單位爲PT
mTextView4.setTextSize(TypedValue.COMPLEX_UNIT_PT,14);
//單位爲毫米
mTextView5.setTextSize(TypedValue.COMPLEX_UNIT_MM,1);
//單位爲英寸
mTextView6.setTextSize(TypedValue.COMPLEX_UNIT_IN,1);
顯示如下:



四、接着看第四個問題設置內容的選中效果:

從上述的bufferType可以看出內容的類型有三種,這裏就是用到了

SPANNABLE
TextView並沒有直接的方法進行設置,此處暫時不做深究,實現代碼如下:

mTextView1.setText("默認單位爲SP", TextView.BufferType.SPANNABLE);
mTextView2.setText("單位爲DP/DIP", TextView.BufferType.SPANNABLE);

Spannable span=(Spannable)mTextView1.getText();
Spannable span1=(Spannable)mTextView2.getText();
span.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, 2,Spannable.SPAN_COMPOSING );
span1.setSpan(new StyleSpan(Typeface.BOLD), 1, 3,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
顯示如下:

可以看到默認加上了北京,下面的變成了粗體。

五、接着看第五個問題顯示內容中的中間某個字體顏色、大小變化:

這個問題還是通過setText方法來實現,藉助於Html類解析Html來實現,

代碼如下:

mTextView1.setText(Html.fromHtml("常用網站:<font color='red'>百度</font>、<font color='red'>好123</font>..."), TextView.BufferType.SPANNABLE);
顯示如下:

可以看到百度和好123均實現了紅色字體顯示。


以上的需求基本已經解決,不需要複雜的佈局,也不需要自定義View,TextView已經封裝好了。平時的開發中多研究源碼對我們的開發以及發展都是有着諸多的益處的。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章