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