In design I have a text field with 16 as text size and 0.6 as character spacing
But, if I set this value for android:letterSpacing attribute of TextView spacing will be much more larger than in design.
So, what is the way to convert sketch value to android value?
According to Romain Guy, Android uses the "1 em = font size" definition, so you'd just do
setLetterSpacing(characterSpacing / textSize)
...just make sure those values are in the same unit (dp vs px)
If Sketch provides the letter spacing value in Points, then the following is the conversion:
float textSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, textSizeInSp, displayMetrics);
float letterSpacingPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, sketchLetterSpacing, displayMetrics);
float androidLetterSpacing = letterSpacingPx / textSizePx
return androidLetterSpacing;
Material design 2 uses em as the unit for letter spacing on Android, and the following conversion ratio for Sketch values need to be applied:
(Tracking from Sketch / font size
in sp) = letter spacing
To clarify, here is an example for Jetpack Compose:
fontSize = 14.sp,
letterSpacing = (1.25 / 14).em
1.25 is the Sketch value and 14 is the font size in sp, but note the unit is converted to em.
Check out android:textScaleX
Depending on how much spacing you need, this might help. That's the only thing remotely related to letter-spacing in the TextView.
Related
In Compose, we use AnnotatedString as a replacement for Spanned. However, I cant seem to find a way to replicate the behaviour of RelativeSizeSpan with a SpanStyle.
The relevant options I can see for SpanStyle are:
fontSize: TextUnit - not useful because this only accepts absolute text sizes, and I need my span style to scale the original font size by some factor
textGeometricTransform: TextGeometricTransform - not useful because TextGeometricTransform only performs X transformations, and I need the text to be scaled in both X and Y.
Can anyone share some insight?
You can achieve it with SpanStyle, but you need to use the em TextUnit, which is a relative font size unit. It means that 1em is equal to the current font size and 2em is a font two times bigger.
Here is the code demonstrating how it behaves on two Texts with different font size:
val annotatedString = buildAnnotatedString {
append("This is a ")
withStyle(style = SpanStyle(fontSize = 2.em)) {
append("big")
}
append(" text")
}
Column {
Text(annotatedString, fontSize = 20.sp)
Text(annotatedString, fontSize = 40.sp)
}
The word big is 2 times bigger than other words in the same Text.
You can also see that it makes the big word from first Text the same size (2 * 20sp) as the other words in the second Text (40sp).
I have an edittext with its textsize set in the layout and another one with the size set programmatically, but what is supposed to be the same size, doesn't match, its bigger.
For performance i don't want to use:
setTextSize(TypedValue.COMPLEX_UNIT_SP, 65);
(that works well). I want to make the calculation before, so I tryed:
sm = (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 18, context.getResources().getDisplayMetrics());
sm = (float) context.getResources().getDimension(R.dimen.dsma);
with
<dimen name="dsma">18sp</dimen>
in dimens.
And then
edit.settextsize(sm);
Both gives me big a big font. Fix? tnx.
edit.setTextSize(18);
Theres no way to avoid the calculation, since its done anyway, a simple int(float) will be considered sp.
Credits to pskink, tnx.
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. ;)
I want to use shape drawable with a radial gradient as a background for a View. According to the javadoc the radius of the gradient can be set as a specific value (presumably pixels) or as a percent:
android:gradientRadius
Radius of the gradient, used only with radial gradient.
May be a floating point value, such as "1.2".
May be a fractional value, which is a floating point number appended
with either % or %p, such as "14.5%". The % suffix always means a
percentage of the base size; the optional %p suffix provides a size
relative to some parent container.
Correct me if I'm wrong, but using a pixel value here is completely useless since this gradient will look totally different from one screen density to another (tested, and yes this is true). I tried to go with the % and %p values, but they didn't work at all.
I dove into the Android source code to see how gradientRadius is being processed and found this in the GradientDrawable Class:
TypedValue tv = a.peekValue(
com.android.internal.R.styleable.GradientDrawableGradient_gradientRadius);
if (tv != null) {
boolean radiusRel = tv.type == TypedValue.TYPE_FRACTION;
st.mGradientRadius = radiusRel ?
tv.getFraction(1.0f, 1.0f) : tv.getFloat();
} else ...
}
Ah HA! So all adding % or %p does is divide my value by 100. (I tested this because the documentation for TypeValue.getFraction() is even more unclear). 65% became 0.65. Makes sense, but serves no useful purpose.
So what is the best way to use gradientRadius?
PS.
I have added my background programmatically using a GradientDrawable and I am getting the desired results. I used GradientDrawable.setGradientRadius() with a value relative to the view width and get a consistent Gradient across devices.
To work with all the screen size you have to set radius in dp. You can calculate px from dp by this method
public float pxfromDp(float dp) {
return dp * getResources().getDisplayMetrics().density;
}
So for example you want to set GradientDrawable.setGradientRadius(pxfromDp(7));
I have some squarish TextViews (with different dynamic sizes(I don't know them while I'm developing)) in my Application and want to set their text. But if I say TextView.setText(); the text font is pretty small. If I set TextView.setFontSize sometimes the text is not fully displayed (remember: they have a dynamic size). So my question: how can I give the text the perfect font (using the full space of the button AND being fully displayed) or make the Text squarish itself so that it fills the whole space of the TextView?
Thank You
You may use Paint.getTextBounds() like this:
int textViewWidth = textView.getMeasuredWidth();
float textSize = 1.0;
do {
textSize += 0.5
textView.setTextSize(textSize);
Paint textPaint = textView.getPaint();
textPaint.getTextBounds(text, 0, text.length(), rect);
int width = rect.width();
} while (width < textViewWidth);
textView.setTextSize(textSize - 0.5);
Looking over the documentation, it looks like you should be able to use something like this:
TextView tv = (TextView) findViewById(R.id.myTextView);
tv.setTextScaleX(tv.getWidth());
This will scale the width of your text to the width of the TextView.
I think you will need to calculate heights of the button and the text you wish to set. APIs you will need are: Paint.getTextBounds() and View.getHeight().