TextView文本尾部添加標籤,支持自動換行

TextView文本尾部添加標籤,支持自動換行

需求

開發過程當中咱們常常會遇到文字尾部添加標籤的需求,看是很簡單,其實蠻難作的。好比咱們的設計稿以下:java

打眼一看,一個水平方向線性佈局就解決了,內部寫兩個TextView就行。android

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="20dp">

    <TextView
        android:id="@+id/tv3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="天行健,君子以自強不息;"
        android:textColor="#000"
        android:textSize="15sp" />

    <TextView
        android:id="@+id/tv4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/room_member_role_bg"
        android:paddingLeft="6dp"
        android:paddingRight="6dp"
        android:text="王蛋蛋的芭比"
        android:textColor="#000"
        android:textSize="15sp" />

</LinearLayout>
複製代碼

emmmmm,可是,要是文字是多行的呢,咱們的標籤還能順利的放在後面麼?git

若是第一行文本過長,咱們就會獲得下面的結果: 尾部標籤顯示不全:github

或者以下,尾部標籤直接不顯示。緩存

若是文字最後一行的剩餘空間放不下咱們的尾部標籤,比較通用的作法是讓標籤換行。bash

咱們想要的是這樣的:app

接下來咱們一步步實現這個需求。佈局

使用SpannableStringBuilder + ImageSpan實現

使用過SpannableStringBuilder的同窗都驚歎於它的強大,經過SpannableStringBuilder#setSpan()咱們能夠給TextView的文本設置獨特的樣式,好比加粗、斜體、字體大小、字體顏色、背景顏色、圖片、刪除線、下劃線、點擊事件等等。字體

咱們這裏也使用SpannableStringBuilder + 特定Span的方式來實現。ui

咱們的尾部標籤實質上是給特定文本添加一個drawable背景,通過調研發現,雖然咱們能夠經過ReplacementSpan等方式給文字繪製drawable背景,可是背景上方的文字卻不顯示,這個方案就暫時夭折了。

回過頭來,咱們發現SpannableStringBuilder + ImageSpan能夠實現將圖片自動換行,而且若是剩餘空間不足時圖片會自動換行,以下所示:

從第二個TextView能夠看出,當前行的剩餘空間不夠放置ImageSpan圖片時,會自動換行。這樣就解決了咱們的自動換行的問題。

咱們接下來看下ImageSpan的構造方法,會發現它不只支持Drawable,還支持Bitmap對象,具體以下:

咱們還知道,View有個getDrawingCache()方法,它能夠生成當前View的Bitmap緩存。

此時咱們的實現思路能夠串起來了,具體以下圖:

代碼實現

具體分爲四步: ①建立TextView對象,設置drawable背景,設置字體樣式,設置間距,設置文本等 ②將View生成Bitmap對象 ③根據Bitmap對象生成ImageSpan對象 ④將ImageSpan對象設置到SpannableStringBuilder的對應位置

具體代碼以下:註釋寫的很清楚,這裏就再也不贅述。

private void addTagToTextView(TextView target, String title, String tag) {
    if (TextUtils.isEmpty(title)) {
        title = "";
    }

    String content = title + tag;


    /**
     * 建立TextView對象,設置drawable背景,設置字體樣式,設置間距,設置文本等
     * 這裏咱們爲了給TextView設置margin,給其添加了一個父容器LinearLayout。不過他倆都只是new出來的,不會添加進任何佈局
     */
    LinearLayout layout = new LinearLayout(this);
    TextView textView = new TextView(this);
    textView.setText(tag);
    textView.setBackground(getResources().getDrawable(R.drawable.room_member_role_bg));
    textView.setTextSize(12);
    textView.setTextColor(Color.parseColor("#FDA413"));
    textView.setIncludeFontPadding(false);
    textView.setPadding(ScreenUtils.dip2px(this, 6), 0,
            ScreenUtils.dip2px(this, 6), 0);
    textView.setHeight(ScreenUtils.dip2px(this, 17));
    textView.setGravity(Gravity.CENTER_VERTICAL);

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    // 設置左間距
    layoutParams.leftMargin = ScreenUtils.dip2px(this, 6);
    // 設置下間距,簡單解決ImageSpan和文本豎直方向對齊的問題
    layoutParams.bottomMargin = ScreenUtils.dip2px(this, 3);
    layout.addView(textView, layoutParams);

    /**
     * 第二步,測量,繪製layout,生成對應的bitmap對象
     */
    layout.setDrawingCacheEnabled(true);
    layout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    // 給上方設置的margin留出空間
    layout.layout(0, 0, textView.getMeasuredWidth() + ScreenUtils.dip2px(this, (6 + 3)), textView.getMeasuredHeight());
    // 獲取bitmap對象
    Bitmap bitmap = Bitmap.createBitmap(layout.getDrawingCache());
    //千萬別忘最後一步
    layout.destroyDrawingCache();

    /**
     * 第三步,經過bitmap生成咱們須要的ImageSpan對象
     */
    ImageSpan imageSpan = new ImageSpan(this, bitmap);


    /**
     * 第四步將ImageSpan對象設置到SpannableStringBuilder的對應位置
     */
    SpannableStringBuilder ssb = new SpannableStringBuilder(content);
    //將尾部tag字符用ImageSpan替換
    ssb.setSpan(imageSpan, title.length(), content.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
    target.setText(ssb);
}
複製代碼

項目地址:Android_Base_Demo

具體代碼請看:SpannableStringBuilderActivity

頁面入口展現:

頁面入口展現

固然了,實現這種需求的方式有不少種,這裏的這種方式比較取巧。你們若是有好的實現方式,還望不吝賜教,比心。

參考

Textview轉化成Bitmap對象

相關文章
相關標籤/搜索