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整列ループ内で の修正が必要です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 に答える