一個TextView設定多種格式(類似於“評論”的樣式)

Wing_Li發表於2018-12-03

如果本文幫助到你,本人不勝榮幸,如果浪費了你的時間,本人深感抱歉。 希望用最簡單的大白話來幫助那些像我一樣的人。如果有什麼錯誤,請一定指出,以免誤導大家、也誤導我。 本文來自:www.jianshu.com/users/320f9… 感謝您的關注。

先看一張效果圖。 主要功能: 1.只有一個 TextView,但是顯示多個樣式,並且,前幾個字是可以點選。 2.修改 Toast 的彈出位置。

一個TextView設定多種格式(類似於“評論”的樣式)

這類效果,使用場景最多的,應該就是評論了吧。

主角介紹 - SpannableString

主要用的到就是 SpannableString 這個類,其實還有個SpannableStringBuilder,他們兩個作用跟String其實是很像的。不同之處就是他們倆可以給字串設定各種樣式。 SpannableString 和 SpannableStringBuilder 的區別也就是字面意思,多了一個Builder。類似於 String 和 StringBuilder。SpannableStringBuilder 是可以通過append()方法進行拼接。而SpannableString 通過構造器建立了之後就固定。

使用方法

String name = "小可愛:";
String msg = name + "小今天心情不錯,買張彩票。";

SpannableString ss = new SpannableString(msg);
ss.setSpan(new ForegroundColorSpan(Color.RED), name.length(), msg.length() - 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTxt.setText(ss);
複製程式碼

因為SpannableString 實現了CharSequence的介面,所以這一步之後,我們定義的 ss,就可以作為字串設定給TextView了。 顯示效果是:除了“小可愛:",後面的都是紅色字。 當然,我們是可以同時給一個字串設定多個樣式的。

很明顯我們可以看到通過setSpan()這個方法,我們就將指定的字元更換了樣式。 我們具體來看看 setSpan(); 到底有多麼的神通廣大。

/**
 * 設定字串的樣式
 * @param what 對應的樣式的類(往下看)
 * @param start 樣式開始的位置
 * @param end 樣式結束的位置
 * @param flags 包含的範圍(往下看)
 */
public void setSpan (Object what, int start, int end, int flags)
複製程式碼

起始結束位置就不用說了,就是符合行業的標準模式,含頭不含尾。 這裡需要介紹是第一個和第四個引數。 我們先來看第四個: int flags可設定為:

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:前後都不包括,即在指定範圍的前面和後面插入新字元都不會應用新樣式
Spannable.SPAN_EXCLUSIVE_INCLUSIVE:前面不包括,後面包括。即僅在範圍字元的後面插入新字元時會應用新樣式
Spannable.SPAN_INCLUSIVE_EXCLUSIVE:前面包括,後面不包括。
Spannable.SPAN_INCLUSIVE_INCLUSIVE:前後都包括。
複製程式碼

這裡系統給定了四個引數,含義已經註明。 需要說明的是,SpannableString 和 SpannableStringBuilder 的區別 在開頭提到了,不知道大家還記得嗎? 只有 SpannableStringBuilder 是可以通過append()方法,往後面拼接字串的,而這幾個標示都是當字串改變之後的效果,所以後面三個樣式的效果,可能只有使用了SpannableStringBuilder 新增文字的時候才看得到效果。 使用SpannableString ,新增了其他的flags也是沒有什麼用的,因為,只要一替換文字,整個物件全換了。 所以這個引數,我們看著用 就好。

Object what 這個引數,那可是相當強大。先看功能

    1、BackgroundColorSpan 背景色
    2、ClickableSpan 文字可點選,有點選事件
    3、ForegroundColorSpan 文字顏色(前景色)
    4、MaskFilterSpan 修飾效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
    5、MetricAffectingSpan 父類,一般不用
    6、RasterizerSpan 光柵效果
    7、StrikethroughSpan 刪除線(中劃線)
    8、SuggestionSpan 相當於佔位符
    9、UnderlineSpan 下劃線
    10、AbsoluteSizeSpan 絕對大小(文字字型)
    11、DynamicDrawableSpan 設定圖片,基於文字基線或底部對齊。
    12、ImageSpan 圖片
    13、RelativeSizeSpan 相對大小(文字字型)
    14、ReplacementSpan 父類,一般不用
    15、ScaleXSpan 基於x軸縮放
    16、StyleSpan 字型樣式:粗體、斜體等
    17、SubscriptSpan 下標(數學公式會用到)
    18、SuperscriptSpan 上標(數學公式會用到)
    19、TextAppearanceSpan 文字外貌(包括字型、大小、樣式和顏色)
    20、TypefaceSpan 文字字型
    21、URLSpan 文字超連結
複製程式碼

例如剛開始,我們用到的:設定文字的顏色

SpannableString ss = new SpannableString(msg); 
ss.setSpan(new ForegroundColorSpan(Color.RED), name.length(), msg.length() - 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
複製程式碼

上面的功能相當的多,不一一介紹,用的時候再看,因為用法都差不多。


效果圖程式碼實現

現在放上剛開始的時候,實現的那張圖程式碼。因為程式碼也相當簡單,所以直接貼上。

public class MainActivity extends AppCompatActivity {

    private TextView mTxt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mTxt = (TextView) findViewById(R.id.txt);
		initView();
    }

    private void initView() {
		String name = "小可愛:";//模擬名稱
		String msg = name + "今天心情不錯,買張彩票。";//模擬說說

		SpannableString ss = new SpannableString(msg);
		//名稱的點選事件
		ss.setSpan(clickableSpan, 0, name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
		//說說的字型樣式
		ss.setSpan(new ForegroundColorSpan(Color.RED), name.length(), msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

		mTxt.setText(ss);
		mTxt.setMovementMethod(LinkMovementMethod.getInstance());//設定超連結為可點選狀態
    }

    /**
     * 名稱的點選事件
     */
    private ClickableSpan clickableSpan = new ClickableSpan() {
		@Override
		public void updateDrawState(TextPaint ds) {
		    super.updateDrawState(ds);
		    ds.setUnderlineText(false); //去掉下劃線
		    ds.setColor(Color.BLUE);//設定點選前的顏色
		}

		@Override
		public void onClick(View widget) {
		    toast(((TextView) widget).getText());
		}
    };

    private void toast(CharSequence str) {
		//如果這裡加了 String.valueOf(str),彈出的提示,就會沒有樣式
		Toast toast = Toast.makeText(MyApplication.getContext(), str, Toast.LENGTH_SHORT);
		toast.setGravity(Gravity.TOP, 0, 200);//改變Toast彈出的位置
		toast.show();
    }
}
複製程式碼

在最後順便用到了修改Toast提示的位置。 座標可以根據螢幕的解析度的尺寸的百分比來進行計算,會更合理。

好了,本次分享就到這裡。 專案地址: github.com/Wing-Li/Pra…

歡迎指正。

相關文章