我希望实现以下布局
AAAAAAAAAAAAAAAAAA
AAAAA... BBBBBBBBB
当 AAAA 是一个文本视图(ellipsize = "end"
)且 BBB 也是一个文本视图时。它永远不会超过两行,我只需要第一个文本视图包装在第二个文本视图周围。
我该怎么做呢?
我希望实现以下布局
AAAAAAAAAAAAAAAAAA
AAAAA... BBBBBBBBB
当 AAAA 是一个文本视图(ellipsize = "end"
)且 BBB 也是一个文本视图时。它永远不会超过两行,我只需要第一个文本视图包装在第二个文本视图周围。
我该怎么做呢?
最终结果
解释
这并不是完美的,可能需要一些微调才能满足您的需求。我省略了ellipsize
部分,以使其更通用,但很容易为此调整代码。这个想法很简单,但我花了几个小时(只因为今天是星期天)才让它工作起来。我们计算第二个TextView
中还有多少字符适合第一个TextView
的最后一行。然后,使用该数字将最后一行添加到第二个TextView
中,并使用与容器背景相匹配的颜色,这是一个限制,可能可以通过某种方式解决,但我似乎找不到。
有了这个,我们就可以使两个视图的文本对齐,但它们仍然不会重叠以允许换行效果。因此,我们获取文本的高度,并向第二个文本视图添加负边距,以使它们重叠,为确保第一个TextView
在第二个TextView
上方,我们需要调用bringToFront()
,以避免将颜色与背景相同的文本覆盖在第一个文本视图的最后一行上(哇,这变得很混乱了)。由于字符可能占用更多空间,它可能无法很好地处理不同字体和字重(例如加粗)。
我没有将其制作成方法,但它可以很容易地变成通用且可重复使用的代码,只是想证明我是否能做到。以下是代码,供任何人享受和改进。布局只是一个容器(例如RelativeLayout
)和两个具有ID first
和 second
的文本视图,我已将第二个文本视图的文本颜色设置为红色,以使其更清晰,但这并非必要。
代码
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);
}
}
});
<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>
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);
最完美和精确的解决方案只能通过FontMetrics实现http://docs.oracle.com/javase/8/docs/api/java/awt/FontMetrics.html。使用这个类,我们可以测量字符、字符串等。
不使用任何库。
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent" >
<TextView
android:id="@+id/AAA"
android:layout_toLeftOf="@+id/BBB"
android:layout_height="wrap_content"
android:maxLines="2"
android:layout_width="match_parent" />
<TextView
android:id="@+id/BBB"
android:layout_alignParentRight="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</RelativeLayout>
AAAAAA
AAAA..BBBBB
好的,在注释中它不起作用,但是A文本不会覆盖B文本。它不会环绕... 不符合要求。 - Stephane Maarek你可以使用 HTML
myTextView.setText(Html.fromHtml("<p>Any html code</p>"));