Consider this layout:
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="160dp"
android:textSize="20sp"
android:text="Apple Inc. is an American multinational technology company headquartered in Cupertino, California, that designs, develops, and sells consumer electronics, computer software, and online services."
android:ellipsize="end"
android:gravity="top"/>
What I want the TextView to do is to figure out how many lines it can fit in 160dp and places three dots if room is not enough. However the text is cut off instead:
How can I achieve the above behavior? I assume I can do it by just specifying some attribute on the layout resource file. Thanks.
There's no way to achieve this by simply specifying attributes on the layout resource file.
If you look at the setEllipsize() method in TextView, you'll see that it says:
Causes words in the text that are longer than the view's width to be ellipsized instead of broken in the middle. You may also want to setSingleLine() or setHorizontallyScrolling(boolean) to constrain the text to a single line. Use null to turn off ellipsizing. If setMaxLines(int) has been used to set two or more lines, only TextUtils.TruncateAt.END and TextUtils.TruncateAt.MARQUEE are supported (other ellipsizing types will not do anything).
From that documentation, you can see that ellipsis in TextView is actually highly dependent on two factors: view width and number of lines.
As such, I recall that an ellipsis might not show up for a TextView if it doesn't know the maximum number of lines that your TextView can have.
So for your intended behavior, this isn't possible because you're depending on the View's height instead. You want to use a specific height then have a TextView calculate the amount of lines that can be shown within that height. Finally, if the amount of lines needed is greater than the amount shown, you want to show ellipses.
That's... not possible with how the ellipses in TextView is coded. It simply wasn't meant for that.
Therefore, if you want this behavior, you need to either:
Create a custom TextView for your specific ellipses implementation
Manually calculate the amount of lines visible, then use setMaxLines() on that TextView
For the second option, you can calculate this by using the TextView methods getHeight() and getLineHeight().
For example:
textview = (TextView) findViewById(R.id.exampleTextView);
textview.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
final int maxLines = textview.getHeight() / textview.getLineHeight();
textview.setMaxLines(maxLines);
}
});
In my example, I'm doing this inside a ViewTreeObserver to avoid getHeight() calling a size of 0.
The second option should be able to get the behavior you want, but if you want this for every TextView, you should consider creating a custom TextView instead.
Set the layout_gravity on the TextView to fill
Related
I have the following TextView:
<com.mycompany.CustomTextView
android:id="#+id/productName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="3"
android:maxLines="3" />
This results in an expected look of the TextView with different amounts of text:
However, when I use our corporate font created by our company, the TextView is getting bigger with every line with no text:
I don't know how this can be dependent on the used font. Is there any attribute in the .ttf file that leads to this odd behaviour?
My first thought was that Android adds new paragraphs to the TextView if not all of the lines are filled. But it would be new to me that a font file can define a default paragraph spacing.
As your view has height and width as "wrap_content" with max_lines = 3. Now it's quite obvious that view's dimensions will change depending as it will figure it out that how much height it will need to accommodate three lines of specific type (font) of input text
As you have custom Textview.Calculate and update LayoutParams dynamically based on the aggregate height of each line.
Yes Text size will vary based on font types.
Check this for detail explanation.
Vote if it helps.
Thanks. Happy coding.
I have a TextView that can have a few different values, and is updated runtime (in Java code).
However, I need this TextView to retain its center point, so that when the text in that TextView is updated, it is always center justified. It should be centered around a point which is not the center of the screen or anything else, so setting gravity only will not help.
As the values that it may contain are already defined, I could try with the longest one first, position it to the correct top left position and set its gravity to center. In this case every shorter in length text should fit correctly.
However, I would like to know if there is better approach, for cases when the values are not known beforehand.
This TextView is placed below an ImageView and it could take the whole screen width (nothing else is placed left or right to it).
Note: I guess it could be also possible to position it every time to a new X axis position, whenever the text is changed, but I don't think it is a nice solution at all.
Set the android:layout_width to match_parent and set android:gravity to center_horizontal.
This way the View is stretched all the way horizontally, and the content (the text) will be centered. If the content changes, it will still be centered.
One thing that many people don't realize is the difference between android:gravity and android:layout_gravity. The first one defines the alignment of the content inside itself, the other one defines alignment of itself relative to its parent.
I would like to draw vertical lines between Numbers/Letters in my TextView. So it should look similar to
A|B|C|D
without the use of the | character and use drawLine() instead.
I am trying to do it using the width of the TextView and assuming the centre of each character will find itself at , 1/8, 3/8, 5/8, 7/8 of the TextView width for this example. However the lines dont line up as they should.
Not sure whats not working, help appreciated.
I am trying to do it using the width of the TextView and assuming the centre of each character will find itself at , 1/8, 3/8, 5/8, 7/8 of the TextView width for this example.
That's your problem. For starters, you haven't specified that you're using a mono-spaced font. If you're not, then the letters won't be evenly distributed. Even if you are using a mono-spaced font, likely the padding at the beginning (and possibly end) of the TextView are going to offset things. I can't remember exactly how TextView measures things, but I suspect looking at actual left padding value would be a good start to find the left padding. If you want to use this with a variable width font, you'll want to use something like Paint.measureText to measure the width of the characters.
Once you have all that, you can add the width of the character(s) to the left padding to find the position to place each line.
I get following requirement.
I need to build a tree with leaves placed left and right, from the screen top to the bottom. I can not put the leaves in a ListView because tow leaves will be in same offset.
I don't know the height of the items.
I need to pre-calculate the height of dynamic content, such as strings with different lengths.
QUESTION:
How can i pre-calculate the height of a sting which will be put in a TextView widget described as follows:
<TextView
android:id="#+id/note_content"
android:layout_width="40sp"
android:layout_height="wrap_content"
android:maxLines="5" />
Create textView, set LayoutParams, set text, call it's measure method and read measured values. BTW you can measure text, not textView (see StaticLayout).
I think you better create your custom layout where you can implement all your "leaves measument" algorithms. Check this lesson. Custom layout is very easy )
Use this for calculate height and width your textview
textView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
public void onGlobalLayout() {
h=textView.getHeight();
w=textView.getWidth();
textView.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
But in xml do not assign textview as a wrap content. Because it will give you value 0.
Imagine a full Android device screen, I want it split in to two sections:
The upper half has text in it, which may be larger than the space available (or not) and so the text will scroll (i.e. TextView inside a ScrollView)
The lower half contains a MapView control.
Looking specifically at some scenarios:
If the text is small, I want the map to take up more space, i.e. more than 50%. So perhaps 20% text, 80% map.
If the text is larger, it only takes up a MAXIMUM of 50% of the screen space, and then scrolls. So 50% map, 50% text.
At the moment I've assigned weights to the two parts, and that isn't too bad, but if the text is small, the map doesn't expand to take the space, and the layout has a wasted gap that the map could usefully use.
I've tried loads of combinations but can't see how to make this happen. It seems to be a common experience for me that I know what I want, but can't see how to get the available views to deliver it. I'm hoping there's a nice easy way to do this.
Please feel free to make me look like a fool and point out the obvious attribute I've missed :-)
======================================================================
As far as I can see there's no way to do this just in declarative XML and it needs doing in the code. I set the text section height to wrap_content, weight to 0 (no resizing), and have the map set to weight=1 (i.e. take up the remaining space). I then check if the text section (in a ScrollView) is taking up too much space and if so, shrink it back. This code would need changing to support a different layout orientation.
private void fixLayoutProportions()
{
float maxPercentageOfScreenForText = 50/100;
LinearLayout container = (LinearLayout)findViewById(R.id.container);
ScrollView eventText = (ScrollView)findViewById(R.id.text_scroller);
int heightAvailable = container.getHeight();
int scrollerHeight = eventText.getHeight();
if ( scrollerHeight>(heightAvailable*maxPercentageOfScreenForText) ) // Text section using too much space
{
eventText.getLayoutParams().height = (int)(heightAvailable*maxPercentageOfScreenForText) ;
eventText.invalidate();
}
}
You can do it by putting everything into LinearLayout and changing following parameters:
the sum of weights for LienarLayout
weights for children
Did you try to measure your screen hight at run time:
Display display = ((WindowManager)
getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getHeight();
Then, set your top view max_height to width*0.5 and min_height to width*0.2. Your top view has to be control (like TextView) that has min_height and max_height properties. Also, set layout_weight to 0 or leave it empty.
On your bottom view set layout weight to 1.
The easiest way to do 50/50 is in XML is using LinearLayout weights. Basically put the two views into a single LinearLayout set the android:layout_weight on both child views to the same value, like setting both to .5, 1, or 42. You then set the layout_width to 0px or fill_parent/match_parent.
The smaller part gets more complicated. Luckily, you can turn off weighing in Java. One way is to wait until the windows get drawn (if they are pre-populated) and measure them. This can be done on I think it was called onWindowFocusChanged
I haven't tested this, but I'd try setting your ScrollView to have android:layout_weight="1" and your MapView to have android:layout_weight="0" and a android:minHeight="240dp". The hope is that minHeight will have precedence over layout_weight.
i think you have to set mapviews height as fill parent and set textviews height as wrap contetn and than for scrolling you have toset vertical scrool true for text view and as you nedded not more than 50% space textview you can set maxheight property of textview.
I am sorry if you find this trivial.
But I am suggesting it in case it did not strike you.
How about using relative layout and keeping the textview always on top of the map.
Make the gravity of the textview top, its width match_parent, its height wrap_content and its weight 1(same as that of thee map). That way your textview will change according to the size of the text, while not going above 50% because of the weight. As for the map, the user can pull the map down to see the hidden part under textview. It'll be as if there is no map under the textview(you know, unless you want to make the textview background transparent which i think would look cool :) ). I do not know about the map view. But I am assuming it'll be something like google maps on iphone, like you can vary size using multi-touch and scroll using single.
OK as I see its something like u are reserving at max half of ur screen to the TextView and if its more it has to scroll. I have a solution but for that you will have to fix the max no.l of lines for TextView, calculating which can be a pain :P but have a solution never the less.
main.xml file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:maxLines="5"
android:id="#+id/tv1"
android:text="wsdvsv sjdgv jsdvn ksdjbn skjdb ksdnbk snbk snbjksn fkbj sfkbjn dfkjbndkjfbn kdjfnb kjdfnbkjdnfbk ndf bjkndf bndfjbn dfkbn jdfnbjdfnbjdfn bjdf nbkjdnf bkjdfnb kjdnfbkjdfn bkjndfbjndfjbndkjfbn dkfjbn kdjfnb kjdfnbkjdfnbjkd nfkjbndf"
/>
<TextView
android:layout_width="fill_parent"
android:layout_below="#id/tv1"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:maxLines="5"
android:text="Does it work ???"
/>
</RelativeLayout>
Java file:
package com.android;
import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;
public class TestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.tv1);
tv.setMovementMethod(new ScrollingMovementMethod());
}
}
If the text is say only in 2 lines "Does it work?" will shift up automatically. But the only problem i see here is the max lines to 5 is you can an max value for u i guess this might work well :)
BR,
J
P.S. I haven't answered many questions before so i m not sure how to attach files :(