当前位置:   article > 正文

TextView自动适配文本大小的几种方案_android 字体大小方案

android 字体大小方案

标题太难取了,其实本文主要就是讲如何控制文本大小,让其自动适配宽度,其次我们还需要精准控制Text的高度和宽度间距等属性。

一般我们的布局都是分 match parent 和 wrap content 而他们的自动方式又有所不同。下面看看都有哪些方式来实现!

一、Autosizing的方式(固定宽度)

官方推出的TextView的Autosizing方式,在宽度固定的情况下,可以设置最大文本Size和最小文本Size和每次缩放粒度,非常方便的就能实现该功能。

  1. <TextView
  2. android:layout_width="340dp"
  3. android:layout_height="50dp"
  4. android:background="@drawable/shape_bg_008577"
  5. android:gravity="center_vertical"
  6. android:maxLines="1"
  7. android:text="这是标题,该标题的名字比较长,产品要求不换行全部显示出来"
  8. android:textSize="18sp"
  9. android:autoSizeTextType="uniform"
  10. android:autoSizeMaxTextSize="18sp"
  11. android:autoSizeMinTextSize="10sp"
  12. android:autoSizeStepGranularity="1sp"/>
  13. 复制代码
  1. autoSizeTextType:设置 TextView 是否支持自动改变文本大小,none 表示不支持,uniform 表示支持。
  2. autoSizeMinTextSize:最小文字大小,例如设置为10sp,表示文字最多只能缩小到10sp。
  3. autoSizeMaxTextSize:最大文字大小,例如设置为18sp,表示文字最多只能放大到18sp。
  4. autoSizeStepGranularity:缩放粒度,即每次文字大小变化的数值,例如设置为1sp,表示每次缩小或放大的值为1sp。

效果:

如果在Java代码中使用,我们也可以这么用

  1. TextView tvText = findViewById(R.id.tv_text);
  2. TextViewCompat.setAutoSizeTextTypeWithDefaults(tvText,TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
  3. TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(tvText,10,18,1, TypedValue.COMPLEX_UNIT_SP);
  4. 复制代码

二、自定义View的方式(固定宽度)

github上有很多这种的TextView自定义,类似这样的。

其核心思想和上面的 Autosizing 的方式类似,一般是测量 TextView 字体所占的宽度与 TextView 控件的宽度对比,动态改变 TextView 的字体大小。

它们的类似用法如下:

  1. <ru.igla.widget.AutoSizeTextView
  2. android:id="@+id/tvFullscreen"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:text="Long ancestry"
  6. android:textColor="@android:color/black"
  7. android:background="@android:color/white"
  8. android:textSize="500sp"
  9. android:maxLines="500"
  10. android:gravity="center"
  11. android:ellipsize="@null"
  12. android:autoText="false"
  13. android:autoLink="none"
  14. android:linksClickable="false"
  15. android:singleLine="false"
  16. android:padding="0px"
  17. android:includeFontPadding="false"
  18. android:textAlignment="center"
  19. android:typeface="normal"
  20. android:layout_gravity="center"
  21. android:textStyle="normal"
  22. app:minTxtSize="8sp"
  23. />
  24. 复制代码

效果和方案一类似

三、使用工具类自行计算(非控件固定宽度)

把第二步中自定义View计算宽度的方法抽取出来,我们可以可以得到一个工具类如下:

  1. private void adjustTvTextSize(TextView tv, int maxWidth, String text) {
  2. int avaiWidth = maxWidth - tv.getPaddingLeft() - tv.getPaddingRight();
  3. if (avaiWidth <= 0) {
  4. return;
  5. }
  6. TextPaint textPaintClone = new TextPaint(tv.getPaint());
  7. float trySize = textPaintClone.getTextSize();
  8. while (textPaintClone.measureText(text) > avaiWidth) {
  9. trySize--;
  10. textPaintClone.setTextSize(trySize);
  11. }
  12. tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, trySize);
  13. }
  14. 复制代码

Demo如下:

右侧的LinearLayout中需要包含2个文本 一个14sp 一个是30sp,同时居中但是要金额的文本自动适配大小。

  1. <LinearLayout
  2. android:layout_width="match_parent"
  3. android:layout_height="wrap_content"
  4. android:layout_marginLeft="@dimen/d_15dp"
  5. android:layout_marginRight="@dimen/d_15dp"
  6. android:gravity="center"
  7. android:orientation="horizontal">
  8. <TextView
  9. android:id="@+id/tv_job_detail_dollar"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:text="$"
  13. android:textColor="@color/black"
  14. android:textSize="@dimen/job_detail_message_size"/>
  15. <TextView
  16. android:id="@+id/text_view_hourly_rate"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:layout_marginLeft="@dimen/d_2dp"
  20. android:singleLine="true"
  21. android:text="-"
  22. android:textColor="@color/job_detail_black"
  23. android:textSize="30sp" />
  24. </LinearLayout>
  25. 复制代码

可以看到2个都是wrap content,那么如何实现这种适应宽度+多布局的变长宽度效果呢。其实就是需要我们调用方法手动的计算金额TextView的宽度

  1. int mFullNameTVMaxWidth = CommUtils.dip2px(60);
  2. // mTextViewHourlyRate.setText(totalMoney);
  3. // while (true) {
  4. // float measureTextWidth = mTextViewHourlyRate.getPaint().measureText(totalMoney);
  5. // if (measureTextWidth > mFullNameTVMaxWidth) {
  6. // int textSize = (int) mTextViewHourlyRate.getTextSize();
  7. // textSize = textSize - 2;
  8. // mTextViewHourlyRate.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
  9. // } else {
  10. // break;
  11. // }
  12. // }
  13. adjustTvTextSize(mTextViewHourlyRate,mFullNameTVMaxWidth,totalMoney)
  14. 复制代码

效果如下:(该效果是去除边距之后的对齐效果)

 

四、去除TextView的边距

我们都知道TextView绘制的时候并非是我们平常自定义View那种drawText,而是分为几块区域,基于基线绘制文本,并加入了上下左右的间距。

 

而不同的TextSize 它的间距还不同,比如上文中我们一个很小的 TextView 和一个很大的 TextView 在一起排列的时候,特别是大的 TextView 还是 AutoSize 的情况下,实现一些对齐效果就很难实现,并且本来宽度就极其有限了,再加上这么多无用的间距,搞得我们很难实现效果嘛!那我们就需要考虑到去除间距,只保留上图灰色的矩形框来绘制文本。

代码如下:

  1. public class NoPaddingTextView extends AppCompatTextView {
  2. private Paint mPaint = getPaint();
  3. private Rect mBounds = new Rect();
  4. private Boolean mRemoveFontPadding = false;//是否去除字体内边距,true:去除 false:不去除
  5. public NoPaddingTextView(Context context) {
  6. super(context);
  7. }
  8. public NoPaddingTextView(Context context, AttributeSet attrs) {
  9. super(context, attrs);
  10. initAttributes(context, attrs);
  11. }
  12. public NoPaddingTextView(Context context, AttributeSet attrs, int defStyleAttr) {
  13. super(context, attrs, defStyleAttr);
  14. initAttributes(context, attrs);
  15. }
  16. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  17. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  18. if (mRemoveFontPadding) {
  19. calculateTextParams();
  20. setMeasuredDimension(mBounds.right - mBounds.left, -mBounds.top + mBounds.bottom);
  21. }
  22. }
  23. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  24. super.onSizeChanged(w, h, oldw, oldh);
  25. }
  26. protected void onDraw(Canvas canvas) {
  27. drawText(canvas);
  28. }
  29. /**
  30. * 初始化属性
  31. */
  32. private void initAttributes(Context context, AttributeSet attrs) {
  33. TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NoPaddingTextView);
  34. mRemoveFontPadding = typedArray.getBoolean(R.styleable.NoPaddingTextView_removeDefaultPadding, false);
  35. typedArray.recycle();
  36. }
  37. /**
  38. * 计算文本参数
  39. */
  40. private String calculateTextParams() {
  41. String text = getText().toString();
  42. int textLength = text.length();
  43. mPaint.getTextBounds(text, 0, textLength, mBounds);
  44. if (textLength == 0) {
  45. mBounds.right = mBounds.left;
  46. }
  47. return text;
  48. }
  49. /**
  50. * 绘制文本
  51. */
  52. private void drawText(Canvas canvas) {
  53. String text = calculateTextParams();
  54. int left = mBounds.left;
  55. int bottom = mBounds.bottom;
  56. mBounds.offset(-mBounds.left, -mBounds.top);
  57. mPaint.setAntiAlias(true);
  58. mPaint.setColor(getCurrentTextColor());
  59. canvas.drawText(text, (float) (-left), (float) (mBounds.bottom - bottom), mPaint);
  60. }
  61. }
  62. 复制代码

使用:

  1. <LinearLayout
  2. android:layout_width="match_parent"
  3. android:layout_height="wrap_content"
  4. android:layout_marginLeft="@dimen/d_15dp"
  5. android:layout_marginRight="@dimen/d_15dp"
  6. android:gravity="center"
  7. android:orientation="horizontal">
  8. <com.guadou.componentservice.widget.view.NoPaddingTextView
  9. android:id="@+id/tv_job_detail_dollar"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:text="$"
  13. android:textColor="@color/black"
  14. android:background="@color/yellow"
  15. android:textSize="@dimen/job_detail_message_size"
  16. app:removeDefaultPadding="true" />
  17. <com.guadou.componentservice.widget.view.NoPaddingTextView
  18. android:id="@+id/text_view_hourly_rate"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:layout_marginLeft="@dimen/d_2dp"
  22. android:singleLine="true"
  23. android:text="-"
  24. android:background="@color/red"
  25. android:textColor="@color/job_detail_black"
  26. android:textSize="30sp"
  27. app:removeDefaultPadding="true" />
  28. </LinearLayout>
  29. 复制代码

效果如下:


 

到此我们就能随心的控制 TextView 的大小和间距,想让文本多大就多大,想在哪展示就在哪展示,很方便的实现对齐和绝大部分文本的展示效果了。

 


 

链接:https://juejin.cn/post/7106714269730914312
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/543889
推荐阅读
相关标签
  

闽ICP备14008679号