Android中TextView自動適配文本大小的幾種解決方案
TextView文本大小自動適配與TextView邊距的去除
標題太難取瞭,其實本文主要就是講如何控制文本大小,讓其自動適配寬度,其次我們還需要精準控制Text的高度和寬度間距等屬性。
一般我們的佈局都是分 match parent 和 wrap content 而他們的自動方式又有所不同。下面看看都有哪些方式來實現!
一、Autosizing的方式(固定寬度)
官方推出的TextView的Autosizing方式,在寬度固定的情況下,可以設置最大文本Size和最小文本Size和每次縮放粒度,非常方便的就能實現該功能。
<TextView android:layout_width="340dp" android:layout_height="50dp" android:background="@drawable/shape_bg_008577" android:gravity="center_vertical" android:maxLines="1" android:text="這是標題,該標題的名字比較長,產品要求不換行全部顯示出來" android:textSize="18sp" android:autoSizeTextType="uniform" android:autoSizeMaxTextSize="18sp" android:autoSizeMinTextSize="10sp" android:autoSizeStepGranularity="1sp"/>
- autoSizeTextType:設置 TextView 是否支持自動改變文本大小,none 表示不支持,uniform 表示支持。
- autoSizeMinTextSize:最小文字大小,例如設置為10sp,表示文字最多隻能縮小到10sp。
- autoSizeMaxTextSize:最大文字大小,例如設置為18sp,表示文字最多隻能放大到18sp。
- autoSizeStepGranularity:縮放粒度,即每次文字大小變化的數值,例如設置為1sp,表示每次縮小或放大的值為1sp。
效果:
如果在Java代碼中使用,我們也可以這麼用
TextView tvText = findViewById(R.id.tv_text); TextViewCompat.setAutoSizeTextTypeWithDefaults(tvText,TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM); TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(tvText,10,18,1, TypedValue.COMPLEX_UNIT_SP);
二、自定義View的方式(固定寬度)
github上有很多這種的TextView自定義,類似這樣的。
其核心思想和上面的 Autosizing 的方式類似,一般是測量 TextView 字體所占的寬度與 TextView 控件的寬度對比,動態改變 TextView 的字體大小。
它們的類似用法如下:
<ru.igla.widget.AutoSizeTextView android:id="@+id/tvFullscreen" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Long ancestry" android:textColor="@android:color/black" android:background="@android:color/white" android:textSize="500sp" android:maxLines="500" android:gravity="center" android:ellipsize="@null" android:autoText="false" android:autoLink="none" android:linksClickable="false" android:singleLine="false" android:padding="0px" android:includeFontPadding="false" android:textAlignment="center" android:typeface="normal" android:layout_gravity="center" android:textStyle="normal" app:minTxtSize="8sp" />
效果和方案一類似
三、使用工具類自行計算(非控件固定寬度)
把第二步中自定義View計算寬度的方法抽取出來,我們可以可以得到一個工具類如下:
private void adjustTvTextSize(TextView tv, int maxWidth, String text) { int avaiWidth = maxWidth - tv.getPaddingLeft() - tv.getPaddingRight(); if (avaiWidth <= 0) { return; } TextPaint textPaintClone = new TextPaint(tv.getPaint()); float trySize = textPaintClone.getTextSize(); while (textPaintClone.measureText(text) > avaiWidth) { trySize--; textPaintClone.setTextSize(trySize); } tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, trySize); }
Demo如下:
右側的LinearLayout中需要包含2個文本 一個14sp 一個是30sp,同時居中但是要金額的文本自動適配大小。
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/d_15dp" android:layout_marginRight="@dimen/d_15dp" android:gravity="center" android:orientation="horizontal"> <TextView android:id="@+id/tv_job_detail_dollar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="$" android:textColor="@color/black" android:textSize="@dimen/job_detail_message_size"/> <TextView android:id="@+id/text_view_hourly_rate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/d_2dp" android:singleLine="true" android:text="-" android:textColor="@color/job_detail_black" android:textSize="30sp" /> </LinearLayout>
可以看到2個都是wrap content,那麼如何實現這種適應寬度+多佈局的變長寬度效果呢。其實就是需要我們調用方法手動的計算金額TextView的寬度
int mFullNameTVMaxWidth = CommUtils.dip2px(60); // mTextViewHourlyRate.setText(totalMoney); // while (true) { // float measureTextWidth = mTextViewHourlyRate.getPaint().measureText(totalMoney); // if (measureTextWidth > mFullNameTVMaxWidth) { // int textSize = (int) mTextViewHourlyRate.getTextSize(); // textSize = textSize - 2; // mTextViewHourlyRate.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); // } else { // break; // } // } adjustTvTextSize(mTextViewHourlyRate,mFullNameTVMaxWidth,totalMoney)
效果如下:(該效果是去除邊距之後的對齊效果)
四、去除TextView的邊距
我們都知道TextView繪制的時候並非是我們平常自定義View那種drawText,而是分為幾塊區域,基於基線繪制文本,並加入瞭上下左右的間距。
而不同的TestSize 它的間距還不同,比如上文中我們一個很小的 TextView 和一個很大的 TextView 在一起排列的時候,特別是大的 TextView 還是 AutoSize 的情況下,實現一些對齊效果就很難實現,我們就需要考慮到去除間距,隻保留上圖灰色的矩形框來繪制文本。
代碼如下:
public class NoPaddingTextView extends AppCompatTextView { private Paint mPaint = getPaint(); private Rect mBounds = new Rect(); private Boolean mRemoveFontPadding = false;//是否去除字體內邊距,true:去除 false:不去除 public NoPaddingTextView(Context context) { super(context); } public NoPaddingTextView(Context context, AttributeSet attrs) { super(context, attrs); initAttributes(context, attrs); } public NoPaddingTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttributes(context, attrs); } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mRemoveFontPadding) { calculateTextParams(); setMeasuredDimension(mBounds.right - mBounds.left, -mBounds.top + mBounds.bottom); } } protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } protected void onDraw(Canvas canvas) { drawText(canvas); } /** * 初始化屬性 */ private void initAttributes(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NoPaddingTextView); mRemoveFontPadding = typedArray.getBoolean(R.styleable.NoPaddingTextView_removeDefaultPadding, false); typedArray.recycle(); } /** * 計算文本參數 */ private String calculateTextParams() { String text = getText().toString(); int textLength = text.length(); mPaint.getTextBounds(text, 0, textLength, mBounds); if (textLength == 0) { mBounds.right = mBounds.left; } return text; } /** * 繪制文本 */ private void drawText(Canvas canvas) { String text = calculateTextParams(); int left = mBounds.left; int bottom = mBounds.bottom; mBounds.offset(-mBounds.left, -mBounds.top); mPaint.setAntiAlias(true); mPaint.setColor(getCurrentTextColor()); canvas.drawText(text, (float) (-left), (float) (mBounds.bottom - bottom), mPaint); } }
使用:
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/d_15dp" android:layout_marginRight="@dimen/d_15dp" android:gravity="center" android:orientation="horizontal"> <com.guadou.componentservice.widget.view.NoPaddingTextView android:id="@+id/tv_job_detail_dollar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="$" android:textColor="@color/black" android:background="@color/yellow" android:textSize="@dimen/job_detail_message_size" app:removeDefaultPadding="true" /> <com.guadou.componentservice.widget.view.NoPaddingTextView android:id="@+id/text_view_hourly_rate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/d_2dp" android:singleLine="true" android:text="-" android:background="@color/red" android:textColor="@color/job_detail_black" android:textSize="30sp" app:removeDefaultPadding="true" /> </LinearLayout>
效果如下:
到此我們就能隨心的控制 TextView 的大小和間距,想讓文本多大就多大,想在哪展示就在哪展示,很方便的實現對齊和絕大部分文本的展示效果瞭。
總結
到此這篇關於Android中TextView自動適配文本大小的幾種解決方案的文章就介紹到這瞭,更多相關Android TextView自動適配文本大小內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- android跑馬燈出現重復跳動以及不滾動問題的解決方法
- Android文本視圖TextView實現跑馬燈效果
- android自定義對話框實例代碼
- Android使用setContentView實現頁面的轉換效果
- Android中Activity組件實例介紹