Android之TextView的Span樣式源碼剖析,androidtextview

來源:互聯網
上載者:User

Android之TextView的Span樣式源碼剖析,androidtextview
Android中的TextView是個顯示文字的的UI類,在現實中的需求中,文字有各式各樣的樣式,TextView本身沒有屬性去設定實現,我們可以通過Android提供的 SpannableString類封裝。Android提供了很多的Span的類去實現樣式,這個樣式都是繼承自CharacterStyle類。     在上一篇部落格中詳細的介紹的怎麼使用各種Span類,這篇部落客要是通過看源碼,來分析Span的工作原理,內部的類結構,繼承結構,從而達到我們自己可以自訂一個Span來使用。
        要想剖析Span的原理,我們就需要看懂TextView的大概的繪製流程,一個TextView中的類似是很複雜的,一點一點看源碼,找順序。
     首先,在CharcaterStyle類中具有      public abstract void updateDrawState(TextPaint tp);   方法,TextPaint是畫筆,我個人認為TextPaint沒啥作用,直接當作Paint去看就行了。既然updateDrawState需要Paint,那麼就需要在TextView中的onDraw去調用這個方法,在onDraw方法中傳遞給畫Text的畫筆,這個方法才能起作用,那我們順著看TextView中的onDraw方法,代碼太多,我只貼關鍵代碼。 在TextView的onDraw方法中只有下面的方法調用到了畫筆。    Path highlight = getUpdatedHighlightPath();        if (mEditor != null) {            mEditor.onDraw(canvas, layout, highlight, mHighlightPaint,                    cursorOffsetVertical);        } else {            layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);        }        if (mMarquee != null && mMarquee.shouldDrawGhost()) {            canvas.translate((int) mMarquee.getGhostOffset(), 0.0f);            layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);        }  
這裡可以發現有兩個類:Editor和Layout,TextView的onDraw就是在這兩個類中去繪製的,繼續分別看這兩個類的作用。1.Editor:還沒找到出處代碼。放下擱置以後再說2.Layout:可以看到Layout有三個子類,BoringLayout、DynamicLayout、StaticLayout,這三個類是一些功能的封裝,主要的實現還都是在Layout中,我們看一下Layout中的代碼:  public void draw(Canvas canvas, Path highlight, Paint highlightPaint,            int cursorOffsetVertical) {        final long lineRange = getLineRangeForDraw(canvas);        int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);        int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);        if (lastLine < 0) return;        drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical,                firstLine, lastLine);        drawText(canvas, firstLine, lastLine);    }drawBackground 繪製背景
drawText  繪製文字
找到了關鍵的代碼了。接著看drawText中的源碼: if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTabOrEmoji) {                // XXX: assumes there's nothing additional to be done                canvas.drawText(buf, start, end, x, lbaseline, paint);            } else {                tl.set(paint, buf, start, end, dir, directions, hasTabOrEmoji, tabStops);                tl.draw(canvas, x, ltop, lbaseline, lbottom);            } 
可以看到的是有個判斷條件的,直接就可以繪製文字的,但是我們還沒找到有關Span的代碼啊,難道沒有,不要著急,還有tl.draw。看源碼:

    ReplacementSpan replacement = null;
             for (int j = 0; j < mMetricAffectingSpanSpanSet.numberOfSpans; j++) {                // Both intervals [spanStarts..spanEnds] and [mStart + i..mStart + mlimit] are NOT                // empty by construction. This special case in getSpans() explains the >= & <= tests                if ((mMetricAffectingSpanSpanSet.spanStarts[j] >= mStart + mlimit) ||                        (mMetricAffectingSpanSpanSet.spanEnds[j] <= mStart + i)) continue;                MetricAffectingSpan span = mMetricAffectingSpanSpanSet.spans[j];                if (span instanceof ReplacementSpan) {                    replacement = (ReplacementSpan)span;                } else {                    // We might have a replacement that uses the draw                    // state, otherwise measure state would suffice.                    span.updateDrawState(wp);                }            }        Ok ,終於找到了Span的出處了。
    

我們可以總結一下TextView繪製流程了。
TextView的onDraw----》Layout的draw----》TextLine的Draw----》CharacterStyle的updateDrawState(如果設定的有Span樣式)
繪製的主要的代碼還是在Layout的Draw中和TextLine的Draw中。
從類的繼承結構圖中我簡單的CharacterStyle分為兩類:一個是直接繼承CharacterStyle的,另一個ReplacementSpan。第一種:直接繼承CharacterStyle的樣式是主要跟Paint相關的,只需要更改畫筆中的設定即可達到更改目的的。第二種:繼承ReplacementSpan的,在ReplacementSpan中有Draw的方法,    public  abstract  void draw(Canvas canvas, CharSequence text,                      int start,  int end,  float x,                      int top,  int y,  int bottom, Paint paint);我們可以直接通過操作canvas去自己繪製,你想要怎麼繪製,不就完全的聽你的嗎???

 分類之後,我們就可以瞭解到以後如果需要自訂Span的時候,就可以去選擇性的去繼承類了。


我的部落格園地址:http://www.cnblogs.com/flyme2012/



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.