標籤:
項目中設計出的效果,我立即想到要使用SpannableString做出此效果。但我對SpannableString只是有基本的瞭解,下面我就記錄下自己收集以及嘗試的效果。
ApiDemo 源碼至 com.example.android.apis.text.Link 類,可以看到text的不同效果。
一、自動應用效果,使用 android:autolink ="email|phone|web|map|all"屬性
<!-- text1 automatically linkifies things like URLs and phone numbers. --> <TextView android:id="@+id/text1" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="8dp" android:autoLink="all" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/link_text_auto" />
點擊數字,就會進入撥號頁面;點擊網址,就會在瀏覽器開啟對應的網址;點擊郵箱就進入發郵箱的功能;
二、在文本中使用 <a> 標籤
<string name="link_text_manual"><b>text2: Explicit links using <a> markup.</b> This has markup for a <a href="http://www.google.com">link</a> specified via an <a> tag. Use a \"tel:\" URL to <a href="tel:4155551212">dial a phone number</a>. </string>
<!-- text2 uses a string resource containing explicit <a> tags to specify links. --> <TextView android:id="@+id/text2" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="8dp" android:paddingBottom="8dp" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/link_text_manual" />
// text2 has links specified by putting <a> tags in the string // resource. By default these links will appear but not // respond to user input. To make them active, you need to // call setMovementMethod() on the TextView object. TextView t2 = (TextView) findViewById(R.id.text2); t2.setMovementMethod(LinkMovementMethod.getInstance());
三、第三種和第二種其實是一樣的,只不過將文本改在 JAVA 代碼中
// text3 shows creating text with links from HTML in the Java // code, rather than from a string resource. Note that for a // fixed string, using a (localizable) resource as shown above // is usually a better way to go; this example is intended to // illustrate how you might display text that came from a // dynamic source (eg, the network). TextView t3 = (TextView) findViewById(R.id.text3); t3.setText( Html.fromHtml( "<b>text3: Constructed from HTML programmatically.</b> Text with a " + "<a href=\"http://www.google.com\">link</a> " + "created in the Java source code using HTML.")); t3.setMovementMethod(LinkMovementMethod.getInstance());
四、通過建立 SpanableString 字串,並在之上創 建一個或多個 Span 來實現豐富的效果。
SpannableString的定義:
This is the class for text whose content is immutable but to which markup objects can be attached and detached. For mutable text, see SpannableStringBuilder.<span style="color:#FF0000;"><strong>翻譯:SpannableString</strong>是常值內容不可改變,但標記對象可以綁定和解除綁定的類。</span>
官方文檔中前半句話好理解,後半句就不怎麼好理解了。問題就來了:
- 什麼是標記對象呢(markup objects)?
- 綁定和解除綁定(attached and detached)又是什麼意思呢?
標記對象
標記語言(也稱置標語言、標記語言、標誌語言、標識語言)是一種將文本(Text)以及文本相關的其他資訊結合起來,展現出關於文檔結構和資料處理細節的電腦文字編碼。至於標記對象則是和標記語言一個意思,就是能設定文本的各種樣式的方法。
例子如下:
link_color的寫法如下:
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:color="#ffff00"/> <!-- pressed --> <item android:state_focused="true" android:color="#ffff00"/> <!-- focused --> <item android:color="#ff0000"/> <!-- default --></selector>
java代碼如下:
textView =(TextView) findViewById(R.id.textview);//使用setSpan(Object what, int start, int end, int flags)方法設定標記對象,其中長度是end-start。 //使用removeSpan()解除綁定標記對象 //public void setSpan (Object what, int start, int end, int flags) //綁定特定的標記對象(Object what)到起始為start,終止為end的text對象上(若已綁定標記對象則先移除) //設定字型TypefaceSpan() //設定字型大小(絕對值)AbsoluteSizeSpan() //設定字型大小(相對值)RelativeSizeSpan() //設定字型大小(相對值,預設字型寬度的倍數)ScaleXSpan() //設定字型的前景色彩ForegroundColorSpan() //設定字型的背景色BackgroundColorSpan() //設定字型的樣式StyleSpan() //設定底線UnderlineSpan() //刪除線StrikethroughSpan() //上標SuperscriptSpan() //下標SubscriptSpan() //連結URLSpan()-->需要添加setMovementMethod方法附加響應 //字型外觀設定(依次包括字型名稱,字型大小,字型樣式,字型顏色,連結顏色)TextAppearanceSpan() //項目符號BulletSpan() //圖片ImageSpan()//android.text.style.XXX 擷取各種span的Parcel屬性 //建立一個 SpannableString對象 msp = new SpannableString("字型測試字型大小一半兩倍前景色彩背景色正常粗體斜體粗斜體底線刪除線x1x2電話郵件網站簡訊多媒體訊息地圖X軸綜合/bot"); //設定字型(default,default-bold,monospace,serif,sans-serif) msp.setSpan(new TypefaceSpan("monospace"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); msp.setSpan(new TypefaceSpan("serif"), 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定字型大小(絕對值,單位:像素) msp.setSpan(new AbsoluteSizeSpan(20), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //第二個參數boolean dip,如果為true,表示前面的字型大小單位為dip,否則為像素,同上。 msp.setSpan(new AbsoluteSizeSpan(20,true), 6, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定字型大小(相對值,單位:像素) 參數表示為預設字型大小的多少倍 msp.setSpan(new RelativeSizeSpan(0.5f), 8, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //0.5f表示預設字型大小的一半 msp.setSpan(new RelativeSizeSpan(2.0f), 10, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //2.0f表示預設字型大小的兩倍 //設定字型前景色彩 msp.setSpan(new ForegroundColorSpan(Color.MAGENTA), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定前景色彩為洋紅色 //設定字型背景色 msp.setSpan(new BackgroundColorSpan(Color.GREEN), 15, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定背景色為青色 //設定字型樣式正常,粗體,斜體,粗斜體 msp.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 18, 20, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //正常 msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 20, 22, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //粗體 msp.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 22, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //斜體 msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 24, 27, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //粗斜體 //設定底線 msp.setSpan(new UnderlineSpan(), 27, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定刪除線 msp.setSpan(new StrikethroughSpan(), 30, 33, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定上下標 msp.setSpan(new SubscriptSpan(), 34, 35, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //下標 msp.setSpan(new SuperscriptSpan(), 36, 37, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //上標 //超級連結(需要添加setMovementMethod方法附加響應) msp.setSpan(new URLSpan("tel:4155551212"), 37, 39, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //電話 msp.setSpan(new URLSpan("mailto:[email protected]"), 39, 41, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //郵件 msp.setSpan(new URLSpan("http://www.baidu.com"), 41, 43, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //網路 msp.setSpan(new URLSpan("sms:4155551212"), 43, 45, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //簡訊 使用sms:或者smsto: msp.setSpan(new URLSpan("mms:4155551212"), 45, 47, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //多媒體訊息 使用mms:或者mmsto: msp.setSpan(new URLSpan("geo:38.899533,-77.036476"), 47, 49, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //地圖 //設定字型大小(相對值,單位:像素) 參數表示為預設字型寬度的多少倍 //2.0f表示預設字型寬度的兩倍,即X軸方向放大為預設字型的兩倍,而高度不變 msp.setSpan(new ScaleXSpan(2.0f), 49, 51, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定字型(依次包括字型名稱,字型大小,字型樣式,字型顏色,連結顏色) ColorStateList csllink = null; ColorStateList csl = null; XmlResourceParser xppcolor=getResources().getXml(R.drawable.link_color); try { csl= ColorStateList.createFromXml(getResources(),xppcolor); csllink= ColorStateList.createFromXml(getResources(),xppcolor); }catch(XmlPullParserException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } msp.setSpan(new TextAppearanceSpan("monospace",android.graphics.Typeface.BOLD_ITALIC, 30, csl, csllink), 51, 53, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //設定項目符號 msp.setSpan(new BulletSpan(android.text.style.BulletSpan.CONTENTS_FILE_DESCRIPTOR,Color.RED), 0 ,msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //第一個參數表示項目符號佔用的寬度,第二個參數為項目符號的顏色 //設定圖片 Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); msp.setSpan(new ImageSpan(drawable), 53, 57, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(msp); textView.setMovementMethod(LinkMovementMethod.getInstance());
效果如下:
最後有幾個點要說明:
1)許多span都有XXXSpan(Parcel src)的構造方法,在android.text.style.XXX.XXX中擷取各種span的Parcel屬性
2) setSpan(Object what, int start, int end, int flags)中的flag有幾個值:
SPAN_INCLUSIVE_EXCLUSIVE(前後都包括): [0,5]
SPAN_INCLUSIVE_INCLUSIVE(前麵包括,後面不包括):[0,5)
SPAN_EXCLUSIVE_EXCLUSIVE(前後都不包括):(0,5)
SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,後麵包括):(0,5]
3)使用TextAppearanceSpan時,color必須是selector類型。
/** * Makes text be drawn with the specified typeface, size, style, * and colors. */ public TextAppearanceSpan(String family, int style, int size, ColorStateList color, ColorStateList linkColor) { mTypeface = family; mStyle = style; mTextSize = size; mTextColor = color; mTextColorLink = linkColor; }
android中TextView的Spnnable使用