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

Java 自动缩放视图文字,完全适合内部视图,java,android,button,text,view,Java,Android,Button,Text,View,我最近读了很多关于自动调整文本大小以填充其视图的文章,其中最全面的一篇是四年前开始的,至今仍在继续(尽管它涉及必须换行的文本,这不是我在下面代码中所做的)。对于刚接触Java(和Android)的人来说,一些答案的复杂性令人难以置信,所以就在几个月前,我抓住了其中最简单的一个。我已经根据自己的需要修改了它,但是为了让它正常工作,我不得不在计算中加入屏幕密度,我不明白为什么。我希望有人能给我解释一下,因为我快发疯了。(我无法回复的帖子,因为我还是新手。) 我已经在下面完整地发布了代码,其中包含了我

我最近读了很多关于自动调整文本大小以填充其视图的文章,其中最全面的一篇是四年前开始的,至今仍在继续(尽管它涉及必须换行的文本,这不是我在下面代码中所做的)。对于刚接触Java(和Android)的人来说,一些答案的复杂性令人难以置信,所以就在几个月前,我抓住了其中最简单的一个。我已经根据自己的需要修改了它,但是为了让它正常工作,我不得不在计算中加入屏幕密度,我不明白为什么。我希望有人能给我解释一下,因为我快发疯了。(我无法回复的帖子,因为我还是新手。)

我已经在下面完整地发布了代码,其中包含了我在头脑中直接输入的所有注释,以防对其他人有用。(很抱歉,由于我缺乏经验而导致错误或效率低下。)

如果
Rect.width()
Rect.height()
返回dp中的值(是吗?文档没有说?),我可以理解将它们乘以
密度,以保持所有像素。但是,为什么我必须将
testTextSize
(已经以像素为单位?)乘以
密度


或者这是一次侥幸,计算结果是错误的,但恰好得出了大致正确的答案,因此它看起来是可行的?

我会使用现有的库,比如。我看了一下,但这似乎是一个大锤式的方法,因为我的需要与它的功能相比是多么简单……另外,对API 16之前的“可能有问题”和“在大多数情况下应该可以很好地工作”让我有点担心(另外,我还没有从GitHub学习如何实现东西——在学习曲线上仍然领先我一大步!)
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);

    }

}