效果圖:
佈局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<com.home.JustifyTextView
android:layout_width="@dimen/dp60"
android:layout_height="wrap_content"
android:text="支付時間"
android:textColor="@color/white"
android:textSize="@dimen/dp14"
android:layout_marginLeft="@dimen/dp50"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textColor="@color/white"
android:textSize="@dimen/dp14" />
<TextView
android:id="@+id/tv_date_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2019-12-03 14:56"
android:textColor="@color/white"
android:textSize="@dimen/dp14" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<com.home.JustifyTextView
android:layout_width="@dimen/dp60"
android:layout_height="wrap_content"
android:text="流水號"
android:textColor="@color/white"
android:textSize="@dimen/dp14"
android:layout_marginLeft="@dimen/dp50"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textColor="@color/white"
android:textSize="@dimen/dp14" />
<TextView
android:id="@+id/tv_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="20191203145976059"
android:textColor="@color/white"
android:textSize="@dimen/dp14" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<com.home.JustifyTextView
android:layout_width="@dimen/dp60"
android:layout_height="wrap_content"
android:text="金額"
android:textColor="@color/white"
android:textSize="@dimen/dp14"
android:layout_marginLeft="@dimen/dp50"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textColor="@color/white"
android:textSize="@dimen/dp14" />
<TextView
android:id="@+id/tv_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-64.00元"
android:textColor="@color/red"
android:textSize="@dimen/dp14" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<com.home.JustifyTextView
android:layout_width="@dimen/dp60"
android:layout_height="wrap_content"
android:text="對方賬號"
android:textColor="@color/white"
android:textSize="@dimen/dp14"
android:layout_marginLeft="@dimen/dp50"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:textColor="@color/white"
android:textSize="@dimen/dp14" />
<TextView
android:id="@+id/tv_remote_account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="青春餵了狗"
android:textColor="@color/white"
android:textSize="@dimen/dp14" />
</LinearLayout>
</LinearLayout>
核心重點在JustifyTextView這個類,實現如下:
package com.home;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
public class JustifyTextView extends android.support.v7.widget.AppCompatTextView {
public static final String TAG = JustifyTextView.class.getSimpleName();
private Paint paint = new Paint();
private Rect rect_0 = new Rect();
private Rect rect_l = new Rect();
private Rect rect_tmp = new Rect();
public JustifyTextView(Context context) {
super(context);
}
public JustifyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public JustifyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas)
{
CharSequence cs = getText();
String txt = null;
if(cs == null)
txt = "";
else
txt = cs.toString();
if(txt.length() == 0)
super.onDraw(canvas);
else
{
float textSize = getTextSize();
Typeface typeface = getTypeface();
int color = getCurrentTextColor();
int w = getWidth();
int h = getHeight();
int l = getPaddingLeft();
int r = w - getPaddingRight();
int t = getPaddingTop();
int b = h - getPaddingBottom();
paint.setAntiAlias(true);
paint.setTypeface(typeface);
paint.setTextSize(textSize);
paint.setTextAlign(Paint.Align.LEFT);
paint.setColor(color);
int centerY = (b + t) / 2;
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float y = centerY + (fontMetrics.descent - fontMetrics.ascent) / 2- fontMetrics.descent; // 垂直方向也居中;
paint.getTextBounds(txt, 0, 1, rect_0); // 獲取第一個字符的大小
paint.getTextBounds(txt, 0, 1, rect_l); // 獲取最後一個字符的大小
float space = (r - l - (rect_0.width() * 0.5f) - (rect_l.width() * 0.5f)) / (txt.length() - 1);
for(int i = 0, iMax = txt.length(); i < iMax; ++i)
{
float x = 0;
if(i == 0)
x = l;
else if(i == iMax - 1)
x = r - rect_l.width();
else
{
paint.getTextBounds(txt, i, i + 1, rect_tmp); // 獲取每一個字符的大小
x = l + rect_0.width() * 0.5f + i * space - rect_tmp.width() * 0.5f;
}
canvas.drawText(txt, i, i + 1, x, y, paint);
}
}
}
}
大概解釋一下中間幾個重點:
一、主要的思路:首先確定最左側一個字符緊貼繪製區域最左側,左右側一個字符緊貼繪製區域最右側,中間的字符在繪製區域中間的空白部分,中心點均勻分佈,讓任意相鄰的兩個字符中心點距離相等。大概圖示如下:
短豎線表示字符中心點,對應代碼中x變量,中間橫線爲一個字符的區域(這個區域大於等於字符實際寬度),對應代碼中的space變量
二、關於x以及space的計算中經常出現的width*0.5f,之所以出現width*0.5f是因爲代碼裏面設置了paint.setTextAlign(Paint.Align.LEFT);這樣一來drawText繪製的時候,對於x座標就都是以字符左側爲標準,而我們確定字符位置都是根據中心點,於是就經常出現減去width*0.5f的情況
三、關於y座標的計算:
float y = centerY + (fontMetrics.descent - fontMetrics.ascent) / 2- fontMetrics.descent; // 垂直方向也居中;
這段代碼是之前寫另外一個控件的時候,從網上某篇帖子裏面摘抄的,時間太久,找不到原文了。關於這段代碼的具體含義,尚不清楚,只知道它能讓文本垂直居中。
四、關於一些bug:
經測試,對於純中文或純英文情況下效果很好,中英混輸情況下,就出現很大的偏差,目前還不知道爲什麼,暫時效果滿足,以後想起來再想辦法修復