2

下面是我在堆栈溢出的某个线程中找到的代码,它减小了字体以适合文本视图中的文本,但我想减小和增加字体以适合文本视图中的文本,这件事还没有完成,搜索很多,帮帮我

public class FontFitTextView extends TextView {

    // Attributes
    private Paint mTestPaint;
    private float defaultTextSize;

    public FontFitTextView(Context context) {
        super(context);
        initialize();
    }

    public FontFitTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    private void initialize() {
        mTestPaint = new Paint();
        mTestPaint.set(this.getPaint());
        defaultTextSize = getTextSize();
    }

    /* Re size the font so the specified text fits in the text box
     * assuming the text box is the specified width.
     */
    private void refitText(String text, int textWidth) {

        if (textWidth <= 0 || text.isEmpty())
            return;

        int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();

        // this is most likely a non-relevant call
        if( targetWidth<=2 )
            return;

        // text already fits with the xml-defined font size?
        mTestPaint.set(this.getPaint());
        mTestPaint.setTextSize(defaultTextSize);
        if(mTestPaint.measureText(text) <= targetWidth) {
            this.setTextSize(TypedValue.COMPLEX_UNIT_PX, defaultTextSize);
            return;
        }

        // adjust text size using binary search for efficiency
        float hi = defaultTextSize;
        float lo = 2;
        final float threshold = 0.5f; // How close we have to be
        while (hi - lo > threshold) {
            float size = (hi + lo) / 2;
            mTestPaint.setTextSize(size);
            if(mTestPaint.measureText(text) >= targetWidth ) 
                hi = size; // too big
            else 
                lo = size; // too small

        }

        // Use lo so that we undershoot rather than overshoot
        this.setTextSize(TypedValue.COMPLEX_UNIT_PX, lo);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int height = getMeasuredHeight();
        refitText(this.getText().toString(), parentWidth);
        this.setMeasuredDimension(parentWidth, height);
    }

    @Override
    protected void onTextChanged(final CharSequence text, final int start,
            final int before, final int after) {
        refitText(text.toString(), this.getWidth());
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (w != oldw || h != oldh) {
            refitText(this.getText().toString(), w);
        }
    }

}
4

1 回答 1

1

实际上,有一些微不足道的错误。如您所见,在您的代码中有检查defaultTextSize,因此文本字体不能比它大,hi在 align 循环内也需要更正,因为它会阻止搜索大小高于defaultTextSize.

因此,使字体变大而不受限制的最终代码如下所示:

public class FontFitTextView extends TextView {

    // Attributes
    private Paint mTestPaint;
    /** 'Initial' text size */
    private float mDefaultTextSize;

    public FontFitTextView(final Context context) {
        super(context);
        initialize();
    }

    public FontFitTextView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    private void initialize() {
        mTestPaint = new Paint();
        mTestPaint.set(this.getPaint());
        mDefaultTextSize = getTextSize();
    }

    /*
     * Re size the font so the specified text fits in the text box
     * assuming the text box is the specified width.
     */
    private void refitText(final String text, final int textWidth) {

        if(textWidth <= 0 || text.isEmpty()) {
            return;
        }

        int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();

        // this is most likely a non-relevant call
        if(targetWidth <= 2) {
            return;
        }

        // text already fits with the xml-defined font size?
        mTestPaint.set(this.getPaint());
        mTestPaint.setTextSize(mDefaultTextSize);

        // adjust text size using binary search for efficiency
        float hi = Math.max(mDefaultTextSize, targetWidth);
        float lo = 2;
        final float threshold = 0.5f; // How close we have to be

        while (hi - lo > threshold) {
            float size = (hi + lo) / 2;
            mTestPaint.setTextSize(size);
            if(mTestPaint.measureText(text) >= targetWidth) {
                hi = size; // too big
            } else {
                lo = size; // too small
            }
        }

        // Use lo so that we undershoot rather than overshoot
        this.setTextSize(TypedValue.COMPLEX_UNIT_PX, lo);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int height = getMeasuredHeight();
        refitText(this.getText().toString(), parentWidth);
        this.setMeasuredDimension(parentWidth, height);
    }

    @Override
    protected void onTextChanged(final CharSequence text, final int start,
                                 final int before, final int after) {
        refitText(text.toString(), this.getWidth());
    }

    @Override
    protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
        if (w != oldw || h != oldh) {
            refitText(this.getText().toString(), w);
        }
    }
}

您可以使用以下 xml 对其进行测试:

<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <com.example.TestApp.FontFitTextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/textView"
        android:layout_centerInParent="true"
        android:text="This text is to be resized." />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:id="@+id/minus_button"
        android:text="-10px"
        android:padding="20dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_toRightOf="@id/minus_button"
        android:id="@+id/plus_button"
        android:text="+10px"
        android:padding="20dp" />
</RelativeLayout>

和活动:

public class MyActivity extends Activity {

    private static final String TAG = "MyActivity";

    TextView mTextView = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Show the layout with the test view
        setContentView(R.layout.main);

        mTextView = (TextView) findViewById(R.id.textView);

        final Button buttonPlus = (Button) findViewById(R.id.plus_button);

        buttonPlus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                changeTextViewSize(10);
            }
        });

        final Button buttonMinus = (Button) findViewById(R.id.minus_button);

        buttonMinus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                changeTextViewSize(-10);
            }
        });
    }

    /**
     * Changes text size by needed delta
     *
     * @param delta in px
     */
    private void changeTextViewSize(final int delta) {
        final ViewGroup.LayoutParams params = mTextView.getLayoutParams();

        params.height += delta;
        params.width += delta;

        mTextView.setLayoutParams(params);
    }
}
于 2013-07-27T08:12:29.870 回答