1. 基础介绍
TextView 是 Android 中最基础的 UI 组件之一,用于显示文本内容。
基本属性
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="16sp"
android:textColor="#000000" />
2. 文本内容相关属性
2.1 文本显示
<TextView
android:text="显示文本"
android:hint="提示文本" <!-- 提示文字 -->
android:textColorHint="#999999" <!-- 提示文字颜色 -->
android:text="@string/app_name" /> <!-- 引用字符串资源 -->
2.2 文本样式
<TextView
android:textStyle="bold" <!-- normal|bold|italic -->
android:textSize="18sp"
android:textColor="#FF5722"
android:textAllCaps="true" <!-- 全部大写 -->
android:fontFamily="sans-serif" <!-- 字体族 -->
android:typeface="monospace" /> <!-- 字型 -->
2.3 字体资源使用(API 26+)
<TextView
android:fontFamily="@font/roboto_regular" />
<!-- 或在代码中 -->
TextView textView = findViewById(R.id.textView);
Typeface typeface = ResourcesCompat.getFont(context, R.font.roboto_regular);
textView.setTypeface(typeface);
3. 布局和对齐
3.1 对齐方式
<TextView
android:gravity="center" <!-- 文本在 View 内的对齐 -->
android:textAlignment="center" <!-- 文本对齐方式 -->
android:layout_gravity="center" /> <!-- View 在父容器中的对齐 -->
gravity 常用值:
-
left|right|start|end- 水平对齐 -
top|bottom|center_vertical- 垂直对齐 -
center- 居中 -
fill- 填充
3.2 尺寸和边距
<TextView
android:layout_width="match_parent" <!-- wrap_content|match_parent|具体数值 -->
android:layout_height="wrap_content"
android:minWidth="100dp"
android:minHeight="40dp"
android:maxWidth="200dp"
android:maxHeight="80dp"
android:padding="16dp"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:layout_margin="8dp" />
4. 文本溢出处理
4.1 单行和多行显示
<TextView
android:singleLine="true" <!-- 已废弃,推荐使用 maxLines -->
android:maxLines="3" <!-- 最大行数 -->
android:minLines="1" <!-- 最小行数 -->
android:lines="2" <!-- 固定行数 -->
android:ellipsize="end" <!-- 省略号位置 -->
android:breakStrategy="simple" <!-- 换行策略 -->
android:hyphenationFrequency="normal" /> <!-- 连字符频率 -->
ellipsize 选项:
-
end- 在末尾显示省略号 -
start- 在开头显示省略号 -
middle- 在中间显示省略号 -
marquee- 跑马灯效果
4.2 跑马灯效果
<TextView
android:id="@+id/marqueeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:focusable="true"
android:focusableInTouchMode="true"
android:scrollHorizontally="true"
android:text="这是一个很长的文本,将会以跑马灯效果显示..." />
代码中需要设置:
TextView marqueeText = findViewById(R.id.marqueeText);
marqueeText.setSelected(true); // 启动跑马灯
5. 富文本显示
5.1 SpannableString 使用
String text = "这是一个富文本示例";
SpannableString spannableString = new SpannableString(text);
// 设置前景色
spannableString.setSpan(new ForegroundColorSpan(Color.RED), 2, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置背景色
spannableString.setSpan(new BackgroundColorSpan(Color.YELLOW), 5, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置粗体
spannableString.setSpan(new StyleSpan(Typeface.BOLD), 8, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置斜体
spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 11, 13, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置下划线
spannableString.setSpan(new UnderlineSpan(), 14, 16, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置删除线
spannableString.setSpan(new StrikethroughSpan(), 17, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置字体大小
spannableString.setSpan(new AbsoluteSizeSpan(24, true), 20, 22, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置相对大小
spannableString.setSpan(new RelativeSizeSpan(1.5f), 23, 25, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置上标/下标
spannableString.setSpan(new SuperscriptSpan(), 26, 28, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new SubscriptSpan(), 29, 31, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置点击事件
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
Toast.makeText(MainActivity.this, "点击了文本", Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(Color.BLUE);
ds.setUnderlineText(false);
}
};
spannableString.setSpan(clickableSpan, 32, 34, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
textView.setMovementMethod(LinkMovementMethod.getInstance()); // 启用点击
5.2 HTML 文本显示
// 简单 HTML 支持
String htmlText = "这是<b>粗体</b>文本,这是<i>斜体</i>文本,<font color='red'>红色文字</font>";
textView.setText(Html.fromHtml(htmlText, Html.FROM_HTML_MODE_COMPACT));
// 自定义 HTML 标签处理
Html.ImageGetter imageGetter = new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
// 处理图片
return null;
}
};
Html.TagHandler tagHandler = new Html.TagHandler() {
@Override
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
// 处理自定义标签
}
};
6. 自动链接识别
6.1 XML 配置
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="all" <!-- 识别所有类型链接 -->
android:linksClickable="true"
android:text="官网: https://www.example.com
邮箱: test@example.com
电话: 13800138000
地址: 北京市朝阳区" />
autoLink 选项:
-
none- 不自动识别 -
web- 识别网址 -
email- 识别邮箱 -
phone- 识别电话 -
map- 识别地址 -
all- 识别所有类型
6.2 代码配置
textView.setAutoLinkMask(Linkify.ALL);
textView.setLinksClickable(true);
// 自定义链接识别
Linkify.addLinks(textView, Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES);
// 自定义正则表达式匹配
Pattern pattern = Pattern.compile("#\\w+");
Linkify.addLinks(textView, pattern, "content://com.example.app/tag/");
7. 自定义字体和样式
7.1 使用 Assets 中的字体
// 方法1:通过 Typeface
Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/custom_font.ttf");
textView.setTypeface(typeface);
// 方法2:通过 ResourcesCompat(推荐)
Typeface typeface = ResourcesCompat.getFont(this, R.font.custom_font);
textView.setTypeface(typeface);
7.2 字体样式组合
// 设置粗体
textView.setTypeface(null, Typeface.BOLD);
// 设置斜体
textView.setTypeface(null, Typeface.ITALIC);
// 粗斜体
textView.setTypeface(null, Typeface.BOLD_ITALIC);
8. 文本选择和复制
8.1 启用文本选择
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
android:selectAllOnFocus="true"
android:text="可以选择和复制的文本" />
8.2 自定义选择操作
textView.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// 创建自定义菜单
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// 准备菜单
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// 处理菜单项点击
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// 销毁模式
}
});
9. 阴影和视觉效果
9.1 文本阴影
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="带阴影的文本"
android:shadowColor="#80000000"
android:shadowDx="2" <!-- X轴偏移 -->
android:shadowDy="2" <!-- Y轴偏移 -->
android:shadowRadius="4" <!-- 阴影模糊半径 -->
android:textColor="#FFFFFF" />
9.2 代码设置阴影
textView.setShadowLayer(4, 2, 2, Color.parseColor("#80000000"));
10. 国际化支持
10.1 多语言支持
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<!-- 在 res/values/strings.xml -->
<string name="hello_world">Hello World!</string>
<!-- 在 res/values-zh/strings.xml -->
<string name="hello_world">你好世界!</string>
10.2 RTL(从右到左)支持
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textDirection="locale" <!-- 跟随系统语言方向 -->
android:textAlignment="viewStart" />
11. 性能优化技巧
11.1 减少过度绘制
<!-- 避免不必要的背景 -->
<TextView
android:background="@null" />
<!-- 使用 selector 代替代码设置背景 -->
<TextView
android:background="@drawable/text_bg_selector" />
11.2 文本测量优化
// 预计算文本尺寸
TextPaint textPaint = textView.getPaint();
float textWidth = textPaint.measureText(textView.getText().toString());
float textHeight = textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top;
// 对于固定文本,设置固定尺寸
textView.setWidth((int) textWidth);
textView.setHeight((int) textHeight);
12. 实用工具方法
12.1 工具类示例
public class TextViewUtils {
// 设置文本并保持滚动位置
public static void setTextKeepState(TextView textView, String text) {
int scrollX = textView.getScrollX();
int scrollY = textView.getScrollY();
textView.setText(text);
textView.scrollTo(scrollX, scrollY);
}
// 高亮特定关键词
public static void highlightText(TextView textView, String keyword, int color) {
String text = textView.getText().toString();
SpannableString spannable = new SpannableString(text);
Pattern pattern = Pattern.compile(Pattern.quote(keyword));
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
spannable.setSpan(
new ForegroundColorSpan(color),
matcher.start(),
matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
textView.setText(spannable);
}
// 为 TextView 添加图标
public static void setCompoundDrawable(TextView textView,
@DrawableRes int drawableRes,
int position) {
Drawable drawable = ContextCompat.getDrawable(textView.getContext(), drawableRes);
if (drawable != null) {
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
}
switch (position) {
case 0: // left
textView.setCompoundDrawables(drawable, null, null, null);
break;
case 1: // top
textView.setCompoundDrawables(null, drawable, null, null);
break;
case 2: // right
textView.setCompoundDrawables(null, null, drawable, null);
break;
case 3: // bottom
textView.setCompoundDrawables(null, null, null, drawable);
break;
}
}
}
13. 常见问题解决
13.1 文本显示不全
<!-- 解决方案 -->
<TextView
android:layout_width="0dp" <!-- 使用 ConstraintLayout 时 -->
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end" />
13.2 链接点击无效
// 需要设置 MovementMethod
textView.setMovementMethod(LinkMovementMethod.getInstance());
13.3 自定义字体内存泄漏
// 使用 Application Context 或缓存 Typeface
public class FontCache {
private static Hashtable<String, Typeface> fontCache = new Hashtable<>();
public static Typeface get(String name, Context context) {
Typeface tf = fontCache.get(name);
if (tf == null) {
try {
tf = Typeface.createFromAsset(context.getAssets(), name);
fontCache.put(name, tf);
} catch (Exception e) {
return null;
}
}
return tf;
}
}
TextView 是 Android 开发中最基础且功能丰富的组件之一,掌握其各种用法对于开发高质量的 Android 应用至关重要。