自动缩放视图文本,完全适合视图内部

时间:2015-03-30 11:22:39

标签: java android button text view

我最近在SO上阅读了很多关于自动调整文本大小的线程,以便填充其视图,这是四年前开始的最全面的this one。还在继续(虽然它涉及必须包装的文本,这不是我在下面的代码中所做的)。对于刚接触Java(和Android)的人来说,一些答案的剪切复杂性是令人难以置信的,所以我抓住了最简单的一些,posted by Sander就在几个月前。我已根据自己的需要对其进行了重新设计,但为了使其正常工作,我必须在计算中包含屏幕密度,而我不明白为什么。我希望有人可以向我解释,因为它让我疯狂。 (我无法回复Sander的帖子,因为我在SO上还是新手。)

我已经完整地发布了下面的代码,包括我在放入脑中时所提出的所有评论,以防它对其他人有用。 (抱歉由于我的经验不足导致错误或效率低下。)

import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.WindowManager;
import android.widget.Button;

/*--------------------------------------------------------------------------------------------------
 * Defines a subclass of Button, myButton, that has a "resize" method.  The text size is set so that
 * the desired button text fits inside the rectangles formed by dividing the screen into a grid of
 * rows and columns (which are a grid of buttons in the original application).  Note that all of the
 * text will appear on a single line, rather than wrapping.
 *
 * Example usage:
 * (Button) findViewById(R.id.button)).setText(text);
 * ((myButton) findViewById(R.id.button)).resize(text, 2, 3);
 *
 * Make sure "Button" is replaced by "myButton" in the .xml and in any casting in the code that uses
 * the resize method.
 *
 * "Button" could easily be substituted for other views and the dimensions of the desired rectangle
 * could be provided explicitly rather than calculated.
 *------------------------------------------------------------------------------------------------*/

public class myButton extends Button {

    // Inherit constructor from the Button superclass
    public myButton (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void resize (String text, int rows, int cols) {

        // Get the screen's physical dimensions, in pixels
        DisplayMetrics metrics = new DisplayMetrics();
        ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metrics);
        float width = metrics.widthPixels;
        float height = metrics.heightPixels;
        float density = metrics.density; // px = dp * density.  Used in the calculations, below.

        // Modify the width and height to get the effective size of the rectangle that text needs to
        // fit inside.  The "fraction" variable reduces the rectangle further (e.g. to 90%) to allow
        // for error or margins/padding.
        float fraction = 0.90f;
        float effectiveWidth = ( width / cols ) * fraction ;
        float effectiveHeight = ( height / rows ) * fraction ;

        // Calculate how many pixels the text would require if the font size was set to an arbitrary
        // value
        Paint p = new Paint();
        Rect bounds = new Rect();
        int testTextSize = 1000; // Arbitrary, but large enough to reduce round-off errors
        p.setTextSize( testTextSize * density );  // WHY DO I HAVE TO MULTIPLY BY THE DENSITY?
        p.getTextBounds(text,0,text.length(),bounds);

        // Scale the text in each direction so that it would exactly fit in the space available
        float textSizeToFitWidth = testTextSize * ( effectiveWidth / (bounds.width() * density) );  //   WHY DO I HAVE TO MULTIPLY BY THE DENSITY?
        float textSizeToFitHeight = testTextSize * ( effectiveHeight / (bounds.height() * density) );

        // Choose the smaller of these two text sizes, so that the text fits in both directions
        int textSize = (int) Math.min( textSizeToFitWidth, textSizeToFitHeight );

        // Change the text size of the myButton view:
        setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);

    }

}

如果Rect.width()Rect.height()返回dp中的值(是吗?文档不是吗?),我可以理解将它们乘以density,以保留所有内容像素。但是,为什么我必须将testTextSize乘以density(已经是像素?)?

或者它是一个侥幸,计算是错误的,但恰好出现了大致正确的答案,以便它看起来像它的工作?

0 个答案:

没有答案