How to adjust text font size to fit textview

后端 未结 22 1762
無奈伤痛
無奈伤痛 2020-11-22 05:15

Is there any way in android to adjust the textsize in a textview to fit the space it occupies?

E.g. I\'m using a TableLayout and adding several Te

相关标签:
22条回答
  • 2020-11-22 05:54

    I had the same problem and wrote a class that seems to work for me. Basically, I used a static layout to draw the text in a separate canvas and remeasure until I find a font size that fits. You can see the class posted in the topic below. I hope it helps.

    Auto Scale TextView Text to Fit within Bounds

    0 讨论(0)
  • 2020-11-22 05:56

    You can now do this without a third party library or a widget. It's built into TextView in API level 26. Add android:autoSizeTextType="uniform" to your TextView and set height to it. That's all. Use app:autoSizeTextType="uniform" for backward compatibility

    https://developer.android.com/guide/topics/ui/look-and-feel/autosizing-textview.html

    <?xml version="1.0" encoding="utf-8"?>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:autoSizeTextType="uniform" />
    

    You can also use TextViewCompat for compatibility.

    0 讨论(0)
  • 2020-11-22 05:56

    I wrote a short helper class that makes a textview fit within a certain width and adds ellipsize "..." at the end if the minimum textsize cannot be achieved.

    Keep in mind that it only makes the text smaller until it fits or until the minimum text size is reached. To test with large sizes, set the textsize to a large number before calling the help method.

    It takes Pixels, so if you are using values from dimen, you can call it like this:


    float minTextSizePx = getResources().getDimensionPixelSize(R.dimen.min_text_size);
    float maxTextWidthPx = getResources().getDimensionPixelSize(R.dimen.max_text_width);
    WidgetUtils.fitText(textView, text, minTextSizePx, maxTextWidthPx);
    

    This is the class I use:


    public class WidgetUtils {
    
        public static void fitText(TextView textView, String text, float minTextSizePx, float maxWidthPx) {
            textView.setEllipsize(null);
            int size = (int)textView.getTextSize();
            while (true) {
                Rect bounds = new Rect();
                Paint textPaint = textView.getPaint();
                textPaint.getTextBounds(text, 0, text.length(), bounds);
                if(bounds.width() < maxWidthPx){
                    break;
                }
                if (size <= minTextSizePx) {
                    textView.setEllipsize(TextUtils.TruncateAt.END);
                    break;
                }
                size -= 1;
                textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 06:02

    This should be a simple solution:

    public void correctWidth(TextView textView, int desiredWidth)
    {
        Paint paint = new Paint();
        Rect bounds = new Rect();
    
        paint.setTypeface(textView.getTypeface());
        float textSize = textView.getTextSize();
        paint.setTextSize(textSize);
        String text = textView.getText().toString();
        paint.getTextBounds(text, 0, text.length(), bounds);
    
        while (bounds.width() > desiredWidth)
        {
            textSize--;
            paint.setTextSize(textSize);
            paint.getTextBounds(text, 0, text.length(), bounds);
        }
    
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }
    
    0 讨论(0)
  • 2020-11-22 06:03

    Inspired by the previous posters I wanted to share my solution. It works with a scale factor which is applied to the previous font size to make it fit the available space. In addition to prevent unexpected behaviour of TextViews onDraw method, it simply draws the text on its own.

    public class FontFitTextView extends TextView {
    
        // How much of the available space should be used in percent.
        private static final float MARGINHEIGHT = 0.8f;
        private static final float MARGINWIDTH = 0.8f;
    
        private Paint paint;
        private int viewWidth;
        private int viewHeight;
        private float textHeight;
        private float textWidth;
    
        public FontFitTextView(Context c) {
            this(c, null);
        }
    
        public FontFitTextView(Context c, AttributeSet attrs) {
            super(c, attrs);
            initComponent();
        }
    
        // Default constructor override
        public FontFitTextView(Context c, AttributeSet attrs, int defStyle) {
            super(c, attrs, defStyle);
            initComponent();
        }
    
        private void initComponent() {
            paint = new Paint();
            paint.setTextSize(30);
            paint.setTextAlign(Align.CENTER);
            paint.setAntiAlias(true);
        }
    
        public void setFontColor(int c) {
            paint.setColor(c);
        }
    
        private void calcTextSize(String s, Canvas c) {
    
            float availableHeight = viewHeight;
            float availableWidth = viewWidth;
    
            // This value scales the old font up or down to match the available
            // space.
            float scale = 1.0f;
    
            // Rectangle for measuring the text dimensions
            Rect rect = new Rect();
            float oldFontSize = paint.getTextSize();
    
            // Calculate the space used with old font size
            paint.getTextBounds(s, 0, s.length(), rect);
            textWidth = rect.width();
            textHeight = rect.height();
    
            // find scale-value to fit the text horizontally
            float scaleWidth = 1f;
            if (textWidth > 0.0f) {
                scaleWidth = (availableWidth) / textWidth * MARGINWIDTH;
            }
    
            // find scale-value to fit the text vertically
            float scaleHeight = 1f;
            if (textHeight > 0.0f) {
                scaleHeight = (availableHeight) / textHeight * MARGINHEIGHT;
            }
    
            // We are always limited by the smaller one
            if (scaleWidth < scaleHeight) {
                scale = scaleWidth;
            } else {
                scale = scaleHeight;
            }
    
            // We apply the scale to the old font size to make it bigger or smaller
            float newFontSize = (oldFontSize * scale);
            paint.setTextSize(newFontSize);
        }
    
        /**
         * Calculates the origin on the Y-Axis (width) for the text in this view.
         * 
         * @return
         */
        private float calcStartDrawingPosX() {
            float left = getMeasuredWidth();
            float centerY = left - (viewWidth / 2);
            return centerY;
        }
    
        /**
         * Calculates the origin on the Y-Axis (height) for the text in this view.
         * 
         * @return
         */
        private float calcStartDrawingPosY() {
            float bottom = getMeasuredHeight();
            // The paint only centers horizontally, origin on the Y-Axis stays at
            // the bottom, thus we have to lift the origin additionally by the
            // height of the font.
            float centerX = bottom - (viewHeight / 2) + (textHeight / 2);
            return centerX;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            String text = getText().toString();
            if (text.length() > 0) {
                calcTextSize(text, canvas);
                canvas.drawText(text, calcStartDrawingPosX(),
                        calcStartDrawingPosY(), paint);
            }
        };
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            viewWidth = w;
            viewHeight = h;
            super.onSizeChanged(w, h, oldw, oldh);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 06:04

    Works with modification

    You need to set the text view size like this because otherwise setTextSize assumes the value is in SP units:

    setTextSize(TypedValue.COMPLEX_UNIT_PX, trySize);
    

    And you needed to explicitly add this code.

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        refitText(this.getText().toString(), parentWidth);
    }
    
    0 讨论(0)
提交回复
热议问题