I use TypedValue.applyDimension and displayMetrix.scaledDensity to set text size in the TextView on my Xiaomi Redmi 5 plus and get surprizing results: text in the TextView is much larger than the one (same sp value) set in layout attribute. Here's my layout:
<TextView
android:id="#+id/my_text_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center|start"
android:layout_margin="4dp"
android:text="Some Text"
android:textSize="18sp" />
And here is how I change text size:
TextView titleView = itemView.findViewById(R.id.my_text_view);
titleView.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 18,
getResources().getDisplayMetrics()));
I also tried to use formula as follows:
(int) getResources().getDisplayMetrics().scaledDensity * 18
On the emulator, I get the right text size, so I am not sure how to reproduce this. If someone manages to do that, please, leave comments for me and others to understand what is actually wrong.
Thanks
So, I opend TextView source code and found out that TextView.setTextSize accepts sp, not px. So the answer is not to convert sp to px, but to use sp by default, or, if you need to support several size units, use setTextSize(int unit, float size)
Related
So I have two text views, one a that has a specific height and auto-size properties implemented in it. The other is a normal multiple lined text view with wrap content as height.
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tvMovieRating"
android:layout_width="match_parent"
android:layout_height="#dimen/tvOthersActivityMovieHeight"
android:layout_marginStart="#dimen/text_view_movie_description_margin_start"
android:layout_marginHorizontal="#dimen/mainCLMarginActivityMovie"
android:text="#string/movieRatingHint"
android:textColor="#color/white"
app:autoSizeMaxTextSize="#dimen/all_auto_max_text_sizes"
app:autoSizeMinTextSize="#dimen/all_auto_min_text_sizes"
app:autoSizeStepGranularity="#dimen/all_auto_size_step_granularities"
app:autoSizeTextType="uniform"
app:layout_constraintTop_toBottomOf="#id/tvMovieNameAndDate"
/>
<TextView
android:id="#+id/tvMovieDescriptionList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/text_view_movie_description_margin_start"
android:layout_marginHorizontal="#dimen/mainCLMarginActivityMovie"
android:textSize="268sp"
android:text="#string/lorem_ispum"
android:textColor="#color/white"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tvNonChangeableDescriptionText"
/>
Now what I'm trying to set the 2nd textView's textSize size based on the first textView's textSize.
I've tried:
binding.tvMovieDescriptionList.textSize = binding.tvMovieRating.textSize
but it didn't work, any help?
You cannot directly do the following: setTextSize(getTextSize()).
The reason is the getTextSize() is returning the exact pixel size, meanwhile setTextSize() sets the scaled pixel unit. The unit does not align with these functions.
So for the simplest way, you can mention the unit when you are setting the size:
binding.tvMovieDescriptionList.setTextSize(TypedValue.COMPLEX_UNIT_PX, binding.tvMovieRating.textSize)
Or you can calculate the scaled pixel unit yourself before setting:
val metrics = resources.displayMetrics
binding.tvMovieDescriptionList.textSize = binding.tvMovieRating.textSize / metrics.density
Perhaps you've forgotten to notify your binding. Most changes in bindings require you to notify them to update them. I would try
binding.notify()
or
binding.notifyAll()
On another note, you could always simply copy your auto-sizing dimensions over to your secondary text view. I don't see why you couldn't do that, as this is only two text views, not 1120.
I got some issue with dynamically created TextViews. To be more specific:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some text"
android:textColor="#color/black"
android:textSize="30px" />
appears much larger than:
TextView prName = new TextView(this);
prName.setTextColor(getResources().getColor(R.color.black));
prName.setText("Some text");
prName.setTextSize(TypedValue.COMPLEX_UNIT_PX, 30);
How to made them equal? Thanks beforehand
For text you should use scale points (SP) instead of pixel.
For xml:
android:textSize="30sp"
For code:
prName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30);
Set height and width as wrap_content for your textview.
LinearLayout.LayoutParams Params1 = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
prName.setLayoutParams(Params1);
Make sure when you setTextSize for any type of view, you should set it in scalable points (sp) and not in pixels (px) like this:
In xml:
android:textSize="18sp"
In code:
prName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
Using scalable points will let your TextView text size be equal on all devices, while using pixels will let your TextView text size be unequal on devices with different resolutions.
use setTextSize(int unit, float size)
TypedValue.COMPLEX_UNIT_PX //Pixels
TypedValue.COMPLEX_UNIT_SP //Scaled Pixels
TypedValue.COMPLEX_UNIT_DIP //Device Independent Pixels
In here just set
prName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
Remove this line:
prName.setTextSize(TypedValue.COMPLEX_UNIT_PX, 30);
... or use this instead:
prName.setTextSize(30);
I have 2 TextViews in my home widget. For the 3rd column, I specific the size in pixel, through XML
<TextView
android:id="#+id/text_view_2"
android:layout_width="0dp"
android:width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:paddingRight="8dp"
android:layout_weight="1"
android:textSize="24px"
android:gravity="right|center_vertical" />
For the 2nd (middle) column, I specific the size in pixel too, through Java code.
#Override
public RemoteViews getViewAt(int position) {
...
remoteViews.setFloat(R.id.text_view_1, "setTextSize", 24);
I expect the 2nd column and 3rd column will be in same size, as both are using 24 pixel.
But, if looking at screenshot, that is not the case! Anything I had done wrong?
Method setFloat() applied to "setTextSize" always uses sp. Here is the method which gets called at the end.
#android.view.RemotableViewMethod
public void setTextSize(float size) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}
Try to use the method below to set test size in px.
remoteViews.setTextViewTextSize(R.id.text_view_1,
TypedValue.COMPLEX_UNIT_PX, 24);
Update: If you need to support Gingerbread you should use setFloat(). Knowing that it expects sp I would try to provide a smaller value in there, which, after scaling, would correspond to desired px size. I believe this would be the formula. I wasn't able to test it, but it might work.
float size = 24 / getResources().getDisplayMetrics().scaledDensity;
remoteViews.setFloat(R.id.text_view_1, "setTextSize", size);
I have extended the TextView and added support for borders, the thing is when I am drawing a border I need to put padding on the bordered side, so that the text would move.
I set my widths of borders in pixels, and it draws them accordingly, but on my TF201 tablet when I setPadding on the TextView, out of some reason it multiplies the padding width by 3x in pixels even though the setpadding documentation says it is defined explicitly in pixels.
EDIT:
Even though the answer I have selected is not what was causing my issue, it is a valid answer. The real answer to my question is actually a duplicate from this. Problem was that I have added a value to my padding each time setPadding was called. And it does get called three times on a page that has scrolling to it.
It might be a issue of pixel density. Its true that setpadding docs asks to set the padding in pixels but are you setting it in px, sp or dp ? If you read Supporting Different Densities document it says and I quote:
Different screens have different pixel densities,so the same number of pixels may correspond to different physical sizes on different devices.
So, when you specify spacing between two views, use dp rather than px:
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/clickme"
android:layout_marginTop="20dp" />
When specifying text size, always use sp:
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp" />
Also, based on your comments:
drawRect unit issues android andDraw Rectangle which change size w.r.t different android screen size question might help.
While the method may only accept pixel values, that sadly doesn't save you from needing to take screen densities into account. Instead, you need to determine your values in terms of DP and then programmatically calculate the pixel equivalents at runtime. Fortunately, there are some built-in methods to help you out. This can be done with the following code:
/// Converts 14 dip into its equivalent px
int dimensionInDp = 14;
Resources r = getResources();
float dimensionInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInDp, r.getDisplayMetrics());
Although the result is a float, you can easily cast it to an int for use in your setPadding(...) method.
(Referencing: Converting pixels to dp)
I think the solution will be quite obvious, but as long as I'm rookie in android forgive me :)
I want to place some picture on the right upper side of the view, and a textview, which will fit the rest of the view. Here's what I've done:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/logo_in_listing"
android:layout_width="100dip"
android:layout_height="100dip"
android:layout_alignParentRight="true"
android:layout_marginRight="11dip"
android:layout_marginTop="11dip"
android:background="#drawable/border_for_imageview"
android:src="#drawable/facebook_logo" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/someString"
android:id="#+id/textview1"
android:layout_toLeftOf="#id/logo_in_listing"
android:layout_margin="3dip"/>
</RelativeLayout>
Here's what I get:
My questions:
1) How to make the textview fit also the lower part of imageview? I don't want that space to be left unused.
2) As you see, I've used dips for placing ImageView. What would you recommend in this case? I mean, how to write in a way, that it will be same for all screen sizes? Or maybe dip is OK?
You have to use Spanned interface. Here's a good example
1) How to make the textview fit also the lower part of imageview? I
don't want that space to be left unused.
Flow around text isn't possible with currently available layouts. However you can display content as HTML in a WebView or even spanned-HTML in a TextView.
2) As you see, I've used dips for placing ImageView. What would you
recommend in this case? I mean, how to write in a way, that it will be
same for all screen sizes? Or maybe dip is OK?
Dip is for device independent pixels. On different screen sizes, 1 Dip will take different number of pixels, but visually, 1 dip will appear almost same to eye on all screens.
If You donĀ“t want to left space, You could use spannables. For example:
int TEXT_START = 0;
int TEXT_END = yourTextView.length();
Spannable span = (Spannable) yourtextview.getText();
span.setSpan(new AlignmentSpan.Standard(Alignment.ALIGN_CENTER), TEXT_START, TEXT_END,
0);
For Your second Question: use dp instead of dip.