当前有个需求.显示一段文本,文本最多显示两行,点击展开后才显示完全。当没有显示完全的时候,需要在文本的第二行末尾显示图标,点击图标和文本,文本展开。
难点在于图标需要和第二行文本显示在同一行,高度和文本一致,居中显示。看似简单 实则思路不好想。最后搞了两天,用html富文本解决。
当中涉及到英文换行的坑 然后涉及到汉字全角 半角导致布局问题的坑。
代码如下
布局文件:
<TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_margin="10dp"android:layout_height="match_parent"android:maxLines="2"android:ellipsize="end"android:breakStrategy="balanced"/>
Activity如下
package com.example.myapplication;import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Html;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.Gravity;
import android.view.ViewTreeObserver;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private String str = "我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱我爱";private boolean isDeal = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView textView = findViewById(R.id.textView);textView.setText(toDBC(str));dealStr(textView);}public static String toDBC(String input) {char[] c = input.toCharArray();for (int i = 0; i < c.length; i++) {if (c[i] == 12288) {// 全角空格为12288,半角空格为32c[i] = (char) 32;continue;}if (c[i] > 65280 && c[i] < 65375)// 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248c[i] = (char) (c[i] - 65248);}return new String(c);}private void dealStr(TextView textView) {// 在TextView绘制完成后获取省略的字符数ViewTreeObserver vto = textView.getViewTreeObserver();vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);if (isDeal) {return;}isDeal = true;int ellipsisCount = 0;Layout layout = textView.getLayout();if (layout != null) {int lineCount = layout.getLineCount();if (lineCount > 0) {int lastLineIndex = lineCount - 1;// 输出省略的字符数ellipsisCount = layout.getEllipsisCount(lastLineIndex);}}// 获取文本内容CharSequence fullText = textView.getText();if (ellipsisCount > 0) {// 截断发生// 获取截断后的文本CharSequence truncatedText = fullText.subSequence(fullText.length() - ellipsisCount, fullText.length());CharSequence un_truncatedText = fullText.subSequence(0, fullText.length() - ellipsisCount);String truncatedString = truncatedText.toString();replaceStr(textView, un_truncatedText.toString());} else {// 没有截断发生replaceStr(textView, textView.getText().toString());}}});}private void replaceStr(TextView textView, String tex) {SpannableStringBuilder builder = new SpannableStringBuilder();// 添加HTML文本内容String htmlText = "<html><body>" + tex + "</body></html>";builder.append(Html.fromHtml(htmlText));// 获取Drawable图标Drawable icon = getResources().getDrawable(R.drawable.expand_icon);icon.setBounds((int) textView.getTextSize(), 0, icon.getIntrinsicWidth() + (int) textView.getTextSize(), icon.getIntrinsicHeight());// 创建一个ImageSpan来显示图标ImageSpan iconSpan = new ImageSpan(icon, ImageSpan.ALIGN_CENTER);// 将ImageSpan添加到SpannableStringBuilder的末尾builder.setSpan(iconSpan, builder.length() - 2, builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);// 设置TextView的文本内容textView.setText(builder);// 垂直居中显示文本和图标textView.setGravity(Gravity.CENTER_VERTICAL);}
}