Android TextView 的基本使用方法和常用功能

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 应用至关重要。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容