I'm trying to create a method for resizing multi-line text in a TextView
such that it fits within the bounds (both the X and Y dimensions) of the TextView
.
我正在尝试创建一种方法来调整TextView中的多行文本的大小,使其适合TextView的边界(X和Y维度)。
At present, I have something, but all it does is resize the text such that just the first letter/character of the text fills the dimensions of the TextView
(i.e. only the first letter is viewable, and it's huge). I need it to fit all the lines of the text within the bounds of the TextView.
目前,我有一些东西,但它只是调整文本的大小,使文本的第一个字母/字符填充TextView的尺寸(即只有第一个字母是可见的,而且它是巨大的)。我需要它来适应TextView边界内的所有文本行。
Here is what I have so far:
这是我到目前为止:
public static void autoScaleTextViewTextToHeight(TextView tv)
{
final float initSize = tv.getTextSize();
//get the width of the view's back image (unscaled)....
float minViewHeight;
if(tv.getBackground()!=null)
{
minViewHeight = tv.getBackground().getIntrinsicHeight();
}
else
{
minViewHeight = 10f;//some min.
}
final float maxViewHeight = tv.getHeight() - (tv.getPaddingBottom()+tv.getPaddingTop())-12;// -12 just to be sure
final String s = tv.getText().toString();
//System.out.println(""+tv.getPaddingTop()+"/"+tv.getPaddingBottom());
if(minViewHeight >0 && maxViewHeight >2)
{
Rect currentBounds = new Rect();
tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds);
//System.out.println(""+initSize);
//System.out.println(""+maxViewHeight);
//System.out.println(""+(currentBounds.height()));
float resultingSize = 1;
while(currentBounds.height() < maxViewHeight)
{
resultingSize ++;
tv.setTextSize(resultingSize);
tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds);
//System.out.println(""+(currentBounds.height()+tv.getPaddingBottom()+tv.getPaddingTop()));
//System.out.println("Resulting: "+resultingSize);
}
if(currentBounds.height()>=maxViewHeight)
{
//just to be sure, reduce the value
tv.setTextSize(resultingSize-1);
}
}
}
I think the problem is in the use of tv.getPaint().getTextBounds(...)
. It always returns small numbers for the text bounds... small relative to the tv.getWidth()
and tv.getHeight()
values... even if the text size is far larger than the width or height of the TextView
.
我认为问题在于使用tv.getPaint()。getTextBounds(...)。它总是返回文本边界的小数字...相对于tv.getWidth()和tv.getHeight()值的小...即使文本大小远远大于TextView的宽度或高度。
14 个解决方案
#1
20
The AutofitTextView library from MavenCentral handles this nicely. The source hosted on Github(1k+ stars) at https://github.com/grantland/android-autofittextview
MavenCentral的AutofitTextView库很好地处理了这个问题。来自Github(1k +星)的源代码位于https://github.com/grantland/android-autofittextview
Add the following to your app/build.gradle
将以下内容添加到app / build.gradle中
repositories {
mavenCentral()
}
dependencies {
compile 'me.grantland:autofittextview:0.2.+'
}
Enable any View extending TextView in code:
在代码中启用任何View扩展TextView:
AutofitHelper.create(textView);
Enable any View extending TextView in XML:
启用任何以XML格式扩展TextView的View:
<me.grantland.widget.AutofitLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
</me.grantland.widget.AutofitLayout>
Use the built in Widget in code or XML:
在代码或XML中使用内置的Widget:
<me.grantland.widget.AutofitTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
#2
3
I was able to answer my own question using the following code (see below), but my solution was very specific to the application. For instance, this will probably only look good and/or work for a TextView sized to approx. 1/2 the screen (with also a 40px top margin and 20px side margins... no bottom margin).
我能够使用以下代码回答我自己的问题(见下文),但我的解决方案非常特定于应用程序。例如,这可能只是看起来很好和/或适用于大小约为的TextView。屏幕1/2(同时还有40px的上边距和20px的边距......没有底边距)。
The using this approach though, you can create your own similar implementation. The static method basically just looks at the number of characters and determines a scaling factor to apply to the TextView's text size, and then incrementally increases the text size until the overall height (an estimated height -- using the width of the text, the text height, and the width of the TextView) is just below that of the TextView. The parameters necessary to determine the scaling factor (i.e. the if/else if statements) were set by guess-and-check. You'll likely have to play around with the numbers to make it work for your particular application.
但是,使用这种方法,您可以创建自己的类似实现。静态方法基本上只查看字符数并确定应用于TextView文本大小的缩放因子,然后逐渐增加文本大小直到整体高度(估计高度 - 使用文本的宽度,文本高度和TextView的宽度刚好低于TextView的宽度。确定缩放因子所需的参数(即if / else if语句)是通过猜测和检查来设置的。您可能需要使用这些数字来使其适用于您的特定应用程序。
This isn't the most elegant solution, though it was easy to code and it works for me. Does anyone have a better approach?
这不是最优雅的解决方案,虽然它很容易编码,但它对我有用。有没有人有更好的方法?
public static void autoScaleTextViewTextToHeight(final TextView tv, String s)
{
float currentWidth=tv.getPaint().measureText(s);
int scalingFactor = 0;
final int characters = s.length();
//scale based on # of characters in the string
if(characters<5)
{
scalingFactor = 1;
}
else if(characters>=5 && characters<10)
{
scalingFactor = 2;
}
else if(characters>=10 && characters<15)
{
scalingFactor = 3;
}
else if(characters>=15 && characters<20)
{
scalingFactor = 3;
}
else if(characters>=20 && characters<25)
{
scalingFactor = 3;
}
else if(characters>=25 && characters<30)
{
scalingFactor = 3;
}
else if(characters>=30 && characters<35)
{
scalingFactor = 3;
}
else if(characters>=35 && characters<40)
{
scalingFactor = 3;
}
else if(characters>=40 && characters<45)
{
scalingFactor = 3;
}
else if(characters>=45 && characters<50)
{
scalingFactor = 3;
}
else if(characters>=50 && characters<55)
{
scalingFactor = 3;
}
else if(characters>=55 && characters<60)
{
scalingFactor = 3;
}
else if(characters>=60 && characters<65)
{
scalingFactor = 3;
}
else if(characters>=65 && characters<70)
{
scalingFactor = 3;
}
else if(characters>=70 && characters<75)
{
scalingFactor = 3;
}
else if(characters>=75)
{
scalingFactor = 5;
}
//System.out.println(((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor));
//the +scalingFactor is important... increase this if nec. later
while((((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor)*tv.getTextSize())<tv.getHeight())
{
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, tv.getTextSize()+0.25f);
currentWidth=tv.getPaint().measureText(s);
//System.out.println(((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor));
}
tv.setText(s);
}
Thanks.
#3
3
I had the same problem and wrote a class that seems to work for me. Basically, I used a static layout to draw the text in a separate canvas and remeasure until I find a font size that fits. You can see the class posted in the topic below. I hope it helps.
我有同样的问题,写了一个似乎适合我的课程。基本上,我使用静态布局在单独的画布中绘制文本并重新测量,直到找到适合的字体大小。您可以在下面的主题中看到该课程。我希望它有所帮助。
Auto Scale TextView Text to Fit within Bounds
自动缩放TextView文本以适应界限
#4
3
Stumbled upon this whilst looking for a solution myself... I'd tried all the other solutions out there that I could see on stack overflow etc but none really worked so I wrote my own.
在我自己寻找解决方案的同时偶然发现了...我已经尝试了所有其他解决方案,我可以在堆栈溢出等上看到但是没有真正有效,所以我自己写了。
Basically by wrapping the text view in a custom linear layout I've been able to successfully measure the text properly by ensuring it is measured with a fixed width.
基本上,通过将文本视图包装在自定义线性布局中,我已经能够通过确保以固定宽度进行测量来成功地正确测量文本。
<!-- TextView wrapped in the custom LinearLayout that expects one child TextView -->
<!-- This view should specify the size you would want the text view to be displayed at -->
<com.custom.ResizeView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_weight="1"
android:orientation="horizontal" >
<TextView
android:id="@+id/CustomTextView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
</com.custom.ResizeView>
Then the linear layout code
然后是线性布局代码
public class ResizeView extends LinearLayout {
public ResizeView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ResizeView(Context context) {
super(context);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// oldWidth used as a fixed width when measuring the size of the text
// view at different font sizes
final int oldWidth = getMeasuredWidth() - getPaddingBottom() - getPaddingTop();
final int oldHeight = getMeasuredHeight() - getPaddingLeft() - getPaddingRight();
// Assume we only have one child and it is the text view to scale
TextView textView = (TextView) getChildAt(0);
// This is the maximum font size... we iterate down from this
// I've specified the sizes in pixels, but sp can be used, just modify
// the call to setTextSize
float size = getResources().getDimensionPixelSize(R.dimen.solutions_view_max_font_size);
for (int textViewHeight = Integer.MAX_VALUE; textViewHeight > oldHeight; size -= 0.1f) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
// measure the text views size using a fixed width and an
// unspecified height - the unspecified height means measure
// returns the textviews ideal height
textView.measure(MeasureSpec.makeMeasureSpec(oldWidth, MeasureSpec.EXACTLY), MeasureSpec.UNSPECIFIED);
textViewHeight = textView.getMeasuredHeight();
}
}
}
Hope this helps someone.
希望这有助于某人。
#5
3
I have played with this for quite some time, trying to get my font sizes correct on a wide variety of 7" tablets (kindle fire, Nexus7, and some inexpensive ones in China with low-res screens) and devices.
我已经玩了很长一段时间了,试图在各种7英寸平板电脑(点燃火,Nexus7,以及中国的一些廉价的低分辨率屏幕)和设备上使我的字体大小正确。
The approach that finally worked for me is as follows. The "32" is an arbitrary factor that basically gives about 70+ characters across a 7" tablet horizontal line, which is a font size I was looking for. Adjust accordingly.
最终对我有用的方法如下。 “32”是一个任意因素,基本上在7“平板电脑水平线上提供了大约70个以上的字符,这是我正在寻找的字体大小。相应地调整。
textView.setTextSize(getFontSize(activity));
public static int getFontSize (Activity activity) {
DisplayMetrics dMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dMetrics);
// lets try to get them back a font size realtive to the pixel width of the screen
final float WIDE = activity.getResources().getDisplayMetrics().widthPixels;
int valueWide = (int)(WIDE / 32.0f / (dMetrics.scaledDensity));
return valueWide;
}
#6
2
maybe try setting setHoriztonallyScrolling() to true before taking text measurements so that the textView doesn't try to layout your text on multiple lines
也许尝试在进行文本测量之前将setHoriztonallyScrolling()设置为true,以便textView不会尝试在多行上布局文本
#7
2
One way would be to specify different sp dimensions for each of the generalized screen sizes. For instance, provide 8sp for small screens, 12sp for normal screens, 16 sp for large and 20 sp for xlarge. Then just have your layouts refer to @dimen text_size or whatever and you can rest assured, as density is taken care of via the sp unit. See the following link for more info on this approach.
一种方法是为每个通用屏幕尺寸指定不同的sp尺寸。例如,为小屏幕提供8sp,为普通屏幕提供12sp,为大屏幕提供16sp,为xlarge提供20sp。然后让你的布局引用@dimen text_size或其他任何你可以放心,因为密度是通过sp单位处理的。有关此方法的详细信息,请参阅以下链接。
http://www.developer.android.com/guide/topics/resources/more-resources.html#Dimension
I must note, however, that supporting more languages means more work during the testing phase, especially if you're interested in keeping text on one line, as some languages have much longer words. In that case, make a dimens.xml file in the values-de-large folder, for example, and tweak the value manually. Hope this helps.
但是,我必须注意,支持更多语言意味着在测试阶段会有更多的工作,特别是如果你有兴趣将文本保存在一行上,因为某些语言的单词长得多。在这种情况下,例如,在values-de-large文件夹中创建一个dimens.xml文件,并手动调整该值。希望这可以帮助。
#8
2
New since Android O:
Android O以来的新功能:
https://developer.android.com/preview/features/autosizing-textview.html
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoSizeTextType="uniform"
android:autoSi*TextSize="12sp"
android:autoSizeMaxTextSize="100sp"
android:autoSizeStepGranularity="2sp"
/>
#9
1
Here is a solution that I created based on some other feedback. This solution allows you to set the size of the text in XML which will be the max size and it will adjust itself to fit the view height. Size Adjusting TextView
这是我根据其他一些反馈创建的解决方案。此解决方案允许您以XML格式设置文本的大小,该大小将是最大大小,并且它将自行调整以适合视图高度。大小调整TextView
private float findNewTextSize(int width, int height, CharSequence text) {
TextPaint textPaint = new TextPaint(getPaint());
float targetTextSize = textPaint.getTextSize();
int textHeight = getTextHeight(text, textPaint, width, targetTextSize);
while(textHeight > height && targetTextSize > mMinTextSize) {
targetTextSize = Math.max(targetTextSize - 1, mMinTextSize);
textHeight = getTextHeight(text, textPaint, width, targetTextSize);
}
return targetTextSize;
}
private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) {
paint.setTextSize(textSize);
StaticLayout layout = new StaticLayout(source, paint, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true);
return layout.getHeight();
}
#10
0
If your only requirement is to have the text automatically split and continue in the next line and the height is not important then just have it like this.
如果您唯一的要求是让文本自动拆分并在下一行中继续,并且高度不重要那么就像这样。
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxEms="integer"
android:width="integer"/>
This will have your TextView wrap to it's content vertically depending on your maxEms value.
这将根据您的maxEms值将TextView垂直包装到其内容中。
#11
0
Check if my solution helps you:
检查我的解决方案是否有助于您
Auto Scale TextView Text to Fit within Bounds
自动缩放TextView文本以适应界限
#12
0
I found that this worked well for me. see: https://play.google.com/store/apps/details?id=au.id.rupert.chauffeurs_name_board&hl=en
我发现这对我来说效果很好。请参阅:https://play.google.com/store/apps/details?id = au.id.rupert.chauffeurs_name_board&hl = en
Source Code at http://www.rupert.id.au/chauffeurs_name_board/verson2.php
源代码,网址为http://www.rupert.id.au/chauffeurs_name_board/verson2.php
http://catchthecows.com/?p=72 and https://github.com/catchthecows/BigTextButton
http://catchthecows.com/?p=72和https://github.com/catchthecows/BigTextButton
#13
0
This is based on mattmook's answer. It worked well on some devices, but not on all. I moved the resizing to the measuring step, made the maximum font size a custom attribute, took margins into account, and extended FrameLayout instead of LineairLayout.
这是基于mattmook的答案。它在某些设备上运行良好,但并非全部。我将调整大小移动到测量步骤,使最大字体大小成为自定义属性,考虑边距,并扩展FrameLayout而不是LineairLayout。
public class ResizeView extends FrameLayout {
protected float max_font_size;
public ResizeView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.ResizeView,
0, 0);
max_font_size = a.getDimension(R.styleable.ResizeView_maxFontSize, 30.0f);
}
public ResizeView(Context context) {
super(context);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
// Use the parent's code for the first measure
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Assume we only have one child and it is the text view to scale
final TextView textView = (TextView) getChildAt(0);
// Check if the default measure resulted in a fitting textView
LayoutParams childLayout = (LayoutParams) textView.getLayoutParams();
final int textHeightAvailable = getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - childLayout.topMargin - childLayout.bottomMargin;
int textViewHeight = textView.getMeasuredHeight();
if (textViewHeight < textHeightAvailable) {
return;
}
final int textWidthSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight() - childLayout.leftMargin - childLayout.rightMargin,
MeasureSpec.EXACTLY);
final int textHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
for (float size = max_font_size; size >= 1.05f; size-=0.1f) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
textView.measure(textWidthSpec, textHeightSpec);
textViewHeight = textView.getMeasuredHeight();
if (textViewHeight <= textHeightAvailable) {
break;
}
}
}
}
And this in attrs.xml:
这在attrs.xml中:
<declare-styleable name="ResizeView">
<attr name="maxFontSize" format="reference|dimension"/>
</declare-styleable>
And finally used like this:
最后像这样使用:
<PACKAGE_NAME.ui.ResizeView xmlns:custom="http://schemas.android.com/apk/res/PACKAGE_NAME"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="start|center_vertical"
android:padding="5dp"
custom:maxFontSize="@dimen/normal_text">
<TextView android:id="@+id/tabTitle2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</PACKAGE_NAME.ui.ResizeView>
#14
0
Try this...
tv.setText("Give a very large text anc check , this xample is very usefull");
countLine=tv.getLineHeight();
System.out.println("LineCount " + countLine);
if (countLine>=40){
tv.setTextSize(15);
}
#1
20
The AutofitTextView library from MavenCentral handles this nicely. The source hosted on Github(1k+ stars) at https://github.com/grantland/android-autofittextview
MavenCentral的AutofitTextView库很好地处理了这个问题。来自Github(1k +星)的源代码位于https://github.com/grantland/android-autofittextview
Add the following to your app/build.gradle
将以下内容添加到app / build.gradle中
repositories {
mavenCentral()
}
dependencies {
compile 'me.grantland:autofittextview:0.2.+'
}
Enable any View extending TextView in code:
在代码中启用任何View扩展TextView:
AutofitHelper.create(textView);
Enable any View extending TextView in XML:
启用任何以XML格式扩展TextView的View:
<me.grantland.widget.AutofitLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
</me.grantland.widget.AutofitLayout>
Use the built in Widget in code or XML:
在代码或XML中使用内置的Widget:
<me.grantland.widget.AutofitTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
#2
3
I was able to answer my own question using the following code (see below), but my solution was very specific to the application. For instance, this will probably only look good and/or work for a TextView sized to approx. 1/2 the screen (with also a 40px top margin and 20px side margins... no bottom margin).
我能够使用以下代码回答我自己的问题(见下文),但我的解决方案非常特定于应用程序。例如,这可能只是看起来很好和/或适用于大小约为的TextView。屏幕1/2(同时还有40px的上边距和20px的边距......没有底边距)。
The using this approach though, you can create your own similar implementation. The static method basically just looks at the number of characters and determines a scaling factor to apply to the TextView's text size, and then incrementally increases the text size until the overall height (an estimated height -- using the width of the text, the text height, and the width of the TextView) is just below that of the TextView. The parameters necessary to determine the scaling factor (i.e. the if/else if statements) were set by guess-and-check. You'll likely have to play around with the numbers to make it work for your particular application.
但是,使用这种方法,您可以创建自己的类似实现。静态方法基本上只查看字符数并确定应用于TextView文本大小的缩放因子,然后逐渐增加文本大小直到整体高度(估计高度 - 使用文本的宽度,文本高度和TextView的宽度刚好低于TextView的宽度。确定缩放因子所需的参数(即if / else if语句)是通过猜测和检查来设置的。您可能需要使用这些数字来使其适用于您的特定应用程序。
This isn't the most elegant solution, though it was easy to code and it works for me. Does anyone have a better approach?
这不是最优雅的解决方案,虽然它很容易编码,但它对我有用。有没有人有更好的方法?
public static void autoScaleTextViewTextToHeight(final TextView tv, String s)
{
float currentWidth=tv.getPaint().measureText(s);
int scalingFactor = 0;
final int characters = s.length();
//scale based on # of characters in the string
if(characters<5)
{
scalingFactor = 1;
}
else if(characters>=5 && characters<10)
{
scalingFactor = 2;
}
else if(characters>=10 && characters<15)
{
scalingFactor = 3;
}
else if(characters>=15 && characters<20)
{
scalingFactor = 3;
}
else if(characters>=20 && characters<25)
{
scalingFactor = 3;
}
else if(characters>=25 && characters<30)
{
scalingFactor = 3;
}
else if(characters>=30 && characters<35)
{
scalingFactor = 3;
}
else if(characters>=35 && characters<40)
{
scalingFactor = 3;
}
else if(characters>=40 && characters<45)
{
scalingFactor = 3;
}
else if(characters>=45 && characters<50)
{
scalingFactor = 3;
}
else if(characters>=50 && characters<55)
{
scalingFactor = 3;
}
else if(characters>=55 && characters<60)
{
scalingFactor = 3;
}
else if(characters>=60 && characters<65)
{
scalingFactor = 3;
}
else if(characters>=65 && characters<70)
{
scalingFactor = 3;
}
else if(characters>=70 && characters<75)
{
scalingFactor = 3;
}
else if(characters>=75)
{
scalingFactor = 5;
}
//System.out.println(((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor));
//the +scalingFactor is important... increase this if nec. later
while((((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor)*tv.getTextSize())<tv.getHeight())
{
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, tv.getTextSize()+0.25f);
currentWidth=tv.getPaint().measureText(s);
//System.out.println(((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor));
}
tv.setText(s);
}
Thanks.
#3
3
I had the same problem and wrote a class that seems to work for me. Basically, I used a static layout to draw the text in a separate canvas and remeasure until I find a font size that fits. You can see the class posted in the topic below. I hope it helps.
我有同样的问题,写了一个似乎适合我的课程。基本上,我使用静态布局在单独的画布中绘制文本并重新测量,直到找到适合的字体大小。您可以在下面的主题中看到该课程。我希望它有所帮助。
Auto Scale TextView Text to Fit within Bounds
自动缩放TextView文本以适应界限
#4
3
Stumbled upon this whilst looking for a solution myself... I'd tried all the other solutions out there that I could see on stack overflow etc but none really worked so I wrote my own.
在我自己寻找解决方案的同时偶然发现了...我已经尝试了所有其他解决方案,我可以在堆栈溢出等上看到但是没有真正有效,所以我自己写了。
Basically by wrapping the text view in a custom linear layout I've been able to successfully measure the text properly by ensuring it is measured with a fixed width.
基本上,通过将文本视图包装在自定义线性布局中,我已经能够通过确保以固定宽度进行测量来成功地正确测量文本。
<!-- TextView wrapped in the custom LinearLayout that expects one child TextView -->
<!-- This view should specify the size you would want the text view to be displayed at -->
<com.custom.ResizeView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_weight="1"
android:orientation="horizontal" >
<TextView
android:id="@+id/CustomTextView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
</com.custom.ResizeView>
Then the linear layout code
然后是线性布局代码
public class ResizeView extends LinearLayout {
public ResizeView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ResizeView(Context context) {
super(context);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// oldWidth used as a fixed width when measuring the size of the text
// view at different font sizes
final int oldWidth = getMeasuredWidth() - getPaddingBottom() - getPaddingTop();
final int oldHeight = getMeasuredHeight() - getPaddingLeft() - getPaddingRight();
// Assume we only have one child and it is the text view to scale
TextView textView = (TextView) getChildAt(0);
// This is the maximum font size... we iterate down from this
// I've specified the sizes in pixels, but sp can be used, just modify
// the call to setTextSize
float size = getResources().getDimensionPixelSize(R.dimen.solutions_view_max_font_size);
for (int textViewHeight = Integer.MAX_VALUE; textViewHeight > oldHeight; size -= 0.1f) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
// measure the text views size using a fixed width and an
// unspecified height - the unspecified height means measure
// returns the textviews ideal height
textView.measure(MeasureSpec.makeMeasureSpec(oldWidth, MeasureSpec.EXACTLY), MeasureSpec.UNSPECIFIED);
textViewHeight = textView.getMeasuredHeight();
}
}
}
Hope this helps someone.
希望这有助于某人。
#5
3
I have played with this for quite some time, trying to get my font sizes correct on a wide variety of 7" tablets (kindle fire, Nexus7, and some inexpensive ones in China with low-res screens) and devices.
我已经玩了很长一段时间了,试图在各种7英寸平板电脑(点燃火,Nexus7,以及中国的一些廉价的低分辨率屏幕)和设备上使我的字体大小正确。
The approach that finally worked for me is as follows. The "32" is an arbitrary factor that basically gives about 70+ characters across a 7" tablet horizontal line, which is a font size I was looking for. Adjust accordingly.
最终对我有用的方法如下。 “32”是一个任意因素,基本上在7“平板电脑水平线上提供了大约70个以上的字符,这是我正在寻找的字体大小。相应地调整。
textView.setTextSize(getFontSize(activity));
public static int getFontSize (Activity activity) {
DisplayMetrics dMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dMetrics);
// lets try to get them back a font size realtive to the pixel width of the screen
final float WIDE = activity.getResources().getDisplayMetrics().widthPixels;
int valueWide = (int)(WIDE / 32.0f / (dMetrics.scaledDensity));
return valueWide;
}
#6
2
maybe try setting setHoriztonallyScrolling() to true before taking text measurements so that the textView doesn't try to layout your text on multiple lines
也许尝试在进行文本测量之前将setHoriztonallyScrolling()设置为true,以便textView不会尝试在多行上布局文本
#7
2
One way would be to specify different sp dimensions for each of the generalized screen sizes. For instance, provide 8sp for small screens, 12sp for normal screens, 16 sp for large and 20 sp for xlarge. Then just have your layouts refer to @dimen text_size or whatever and you can rest assured, as density is taken care of via the sp unit. See the following link for more info on this approach.
一种方法是为每个通用屏幕尺寸指定不同的sp尺寸。例如,为小屏幕提供8sp,为普通屏幕提供12sp,为大屏幕提供16sp,为xlarge提供20sp。然后让你的布局引用@dimen text_size或其他任何你可以放心,因为密度是通过sp单位处理的。有关此方法的详细信息,请参阅以下链接。
http://www.developer.android.com/guide/topics/resources/more-resources.html#Dimension
I must note, however, that supporting more languages means more work during the testing phase, especially if you're interested in keeping text on one line, as some languages have much longer words. In that case, make a dimens.xml file in the values-de-large folder, for example, and tweak the value manually. Hope this helps.
但是,我必须注意,支持更多语言意味着在测试阶段会有更多的工作,特别是如果你有兴趣将文本保存在一行上,因为某些语言的单词长得多。在这种情况下,例如,在values-de-large文件夹中创建一个dimens.xml文件,并手动调整该值。希望这可以帮助。
#8
2
New since Android O:
Android O以来的新功能:
https://developer.android.com/preview/features/autosizing-textview.html
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoSizeTextType="uniform"
android:autoSi*TextSize="12sp"
android:autoSizeMaxTextSize="100sp"
android:autoSizeStepGranularity="2sp"
/>
#9
1
Here is a solution that I created based on some other feedback. This solution allows you to set the size of the text in XML which will be the max size and it will adjust itself to fit the view height. Size Adjusting TextView
这是我根据其他一些反馈创建的解决方案。此解决方案允许您以XML格式设置文本的大小,该大小将是最大大小,并且它将自行调整以适合视图高度。大小调整TextView
private float findNewTextSize(int width, int height, CharSequence text) {
TextPaint textPaint = new TextPaint(getPaint());
float targetTextSize = textPaint.getTextSize();
int textHeight = getTextHeight(text, textPaint, width, targetTextSize);
while(textHeight > height && targetTextSize > mMinTextSize) {
targetTextSize = Math.max(targetTextSize - 1, mMinTextSize);
textHeight = getTextHeight(text, textPaint, width, targetTextSize);
}
return targetTextSize;
}
private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) {
paint.setTextSize(textSize);
StaticLayout layout = new StaticLayout(source, paint, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true);
return layout.getHeight();
}
#10
0
If your only requirement is to have the text automatically split and continue in the next line and the height is not important then just have it like this.
如果您唯一的要求是让文本自动拆分并在下一行中继续,并且高度不重要那么就像这样。
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxEms="integer"
android:width="integer"/>
This will have your TextView wrap to it's content vertically depending on your maxEms value.
这将根据您的maxEms值将TextView垂直包装到其内容中。
#11
0
Check if my solution helps you:
检查我的解决方案是否有助于您
Auto Scale TextView Text to Fit within Bounds
自动缩放TextView文本以适应界限
#12
0
I found that this worked well for me. see: https://play.google.com/store/apps/details?id=au.id.rupert.chauffeurs_name_board&hl=en
我发现这对我来说效果很好。请参阅:https://play.google.com/store/apps/details?id = au.id.rupert.chauffeurs_name_board&hl = en
Source Code at http://www.rupert.id.au/chauffeurs_name_board/verson2.php
源代码,网址为http://www.rupert.id.au/chauffeurs_name_board/verson2.php
http://catchthecows.com/?p=72 and https://github.com/catchthecows/BigTextButton
http://catchthecows.com/?p=72和https://github.com/catchthecows/BigTextButton
#13
0
This is based on mattmook's answer. It worked well on some devices, but not on all. I moved the resizing to the measuring step, made the maximum font size a custom attribute, took margins into account, and extended FrameLayout instead of LineairLayout.
这是基于mattmook的答案。它在某些设备上运行良好,但并非全部。我将调整大小移动到测量步骤,使最大字体大小成为自定义属性,考虑边距,并扩展FrameLayout而不是LineairLayout。
public class ResizeView extends FrameLayout {
protected float max_font_size;
public ResizeView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.ResizeView,
0, 0);
max_font_size = a.getDimension(R.styleable.ResizeView_maxFontSize, 30.0f);
}
public ResizeView(Context context) {
super(context);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
// Use the parent's code for the first measure
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Assume we only have one child and it is the text view to scale
final TextView textView = (TextView) getChildAt(0);
// Check if the default measure resulted in a fitting textView
LayoutParams childLayout = (LayoutParams) textView.getLayoutParams();
final int textHeightAvailable = getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - childLayout.topMargin - childLayout.bottomMargin;
int textViewHeight = textView.getMeasuredHeight();
if (textViewHeight < textHeightAvailable) {
return;
}
final int textWidthSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight() - childLayout.leftMargin - childLayout.rightMargin,
MeasureSpec.EXACTLY);
final int textHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
for (float size = max_font_size; size >= 1.05f; size-=0.1f) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
textView.measure(textWidthSpec, textHeightSpec);
textViewHeight = textView.getMeasuredHeight();
if (textViewHeight <= textHeightAvailable) {
break;
}
}
}
}
And this in attrs.xml:
这在attrs.xml中:
<declare-styleable name="ResizeView">
<attr name="maxFontSize" format="reference|dimension"/>
</declare-styleable>
And finally used like this:
最后像这样使用:
<PACKAGE_NAME.ui.ResizeView xmlns:custom="http://schemas.android.com/apk/res/PACKAGE_NAME"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="start|center_vertical"
android:padding="5dp"
custom:maxFontSize="@dimen/normal_text">
<TextView android:id="@+id/tabTitle2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</PACKAGE_NAME.ui.ResizeView>
#14
0
Try this...
tv.setText("Give a very large text anc check , this xample is very usefull");
countLine=tv.getLineHeight();
System.out.println("LineCount " + countLine);
if (countLine>=40){
tv.setTextSize(15);
}