多行文字末尾新增圖片排版問題解決

沉默的範大叔發表於2019-03-04

最近在專案中需要在某個多行英文文字末尾增加一個圖片,嘗試了很多方法,最後用了一個比較Tricky的方法解決了,當然這種方法不一定是最好最優的解決辦法,記錄一下。

問題

如果直接使用drawableRight或者drawableEnd來將圖片放置到文字末尾,結果會是這樣:

多行文字末尾新增圖片排版問題解決

圖片會在TextView右邊豎直方向的中間位置顯示,而不是我們期望的在最後一行位置顯示。
這時我們可以嘗試使用ImageSpan來將圖片放置在最後一行:

    final TextView text = findViewById(R.id.text);
    final String string = "dkffkdjkfjdkfjkdjfdjfkjdkfjkdjkdjfkjdkjk";
    //建立一個SpannableString物件,後面增加空格是預留給圖片的
    SpannableString spannableString = new SpannableString(string + "  ");
    //建立圖片的Drawable物件
    Drawable drawable = getResources().getDrawable(R.mipmap.copy);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    //建立圖片的ImageSpan物件
    ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
    //設定ImageSpan,將其位置設定在spannableString最後面,起始位置start=spannableString.length() - 1,結束位置為end=spannableString.length(),
    // SPAN_INCLUSIVE_EXCLUSIVE表示包含start不包含end
    spannableString.setSpan(imageSpan, spannableString.length() - 1, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    text.setText(spannableString);
複製程式碼

效果如下:

多行文字末尾新增圖片排版問題解決

圖片確實是放在了最後面,但是英文文字的顯示出現了凌亂。

原因

實際上最後的效果是TextView繪製出來的,原因當然是TextView繪製咯。TextView的Span繪製主要是使用DynamicLayout裡面的方法來計算行數,
呼叫其draw方法(DynamicLayout父類Layout實現)完成繪製。具體實現細節這裡就不在闡述,有興趣的朋友可以自行研究下。

解決

這裡使用了比較討巧的一種方式,問題主要是文字換行並沒有按照我們期望的樣子進行,而是換行之後後面還留了一大半空白。後面發現如果字串中包含了空格的話,
就會自動以空格的位置進行換行。所以解決思路就是按照TextView的寬度,計算每一行能夠容納的字元個數,在每一行的最後插入一個空格,就能解決換行凌亂了。
具體實現如下:

//先設定原始文字
text.setText(string);
//使用post方法,在TextView完成繪製流程後在訊息佇列中被呼叫
text.post(new Runnable() {
    @Override
    public void run() {
        //獲取第一行的寬度
        float lineWidth = text.getLayout().getLineWidth(0);
        //獲取第一行最後一個字元的下標
        int lineEnd = text.getLayout().getLineEnd(0);
        //計算每個字元佔的寬度
        float widthPerChar = lineWidth / (lineEnd + 1);
        //計算TextView一行能夠放下多少個字元
        int numberPerLine = (int) Math.floor(text.getWidth() / widthPerChar);
        //在原始字串中插入一個空格,插入的位置為numberPerLine - 1
        StringBuilder stringBuilder = new StringBuilder(string).insert(numberPerLine - 1, " ");

        //SpannableString的構建
        SpannableString spannableString = new SpannableString(stringBuilder.toString() + "  ");
        Drawable drawable = getResources().getDrawable(R.mipmap.copy);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
        spannableString.setSpan(imageSpan, spannableString.length() - 1, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        text.setText(spannableString);
    }

});
複製程式碼

這裡使用的是post方法延後處理,當然也可以使用ViewTreeObserver監聽佈局完成再進行處理,最後的效果,完美:

多行文字末尾新增圖片排版問題解決

相關文章