Get the size of a text in TextView - android

I have a problem placing a textView at specified center's x and y coordinates.
Firstly, I tried to set the text in the textView, and to move the view with the width and the height of the view
from this link.
But it doesn't work, and I'd like to try something else.
I'd like to know if there is a method to get the size which a specified text will take in my textView?
I mean, I know the text and the textSize, how can I get the width and the height my textView will take?
Something like the method (NSString)sizeWithFont; for those who know iPhone dev.

Rect bounds = new Rect();
textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), bounds);
bounds.width() will give you the accurate width of the text in the Text View.

If your textview is called tv
tv.setText("bla");
tv.measure(0, 0); //must call measure!
tv.getMeasuredHeight(); //get height
tv.getMeasuredWidth(); //get width
More on this (updated): How to get width/height of a View

For some reason the solution of Midverse Engineer does not give me always correct results (at least on some Android versions). The solution of Sherif elKhatib works, but has the side effect of changing MeasuredWidth and Height. This could lead to incorrect positioning of the textView.
My solution:
width = textView.getPaint().measureText(text);
metrics = textView.getPaint().getFontMetrics();
height = metrics.bottom - metrics.top;

Using the TextView inner Paing class is not so hot when you have multiple lines of text and different paddings. So stop trying to reinvent the wheel. Use getMeasuredHeight and getMeasuredWidth methods after calling measure(UNSPECIFIED, UNSPECIFIED). Just don't forget to get the new values inside the post, otherwise mostly you'll get a wrong result.
tv.setText(state.s);
tv.measure(UNSPECIFIED,UNSPECIFIED);
tv.post(new Runnable() {
#Override
public void run() {
Log.d("tv","Height = "+tv.getMeasuredHeight());
Log.d("tv","Width = "+tv.getMeasuredWidth());
}
});

Related

Android setMaxLines with animation

I'm using a TextView to be viewed in ListView item, when that item is clicked I need that text to completely be viewed instead of just first 2 lines.
What I'm doing now is changing maxLines value from 2 (the initial value) to the maximum integer value.
I need this to be done with expand animation. I already know how to expand it, but I only need to find the new height such that I can simply call the expand method.
Update:
I'm using this code to solve my problem, but the returned full height is smaller than the actual one. I think it's px and dp issue:
public int getFullHeight(TextView tv) {
Context context = tv.getContext();
TextView textView = new TextView(context);
textView.setText(tv.getText().toString());
textView.setTypeface(tv.getTypeface());
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tv.getTextSize());
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(tv.getLayoutParams().width, View.MeasureSpec.EXACTLY);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
textView.measure(widthMeasureSpec, heightMeasureSpec);
return textView.getMeasuredHeight();
}
Given that tv is the original TextView that's with 2 lines.
If I change COMPLEX_UNIT_PX to COMPLEX_UNIT_DIP then it gets larger than the full size, with a white space at the bottom.
Best solution I can find is this:
Measuring text height to be drawn on Canvas ( Android )
Or here: http://egoco.de/post/19077604048/calculating-the-height-of-text-in-android
What they are doing is, creating a paint object with specified width, placing the text and style to use in it and then geting the boundaries.
Hope that helps

Text width in a textview android

I am new to Android.. I have a textview with size 250dp.. I am trying to calculate the text width inside it.. But I could not find any API that returns the actual content width.. Can someone help how it can be done.
Thanks in advance.
You can use the Paint object held by the TextView to measure the width of the text contents:
CharSequence text = textView.getText();
float width = textView.getPaint().measureText(text, 0, text.length());
There is also a version that measures the full bounds (left/right/top/bottom) of the text contents:
Rect bounds = new Rect();
CharSequence text = textView.getText();
textView.getPaint().getTextBounds(text, 0, text.length(), bounds);
//bounds now contains the rect of the actual text string
int width = bounds.getWidth();
The Devunwired answer is completely right.
However, it's useful the reader to know that the text width measure in pixels don't need to be linked with any real content of a TextView or EditText and isn't restricted to the view widht, so one can simulate if a determinated text fits well in the view before set the view with a text.
Besides, if one uses the whole string you don't need to specify a initial index and a final index (exclusive).
So one can write
float width = textView.getPaint().measureText("my favorite fruit is a banana");
It works smoothly
There is no API for this.first you have to find the text size and find lenth of string.finally multipl both you will get width of text in textview.

Android multiline TextView , check if text fits , or check is TextView is full

I have an Android application layout which contains a multiline TextView. When the screen is in portrait orientation, the TextView can display a different length of text to when running in landscape mode. Also when running on a small screen, the TextView can display a different length of text to when running on a larger screen.
Is there any way I can check if the text fits or will be truncated? Or is there any way I can check if the TextView if full?
The problem is the TextView can potentially contain a different number of lines, depending on whether it is landscape, portrait, small screen, large screen, etc.
Thank you for your advice,
Best regards,
James
These answers didn't work very well for me. Here's what I ended up doing
Paint measurePaint = new Paint(myTextView.getPaint());
float pWidth = measurePaint.measureText("This is my big long line of text. Will it fit in here?");
float labelWidth = myTextView.getWidth();
int maxLines = myTextView.getMaxLines();
while (labelWidth > 0 && pWidth/maxLines > labelWidth-20) {
float textSize = measurePaint.getTextSize();
measurePaint.setTextSize(textSize-1);
pWidth = measurePaint.measureText("This is my big long line of text. Will it fit in here?");
if (textSize < TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 7,
getContext().getResources().getDisplayMetrics())) break;
}
myTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, measurePaint.getTextSize());
I'm not saying this will work for every situation as I'm certainly cutting corners here, but the general idea is to measure the text with the textview's paint and keep shrinking it until it will fit inside the textview.
I have found a "cheeky" solution to the problem of measuring the height of the text in a MULTILINE TextView :-
//Calculate the height of the text in the MULTILINE TextView
int textHeight = textView.getLineCount() * textView.getLineHeight();
if (textHeight > textViewHeight) {
//Text is truncated because text height is taller than TextView height
} else {
//Text not truncated because text height not taller than TextView height
}
However this solution has some caveats :-
Firstly regarding getLineHeight() , markup within the text can cause individual lines to be taller or shorter than this height, and the layout may contain additional first- or last-line padding. See http://developer.android.com/reference/android/widget/TextView.html#getLineHeight()
Secondly , the application needs to calculate the actual height of the TextView in pixels , and (in the case of my layout) it might not be as simple as textView.getHeight() , and calculation may vary from one layout to another layout.
I would recommend avoiding LinearLayout because the actual pixel height of the TextView can vary depending on text content. I am using a RelativeLayout (see http://pastebin.com/KPzw5LYd).
Using this RelativeLayout, I can calculate my TextView height as follows :-
//Calculate the height of the TextView for layout "http://pastebin.com/KPzw5LYd"
int textViewHeight = layout1.getHeight() - button1.getHeight() - button2.getHeight();
Hope that helps,
Regards,
James
Basically, you need to calculate the size of your textview and the size of your text when the orientation mode changed. Try ViewTreeObserver.OnGlobalLayoutListener to do so.
Inside the change orientation method:
main_view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
main_view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//Calculation goes here
int text_size = getTextSize(text_view.getText().toString());
int text_view_size = text_view.getLayoutParams().width;
//Compare your text_size and text_view_size and do whatever you want here.
}
});
Here is the code of calculate the text_size:
private int getTextSize(String your_text){
Paint p = new Paint();
//Calculate the text size in pixel
return p.measureText(your_text);
}
Hope this help.
For checking whether a multiline (or not) TextView is going to be truncated, check this post.
Or, have you looked into using a scrolling textview? (marquee).. where the text will scroll by (horizontally, animated) if it is too long for a given width?
Here is an example TextView in a layout file, that has some of these characteristics:
<TextView
android:id="#+id/sometextview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:scrollHorizontally="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:freezesText="true"
android:textColor="#808080"
android:textSize="14sp"
android:text="This is a long scrolling line of text.. (etc)"/>
This extension function in Kotlin worked for me, just make sure to call it when the view is already laied out, e.g. view.post() is a good place for me;
/**
* Make sure to call this method only when view layout is finished, e.g. view.post() is a good place to check this
*/
fun TextView.isTruncated() = (lineCount * lineHeight) > height
Usage
textView.post {
if(isTruncated()) {
// Do something
}
}
Just check textView.getLineCount(), if line count > 1 then your text is multiline

Changing text of TextView based on its size

Is there any simple way of changing the text of a TextView in order to make it fit the view's size? Note that I do not want to truncate the text or to put an ellipsis, I want to set a different text.
For example instead of Experience: I want to use Exp: if the view is too small(where both those strings are resources).
I know that I could "avoid" this writing a custom .xml layout file for every possible screen size, but I'd like to avoid this if possible. I'm already using some different layout files, but only for situations where the layout needs some radical change to fit the size of the screen. Also in some circumstances I'd like to be able to dynamically set the text of a TextView and this can't be done via xml layout files.
I'm interested only in single-line TextViews and width.
The only way I could think of is to use a custom TextView subclass that uses a fallback text if the original text doesn't fit, but I wonder whether there is a simpler solution and, eventually, how can I reliably compute whether some text fits the TextView size or not.
You can try something like this:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int screenWidth = size.x;
if( textView.getWidth() > screenWidth ) {
textView.setText("Exp:");
} else {
textView.setText("Experience:");
}
I'm not sure if you need to use getWidth() or getMeasuredWidth() so if it will not work, try second option.

Programmatically getting the width of a TextView

I'm attempting to build a layout programmatically.
This layout is dynamic. Based on the data read from a database, it could look different every time.
I have a LinearLayout with its orientation set to vertical.
I want to fit as many TextViews with text (the data from database) as I can on a "row".
What I'm doing is building LinearLayouts that are the rows. These LinearLayouts are populated with TextViews. I build the TextView, set the text, and then check the width to see if it will fit on this row (by subtracting the sum of all TextView widths from the screen width and see if the new TextView will fit). If not, I create a new LinearLayout and start adding TextViews to that one.
The problem is myTextView.getWidth() and myTextView.getMeasuredWidth() both return 0.
Why? How can I get the width of the TextView?
Well first of all, please post your code. Second the getWidth/getHeight returning zero question gets asked A LOT so you could search SO for more answers.
Assuming your calling these methods during onCreate (which is probably the case), the UI hasn't been drawn yet so the returned value is zero. You can't get the width or height of the view until it has been drawn.
You can use this library to schedule the task of perform calculation on the width to the correct time after the view had been completely drawn
You can call it on onCreate() and from any Thread
https://github.com/Mohamed-Fadel/MainThreadScheduler
Sample of use:
MainThreadScheduler.scheduleWhenIdle(new Runnable() {
#Override
public void run() {
int width = textview.getWidth();
int height = textview.getHeight();
textview.setText( String.valueOf( width +","+ height ));
}
});

Categories

Resources