1. 程式人生 > >解決TextView在顯示文字的時候,一行還沒顯示滿就跳到下一行(最新)

解決TextView在顯示文字的時候,一行還沒顯示滿就跳到下一行(最新)

轉載請註明:轉自 http://blog.csdn.net/u011176685/article/details/48295185

一、問題描述:

Android的TextView在顯示文字的時候,如果有段中文有英文,有中文,有中文標點符號,你會發現,當要換行的時候遇到中文標點,

這一行就會空出很多空格出來。原因是:

1) TextView在顯示中文的時候 標點符號不能顯示在一行的行首和行尾,如果一個標點符號剛好在一行的行尾,該標點符號就會連同前一個字元跳到下一行顯示;

2)一個英文單詞不能被顯示在兩行中( TextView在顯示英文時,標點符號是可以放在行尾的,但英文單詞也不能分開 );

3)全形和半形的問題,漢字無論全形還是半形都是佔2個位元組,英文和符號在半形是佔一個位元組,全形是佔兩個位元組。


二、解決方法

可能由於時間問題,都沒有很好解決我的問題。將textview中的字元全形化沒有效果,去除特殊字元或將所有中文標號替換為英文標號。這個有點效果,但是產品經理說文案不符合標準。改原始碼擔心出問題,影響其他的應用。自定義TextView時,canvas.setViewport()這個方法的api被刪了。然後各種百度查資料,很多都是轉過來轉過去。然並卵。後面找了好久才找到一個靠譜的。完美的解決了我的問題。

自定義TextView(直接把程式碼拷進去就能用)

package com.lhx.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.widget.TextView;

/**
 * @author lhx
 * @Date 9/8/15
 */
public class MyTextView extends TextView {

    private int mLineY;
    private int mViewWidth;

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right,
                            int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDraw(Canvas Canvas) {
        TextPaint paint = getPaint();
        paint.setColor(getCurrentTextColor());
        paint.drawableState = getDrawableState();
        mViewWidth = getMeasuredWidth();
        String text = getText().toString();
        mLineY = 0;
        mLineY += getTextSize();
        Layout layout = getLayout();

        // layout.getLayout()在4.4.3出現NullPointerException
        if (layout == null) {
            return;
        }

        Paint.FontMetrics fm = paint.getFontMetrics();

        int textHeight = (int) (Math.ceil(fm.descent - fm.ascent));
        textHeight = (int) (textHeight * layout.getSpacingMultiplier() + layout
                .getSpacingAdd());
        //解決了最後一行文字間距過大的問題
        for (int i = 0; i < layout.getLineCount(); i++) {
            int lineStart = layout.getLineStart(i);
            int lineEnd = layout.getLineEnd(i);
            float width = StaticLayout.getDesiredWidth(text, lineStart,
                    lineEnd, getPaint());
            String line = text.substring(lineStart, lineEnd);

            if(i < layout.getLineCount() - 1) {
                if (needScale(line)) {
                    drawScaledText(Canvas, lineStart, line, width);
                } else {
                    Canvas.drawText(line, 0, mLineY, paint);
                }
            } else {
                Canvas.drawText(line, 0, mLineY, paint);
            }
            mLineY += textHeight;
        }
    }

    private void drawScaledText(Canvas Canvas, int lineStart, String line,
                                float lineWidth) {
        float x = 0;
        if (isFirstLineOfParagraph(lineStart, line)) {
            String blanks = "  ";
            Canvas.drawText(blanks, x, mLineY, getPaint());
            float bw = StaticLayout.getDesiredWidth(blanks, getPaint());
            x += bw;

            line = line.substring(3);
        }

        int gapCount = line.length() - 1;
        int i = 0;
        if (line.length() > 2 && line.charAt(0) == 12288
                && line.charAt(1) == 12288) {
            String substring = line.substring(0, 2);
            float cw = StaticLayout.getDesiredWidth(substring, getPaint());
            Canvas.drawText(substring, x, mLineY, getPaint());
            x += cw;
            i += 2;
        }

        float d = (mViewWidth - lineWidth) / gapCount;
        for (; i < line.length(); i++) {
            String c = String.valueOf(line.charAt(i));
            float cw = StaticLayout.getDesiredWidth(c, getPaint());
            Canvas.drawText(c, x, mLineY, getPaint());
            x += cw + d;
        }
    }

    private boolean isFirstLineOfParagraph(int lineStart, String line) {
        return line.length() > 3 && line.charAt(0) == ' '
                && line.charAt(1) == ' ';
    }

    private boolean needScale(String line) {
        if (line == null || line.length() == 0) {
            return false;
        } else {
            return line.charAt(line.length() - 1) != '\n';
        }
    }

}

xml檔案程式碼
 <!--工作時間提醒-->
    <LinearLayout
            android:layout_width="match_parent"
            android:id="@+id/ll_chat"
            android:background="@color/topbar_chat"
            android:layout_height="wrap_content">
        <com.lhx.widget.MyTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/tv_reminder"
                android:layout_marginTop="5dp"
                android:layout_marginBottom="5dp"
                android:layout_marginRight="8dp"
                android:layout_marginLeft="8dp"
                android:text = "服務商不管以任何形式要求線下交易,都存在詐騙的風險,請提高警惕。This is test!歡迎相互關注。有不對的地方望指出和包容。謝謝! "
                android:textColor="@color/text_orange_1"/>
    </LinearLayout>

以上就很好的解決了TextView中英文字元排版的問題,折騰了好久終於搞定。希望對您有點幫助。