Android設定TextView中部分字型顏色和點選事件
最近接到一個新需求,在一個TextView中實現部分字型的顏色不同於其它字型,且點選該部分文字時實現跳轉的功能。一開始想著用多個TextView連起來實現功能,優化程式碼時再想想,這也太弱智了點兒吧!
果斷Google搜尋一下別的Coder是怎麼實現的,其實Android在TextView中已經為開發者提供了這樣的API:
/** * This is the class for text whose content and markup can both be changed. * 這是一個內容和標記都可以更改的文字類 */ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable, Appendable, GraphicsOperations {......}
-
先展示一下效果吧!
-
接著來簡單看下程式碼實現:
佈局檔案很簡單的就添加了一個TextView:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginStart="20dp" android:layout_marginEnd="20dp" android:orientation="vertical"> <TextView android:id="@+id/spannable_test_string_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginTop="20dp" tools:text="測試" /> </LinearLayout>
Activity中程式碼實現如下:
public class SpannableActivity extends AppCompatActivity { private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_spannable); mTextView = (TextView) findViewById(R.id.spannable_test_string_tv); String str = new String("獲取更多幫助,請撥打客服電話400-888-8888"); // SpannableString 的用法、和 SpannableStringBuilder 很相似、下面主要以 SpannableStringBuilder 來介紹 // SpannableString spannableString = new SpannableString(str); // ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#3072F6")); // spannableString.setSpan(colorSpan, 14, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // mTextView.setText(spannableString); // SpannableStringBuilder 用法 SpannableStringBuilder spannableBuilder = new SpannableStringBuilder(str); // 設定字型大小 AbsoluteSizeSpan sizeSpan = new AbsoluteSizeSpan(40); // 相對於預設字型大小的倍數,這裡是1.3倍 // RelativeSizeSpan sizeSpan1 = new RelativeSizeSpan((float) 1.3); spannableBuilder.setSpan(sizeSpan, 0, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 單獨設定字型顏色 ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#3072F6")); spannableBuilder.setSpan(colorSpan, 14, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 單獨設定點選事件 ClickableSpan clickableSpanOne = new ClickableSpan() { @Override public void onClick(View view) { Toast.makeText(SpannableActivity.this, "撥打電話", Toast.LENGTH_SHORT).show(); } }; spannableBuilder.setSpan(clickableSpanOne, 14, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 設定刪除線 StrikethroughSpan strikeSpan = new StrikethroughSpan(); // 設定下劃線 UnderlineSpan underlineSpan = new UnderlineSpan(); // 在設定點選事件、同時設定字型顏色 ClickableSpan clickableSpanTwo = new ClickableSpan() { @Override public void onClick(View view) { Toast.makeText(SpannableActivity.this, "撥打電話", Toast.LENGTH_SHORT).show(); } @Override public void updateDrawState(TextPaint paint) { paint.setColor(Color.parseColor("#3072F6")); // 設定下劃線 true顯示、false不顯示 paint.setUnderlineText(false); // paint.setStrikeThruText(true); } }; spannableBuilder.setSpan(clickableSpanTwo, 14, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 不設定點選不生效 mTextView.setMovementMethod(LinkMovementMethod.getInstance()); mTextView.setText(spannableBuilder); // 去掉點選後文字的背景色 // mTextView.setHighlightColor(Color.parseColor("#00000000")); } }
- 介紹一下 SpannableStringBuilder 相關知識
SpannableStringBuilder 的 setSpan 方法,該方法有四個引數:
Object what:根據傳入的具體 Object 物件來標記 Span 範圍的Text
int start:Span 的開始位置index
int end:Span的結束位置index,並不包括這個位置
int flags:標記位
3.1 介紹一下 Object 引數
setSpan 方法的 Object 引數可以傳入各種Span,不同的Span對應不同的樣式,簡單介紹幾個:
1、AbsoluteSizeSpan(int size) :設定字型大小,引數是絕對數值;
AbsoluteSizeSpan sizeSpan = new AbsoluteSizeSpan(40);
2、RelativeSizeSpan(float proportion) :設定字型大小,引數是相對於預設字型大小的倍數,proportion>1就是放大(zoom in),proportion<1就是縮小(zoom out);
// 相對於預設字型大小的倍數,這裡是1.3倍
RelativeSizeSpan sizeSpan1 = new RelativeSizeSpan((float) 1.3);
3、ScaleXSpan(float proportion):縮放字型,引數和RelativeSizeSpan相同;
4、BackgroundColorSpan(int color):背景色,引數是顏色數值,可以直接使用android.graphics.Color裡面定義的常量,或是用 Color.rgb(int, int, int) 和 Color.parseColor("#3072F6") 等;
5、ForegroundColorSpan(int color):前景色,也就是字型的著色,引數與背景色相同;
6、TypefaceSpan(String family):字型,引數是字型的名字比如“sans","sans-serif"等;
7、StyleSpan(Typeface style):字型風格,比如粗體,斜體,引數是android.graphics.Typeface裡面定義的常量,如Typeface.BOLD,Typeface.ITALIC等等;
8、StrikethroughSpan:設定刪除線,會有一條線從中間穿過所有的字,就像被劃掉一樣;
9、UnderlineSpan:設定下劃線;
10、ClickableSpan:設定點選事件監聽,需要重寫 onClick 方法
// 單獨設定點選事件
ClickableSpan clickableSpanOne = new ClickableSpan() {
@Override
public void onClick(View view) {
Toast.makeText(SpannableActivity.this, "撥打電話", Toast.LENGTH_SHORT).show();
}
};
如果需要同時改變字型的顏色,以及做一些其它改變(如上面的各個分項),還可以重寫 updateDrawState 方法;
// 在設定點選事件、同時設定字型顏色
ClickableSpan clickableSpanTwo = new ClickableSpan() {
@Override
public void onClick(View view) {
Toast.makeText(SpannableActivity.this, "撥打電話", Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint paint) {
paint.setColor(Color.parseColor("#3072F6"));
// 設定下劃線 true顯示、false不顯示
paint.setUnderlineText(false);
// paint.setStrikeThruText(true);
}
};
先介紹這麼多吧!讀者可以自己試試效果,我試了其中的一部分而已;
3.2 介紹一下 flags 標記位
呼叫 setSpan 時需要指定的 flag 位,用來標識在 Span 範圍內的文字前後輸入新的字元時是否把它們也應用這個效果。該標記位有四個可選值,如下:
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE:前後都不包括,即在文字前後插入新的文字都不會應用該樣式
Spanned.SPAN_INCLUSIVE_EXCLUSIVE:前面包括,後面不包括,即在文字前插入新的文字會應用該樣式,而在文字後插入新文字不會應用該樣式
Spanned.SPAN_EXCLUSIVE_INCLUSIVE:前面不包括,後面包括
Spanned.SPAN_INCLUSIVE_INCLUSIVE:前後都包括
具體效果可以在程式碼中手動試試,這裡就不一一試啦!