API低于26时,如何用Java实现TextView自动适配指定宽度单行显示?
Hey there! I totally get how tricky this can be—API 26 introduced the handy autoSizeTextType attributes, but getting the same behavior back to Lollipop requires a bit of manual work. Let me walk you through two solid, Java-based solutions that get the job done.
Approach 1: Custom Auto-Resize TextView (Best for Reusability)
Creating a custom TextView encapsulates all the resize logic, so you can reuse it across your app without repeating code. Here's a complete implementation:
public class AutoResizeSingleLineTextView extends TextView { // Adjust these values to match your app's design requirements private static final float MIN_TEXT_SIZE_SP = 12f; private static final float MAX_TEXT_SIZE_SP = 48f; public AutoResizeSingleLineTextView(Context context) { super(context); init(); } public AutoResizeSingleLineTextView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public AutoResizeSingleLineTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setSingleLine(true); setEllipsize(null); // We'll resize text to fit fully, no ellipsis needed // Start with maximum allowed text size setTextSize(TypedValue.COMPLEX_UNIT_SP, MAX_TEXT_SIZE_SP); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { resizeTextToFitAvailableWidth(); } } @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); resizeTextToFitAvailableWidth(); } private void resizeTextToFitAvailableWidth() { int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight(); if (availableWidth <= 0) return; Paint textPaint = getPaint(); float currentTextSizePx = getTextSize(); float minTextSizePx = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, MIN_TEXT_SIZE_SP, getResources().getDisplayMetrics() ); String text = getText().toString(); if (text.isEmpty()) return; float textWidth = textPaint.measureText(text); // Shrink text size until it fits or hits the minimum while (textWidth > availableWidth && currentTextSizePx > minTextSizePx) { currentTextSizePx -= 1f; textPaint.setTextSize(currentTextSizePx); textWidth = textPaint.measureText(text); } // Ensure we don't go below the minimum size currentTextSizePx = Math.max(currentTextSizePx, minTextSizePx); setTextSize(TypedValue.COMPLEX_UNIT_PX, currentTextSizePx); } }
How to Use It
Just replace your regular TextView in layouts with this custom class:
<com.yourpackage.AutoResizeSingleLineTextView android:layout_width="200dp" <!-- Fixed width is key here --> android:layout_height="wrap_content" android:text="Your long text that needs resizing" />
Approach 2: Dynamic Resizing in Code (For One-Off Use Cases)
If you don't want to create a custom View, you can add the resize logic directly to your Activity/Fragment. This works great for single instances of TextView:
private void resizeTextViewToFitSingleLine(TextView textView) { int availableWidth = textView.getWidth() - textView.getPaddingLeft() - textView.getPaddingRight(); // If the view hasn't been measured yet, wait for layout to complete if (availableWidth <= 0) { textView.post(() -> resizeTextViewToFitSingleLine(textView)); return; } Paint paint = textView.getPaint(); DisplayMetrics metrics = getResources().getDisplayMetrics(); float maxTextSizePx = textView.getTextSize(); float minTextSizePx = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 12f, // Minimum size in SP metrics ); String text = textView.getText().toString(); if (text.isEmpty()) return; float textWidth = paint.measureText(text); float currentTextSize = maxTextSizePx; // Shrink until text fits or we hit the minimum while (textWidth > availableWidth && currentTextSize > minTextSizePx) { currentTextSize -= 1f; paint.setTextSize(currentTextSize); textWidth = paint.measureText(text); } textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, Math.max(currentTextSize, minTextSizePx)); }
When to Call This Method
Make sure to call it after the TextView has been laid out—for example, in onResume() or using view.post():
@Override protected void onResume() { super.onResume(); TextView myTextView = findViewById(R.id.my_text_view); resizeTextViewToFitSingleLine(myTextView); }
Key Notes for Both Approaches
- Fixed Width Requirement: This logic only works if your TextView has a fixed width (e.g.,
match_parent, specificdpvalue). If it'swrap_content, there's no target width to fit against. - Screen Rotation: If your app supports screen rotation, you'll need to re-trigger the resize logic (the custom View handles this automatically via
onLayout()). - Performance: The loop to shrink text is lightweight, but avoid using it on hundreds of TextViews at once—for large lists, consider optimizing by pre-calculating sizes where possible.
内容的提问来源于stack exchange,提问作者Aden Diamond

