I would like to achieve the following layout
AAAAAAAAAAAAAAAAAA
AAAAA... BBBBBBBBB
Where AAAA is a textview (ellipsize = "end"
) and BBB is a textview as well.
It will never have more than two lines. I just need the first textview to be wrapped around the second sort of.
How should I do that?
Final result
Explanation
It is by no means perfect and will likely need some tweaking for it to fit your needs. I left out the ellipsize
part to make it more generic, but it would be easy to adapt the code for that. The idea is simple but it took me a few hours (only because its Sunday) to make it work. We calculate how many more characters from the second TextView
would fit the last line of the first one. Then with that number we add the last line to the second TextView
with a color matching the background of the container, this is a limitation that could probably be solved somehow yet I can't seem to find it.
With that, we would have the two views with their text aligned, yet they are still not overlapping each-other to allow the wrap effect. So we get the height of the text and add a negative margin to the second one so that they overlap, to ensure that the first TextView
is on top of the second one we need to call bringToFront()
to avoid having the text with the same color as the background over the last line of the first one (wow this is getting confusing). It may not work good with different fonts and weights (bold for example) since the characters will likely take more space.
I didn't make it a method but it could easily become generic and reusable, just wanted to prove if I could do it or not. Here's the code for anyone and everyone to enjoy and improve upon. The layout is simply a container (a RelativeLayout
for example) and two textviews with ids first
and second
, I've set the text color to red on the second one to make it clearer but it's not necessary.
Code
final TextView first = (TextView) findViewById(R.id.textView);
final TextView second = (TextView) findViewById(R.id.textView2);
final ViewGroup container = (ViewGroup)findViewById(R.id.container);
final ViewTreeObserver obs = findViewById(R.id.container).getViewTreeObserver();
obs.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//Get characters from the first TextView's last line
String lastLine = first.getText().toString().substring(first.getLayout().getLineStart(first.getLineCount() - 1));
//Calculate the number of extra characters that will fit in the first one
int e = 0; //Extra characters
int lineCount = first.getLineCount();
while (lineCount == first.getLineCount() && e < second.getText().toString().length() - 1) {
first.append(second.getText().toString().substring(e, e + 1));
e++;
}
//Remove those characters again to leave the first TextView as it was
String firstString = first.getText().toString();
first.setText(firstString.substring(0, firstString.length() - e));
//Add the last line of the first textview to the second textview
second.setText(Html.fromHtml("<font color='#F2F2F2'>"+lastLine+"</font>"+second.getText()));
//add a negative margin to the second textview equal to a line's height
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) second.getLayoutParams();
params.topMargin = -(int)(first.getLineHeight()+10);
second.setLayoutParams(params);
//Make sure first is on top
first.bringToFront();
//Remove the listener
if (Build.VERSION.SDK_INT < 16) {
container.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
container.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
In RelativeLayout make textview AAA normal 2-lines-high textview without ellipsization and make textview BBB with text "... BBBBBBBB" and with non-transparent background so textview AAA will not be visible behind BBB.
Second option is do it programatically - calculate amount of letters and cut that string down if longer than should be.
But none of those 2 "hacks" will work at 100% if you don't use monospace font. Sorry for my english.
<RelativeLayout android:layout_width="200dp" android:layout_height="70dp">
<TextView android:id="@+id/aaa"
android:layout_width="match_parent" android:layout="match_parent"
android:lines="2"
android:typeface="monospace" />
<TextView android:id="@+id/bbb"
android:layout_width="match_parent" android:layout="wrap_content"
android:typeface="monospace"
android:lines="1"
android:background="#ffffffff"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
You also need to count amount of letters in string for AAA and so in BBB. If sum of those 2 amounts is more than allowed (texts will overlap) add "... " string before BBB string:
BBBTextView = (TextView) findViewbyId(R.id.bbb);
int maxLetterCount = 125; // you need to specify this number
String AAAString = " gtgtfd def e refrfecj gjv jvrji rf wj jiefijr jgfrjf jrf"
String BBBString = "deeded ed e ddd"
if ( (BBBString.length()+BBBString.length()) > maxLetterCount ) {
BBBString = "... " + BBBString;
}
BBBTextView.setText(BBBString);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With