I'm adding line spacing in my textview which spans multiple lines.
What's the difference between android:lineSpacingExtra and android:lineSpacingMultiplier?
lineSpacingExtra with 2dp worked fine for me but I was wondering what the Multiplier does instead?
The difference is that android:lineSpacingExtra add extra spacing between lines of text of TextView and android:lineSpacingMultiplier work as scale factor for height of line space. in other words, each line height will be height*multiplier + extra
It's rather simple: one is additive and one is multiplicative.
If you have a default line spacing of LINE_SPACING and use:
float x = 2;
float y = 1.5;
setLineSpacing(x, y);
The resulting line spacing will be 1.5*LINE_SPACING + 2
It is important to note that the multiplication happens first! This follows the conventional order of operations (multiplication before addition).
See the docs here: http://developer.android.com/reference/android/widget/TextView.html#setLineSpacing(float, float)
In the future, it might be wise to look up such documentation first. ;)
Related
can I know what is the difference between lineHeight and lineSpacingExtra in android xml. I tried to compare both, but I got the different result (I need the lineHeight function, however it is only supported in API 28).
Here is part of my code:
left:
android:textSize="14sp"
android:lineSpacingExtra="6dp"
right:
android:textSize="14sp"
android:lineHeight="20dp"
Result:
Any solution for this?
Thank you.
You mentioned you want to set lineHeight in pre-API 28, an alternative approach would be to just set a small lineSpacingExtra / lineSpacingMultiplier value (as you have shown). Otherwise, there are many solutions to setting a line height yourself in this related question.
I'll briefly cover the differences below, with my summary and the official documentation.
android:lineHeight is the total height of each line. This includes the text, as well as any padding on the top and bottom.
Explicit height between lines of text. If set, this will override the values set for lineSpacingExtra and lineSpacingMultiplier.
android:lineSpacingExtra is the additional spacing added after each line of text (except the last one).
Extra spacing between lines of text. The value will not be applied for the last line of text.
Finally, you may be interested in android:lineSpacingMultiplier. This is similar to lineSpacingExtra, but with a multiplier value of the current height (e.g. 1.2) instead of a fixed value.
Extra spacing between lines of text, as a multiplier. The value will not be applied for the last line of text.
Further information (besides the included quotas) is available in the TextView documentation.
MaterialTextView (MTV) includes the ability to set the android:lineHeight.
And if you use the app: prefix, it is backwards compatible until SDK-Version 21.
Btw., under some circumstances (i believe its depending on your style, but am not sure about it), standard TextViews are automatically replaced with MTVs. (Check your LayoutInspector, you might already use them without knowing it)
In case you're still wondering about the differences, there's an excellent talk by the android team about text in general; which should solve your question at ~16:50.
android:lineHeight defines Explicit height between lines of text. while android:lineSpacingExtra defines Extra spacing between lines of text
you can read more android_documentation_for_text_arributes
android:lineHeight
is used to specify the total height for single line of text.
android:lineSpacingExtra
is used to add extra spacing between 2 lines of text in addition to the default line height used by android.
In order to replicate lineHeight functionality with API level < 28, set the lineSpacingMultiplier to 0 and set the lineSpacingExtra to the lineHeight that you want to use
android:lineSpacingMultiplier="0"
android:lineSpacingExtra="<enter line height value here in dp>"
I'm trying to draw text using Canvas and have found that using StaticLayout would take care of the line breaks automatically. I also want to limit its height so that when text is too long it would be ellipsized, but the size of text container is dynamic. I can easily apply the width to StaticLayout, but cant find a way to do height.
I tried to utilize TextUtils.ellipsize(), but having issue to get the spacing between lines.
PerracoLabs has the right answer but, as CheokYanCheng stated, the calculation of the maximum number of lines is off (although it may yield the correct result many if not most of the time).
A maximum height cannot be specified for a StaticLayout except indirectly by specifying the maximum number of lines. Ellipsis is tied to the maximum line count anyway, so determining the maximum number of lines for a specific height to back into a solution is the way to go. So, how do we determine the appropriate maximum line count so that a fixed-size StaticLayout with ellipsis can be created as PerracoLabs has explained.?
If the text has no spans that effect the height any of the lines of text then a simply calculation can determine the maximum number of lines that will fit into a StaticLayout before ellipsis.
The following Kotlin function will determine how many lines of text will fit into a view that has a fixed height and width. It is assumed that each line of a StaticLayout has a set height (no height-effecting spans). The top line has the same height of other lines but it is augmented by a top padding. The bottom line has a bottom padding added to it.
private fun getMaxLines(maxHeight: Int): Int {
// Build a dummy StaticLayout to get the internal measurements.
return makeStaticLayout("", width, 1).run {
val lineHeight = getLineBottom(0) - getLineTop(0) + topPadding - bottomPadding
(maxHeight - topPadding - bottomPadding) / lineHeight
}
However, if the text contains a span that changes the height of one or more lines then the only way to calculate the maximum number of lines is through the creation of the static layout that holds the entire text (no ellipsis) followed by an inspection of the lines within the layout to determine how many complete lines have fit. A new StaticLayout can then be created with the calculated maximum lines determined from the inspection.
The following Kotlin function will calculate the maximum lines by inspecting the StaticLayout for the last full line that is present.
private fun getMaxLinesByInspection(staticLayout: StaticLayout, maxHeight: Int): Int {
var line = staticLayout.lineCount - 1
while (line >= 0 && staticLayout.getLineBottom(line) >= maxHeight) {
line--
}
return line + 1
}
I have posted a small project on GitHub as a demonstration.
Here is a screen shot of the app.
You (and #Cheok Yan Cheng) might try to make use of PagedTextView. The view is intended for Paginating text in Android.
The view partially solves the problem, i.e. reacts to dynamic size changes. As to text ellipsizing, you might achieve this by customising the algorithm I've used for measuring text in height.
There is a methods that multiply spacing between lines in TextView
lineSpacingMultiplier
I want to multiply it by 2 , but what is the default spacing value that it multiplies? 2px, 5px?
Thanks.
The value is a 17.1 percent of the text size.
But use 20 percent to be sure that letter like j or g appear correctly
After some messing around with Spans, I finally found how to find the default line spacing (the space from the lowest glyph (y) in a line to the tallest glyph (L) in the next line). Here is the code:
public static int getLineSpacing(TextView textContainer){
Paint.FontMetricsInt fontMetrics = textContainer.getPaint().getFontMetricsInt();
return fontMetrics.ascent - fontMetrics.top;
}
I have a TextView which displays a long text. I want to give some space between lines like in CSS with line-height property. How can I do it?
You can use lineSpacingExtra and lineSpacingMultiplier in your XML file.
If you want padding between text, try LineSpacingExtra="10sp"
<TextView
android:layout_width="match_parent"
android:layout_height="180dp"
android:lineSpacingExtra="10sp"/>
you can look into android:lineSpacingExtra and apply it to your XML
Additional Info is on this page
or the related method public void setLineSpacing (float add, float mult)
Additional Info here
This supplemental answer shows the effect of changing the line spacing.
You can set the multiplier and/or extra spacing with
textView.setLineSpacing(float add, float mult)
Or you can get the values with
int lineHeight = textView.getLineHeight();
float add = tvSampleText.getLineSpacingExtra(); // API 16+
float mult = tvSampleText.getLineSpacingMultiplier(); // API 16+
where the formula is
lineHeight = fontMetricsLineHeight * mult + add
The default multiplier is 1 and the default extra spacing is 0.
Adding android:lineSpacingMultiplier="0.8" can make the line spacing to 80%.
You can use TextView.setLineSpacing(n,m) function.
You can either use lineSpacingExtra or lineSpacingMultiplier in your XML file.
lineSpacingExtra add extra spacing between lines of text of TextView
<TextView
android:lineSpacingExtra="4dp" />
lineSpacingMultiplier works as scale factor for height of line space:
<TextView
android:lineSpacingMultiplier="0.8" />
In other words, each line height will be height * multiplier + extra.
You can use 2 attrs
1. lineSpacingExtra:
it use for dp spacing
android:lineSpacingExtra="4dp"
2. lineSpacingMultiplie:
it use for relative scale
android:lineSpacingMultiplier="0.8"
As an extended answer to above solutions
Remember you can add <item name="android:lineHeight">16sp</item> for directly setting the line heights but as per the docs above line works like this -
Explicit height between lines of text. If set, this will override the values set for lineSpacingExtra and lineSpacingMultiplier.
<attr name="lineHeight" format="dimension" />
So be sure to use either lineSpacingExtra & lineSpacingMultiplier or lineHeight and not both.
As of 16/11/2021,
I use this line to increase the line space height:
android:lineHeight="25dp"
For me the other answers weren't helpful because maybe they updated the attribute and quite a lot of stuff changed in this version.
I am writing an app, in which part of it displays a line of text. there are certain scenarios where that line of text will take up more than one line. the problem is that I only want it to take up one line, and when I set it up either in java or in xml to only take up one line, the text is cut off. how would I make it so that it automatically adjusts the font size of the text so that it will only take up one line without being cut off?
Use proportions along with Paint.measureText():
(text size / measureText width) = (perfectSize / screenWidth)
Solving for the perfect text size:
perfectSize = (text size / measureText width) * screenWidth;
You can find the screen width with getWindowManager().getDefaultDisplay().getWidth() from the Display class.
Turned it into a math problem!
This isn't too hard to do if you use Paint#measureText.
Basically you would start with a font height smaller than the height of your TextView and then iterate (or do a binary search) through fonts of varying sizes until you find one that measures to smaller than the width of your TextView.
It requires some implementation, as there is no "automatic" way provided by the framework.