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);
}
}
});