You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API低于26时,如何用Java实现TextView自动适配指定宽度单行显示?

Fixing TextView Auto-Resize for Single-Line Display (API 21+)

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, specific dp value). If it's wrap_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:01:54