热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

TextView那些鲜为人知的方法

综述一起先看看官方文档怎么说的:Displaystexttotheuserandoptionallyallowsthemtoeditit.ATextVie

综述


一起先看看官方文档怎么说的:

Displays text to the user and optionally allows them to edit it. A TextView is a complete text editor, however the basic class is configured to not allow editing; see EditText for a subclass that configures the text view for editing.

To allow users to copy some or all of the TextView’s value and paste it somewhere else, set the XML attribute android:textIsSelectable to “true” or call setTextIsSelectable(true). The textIsSelectable flag allows users to make selection gestures in the TextView, which in turn triggers the system’s built-in copy/paste controls.

这个是官方文档给的概述,这是一个展示文本的一个基类,是EditText的父类,不允许用户编辑,如果想要配置这个类的话,去看看EditText。如果想让用户长按复制的话,可以在xml文件中配置属性android:textIsSelectable=”true”,也可以在代码中设置,setTextIsSelectable(true)即可,相信大家在也熟悉不过了,这次我们了解下TextView鲜为人知的用法。究竟什么用法呢,先看看需求吧,有需求才有实现么。

需求



这里写图片描述
这个是我从Uber乘车软件上截取下来的,因为那时候项目有这个需求。基本就是这样的,上面那段“当有…..详细信息”那块你怎么实现!难道你还用两个TextView拼接在一起嚒?显然不适合,因为,Android设备尺寸,分辨率什么的太多了。很难做到适应每个屏幕。

实现



接下来一起实现下吧,用多个TextView的方式肯定是不行的,得排除掉。那么如何用一个TextView显示不同颜色的文本呢?这里我们有两种方式可以实现:

一、使用Html格式化文字。

  String cOntent= "当好友使用您的优惠码搭乘时,你们都\n将获得¥30!<font color='red'>详细信息font>";
uber1.setText(Html.fromHtml(content));

这样我们可以通过写Html的方式来显示文本,可以控制它的大小,颜色,字体。但是,这种解析也并不一定是万能的,我们跟进Html的源码看看:

   private void handleStartTag(String tag, Attributes attributes) {
if (tag.equalsIgnoreCase("br")) {
// We don't need to handle this. TagSoup will ensure that there's a
for each

// so we can safely emite the linebreaks when we handle the close tag.
} else if (tag.equalsIgnoreCase("p")) {
handleP(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("div")) {
handleP(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("strong")) {
start(mSpannableStringBuilder, new Bold());
} else if (tag.equalsIgnoreCase("b")) {
start(mSpannableStringBuilder, new Bold());
} else if (tag.equalsIgnoreCase("em")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("cite")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("dfn")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("i")) {
start(mSpannableStringBuilder, new Italic());
} else if (tag.equalsIgnoreCase("big")) {
start(mSpannableStringBuilder, new Big());
} else if (tag.equalsIgnoreCase("small")) {
start(mSpannableStringBuilder, new Small());
} else if (tag.equalsIgnoreCase("font")) {
startFont(mSpannableStringBuilder, attributes);
} else if (tag.equalsIgnoreCase("blockquote")) {
handleP(mSpannableStringBuilder);
start(mSpannableStringBuilder, new Blockquote());
} else if (tag.equalsIgnoreCase("tt")) {
start(mSpannableStringBuilder, new Monospace());
} else if (tag.equalsIgnoreCase("a")) {
startA(mSpannableStringBuilder, attributes);
} else if (tag.equalsIgnoreCase("u")) {
start(mSpannableStringBuilder, new Underline());
} else if (tag.equalsIgnoreCase("sup")) {
start(mSpannableStringBuilder, new Super());
} else if (tag.equalsIgnoreCase("sub")) {
start(mSpannableStringBuilder, new Sub());
} else if (tag.length() == 2 &&
Character.toLowerCase(tag.charAt(0)) == 'h' &&
tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {
handleP(mSpannableStringBuilder);
start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1'));
} else if (tag.equalsIgnoreCase("img")) {
startImg(mSpannableStringBuilder, attributes, mImageGetter);
} else if (mTagHandler != null) {
mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader);
}
}

这个是解析开始标签的方法,我们可以看到,他只支持这些标签,但是Google还做了一些拓展,如果你用到了其他标签或者是自定义标签,你可以通过实现

 /**
* Is notified when HTML tags are encountered that the parser does
* not know how to interpret.
*/

public static interface TagHandler {
/**
* This method will be called whenn the HTML parser encounters
* a tag that it does not know how to interpret.
*/

public void handleTag(boolean opening, String tag,
Editable output, XMLReader xmlReader);
}

这个接口,来实现自己的业务需求。有一点需要注意的是,如果你想在TextView上用标签时,还需要实现一个接口:

/**
* Retrieves images for HTML tags.
*/

public static interface ImageGetter {
/**
* This method is called when the HTML parser encounters an
* tag. The source argument is the
* string from the "src" attribute; the return value should be
* a Drawable representation of the image or null
* for a generic replacement image. Make sure you call
* setBounds() on your Drawable if it doesn't already have
* its bounds set.
*/

public Drawable getDrawable(String source);
}

其中的英文解释的已经很清楚了,这里也不做赘述了,但是它强调的是一定要给图片设置边界,然后再forHtml()方法中将自己实现的接口放进去就行了。

二、 通过SpannableString来设置文本内容
通过这个类可以给他设置各种类型的span,常见的span的类型有一下这些,都通过一些实例来说明用法:

//设置字体(default,default-bold,monospace,serif,sans-serif)  msp.setSpan(new TypefaceSpan("monospace"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

//设置字体大小(绝对值,单位:像素)
msp.setSpan(new AbsoluteSizeSpan(20), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

//设置字体大小(相对值,单位:像素) 参数表示为默认字体大小的多少倍 msp.setSpan(new RelativeSizeSpan(0.5f), 8, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //0.5f表示默认字体大小的一半

//设置字体前景色
msp.setSpan(new ForegroundColorSpan(Color.MAGENTA), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //设置前景色为洋红色

//设置字体背景色
msp.setSpan(new BackgroundColorSpan(Color.CYAN), 15, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //设置背景色为青色

//设置字体样式正常,粗体,斜体,粗斜体
msp.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 18, 20, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //正常

//设置下划线
msp.setSpan(new UnderlineSpan(), 27, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

//设置删除线
msp.setSpan(new StrikethroughSpan(), 30, 33, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

//设置上下标
msp.setSpan(new SubscriptSpan(), 34, 35, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //下标
msp.setSpan(new SuperscriptSpan(), 36, 37, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //上标

//超级链接(需要添加setMovementMethod方法附加响应) msp.setSpan(new URLSpan("tel:4155551212"), 37, 39, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //电话
TextView.setMovementMethod(LinkMovementMethod.getInstance());

其中:
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE等的作用:
用来标识在 Span 范围内的文本前后输入新的字符时是否把它们也应用这个效果。分别有 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)、Spanned.SPAN_INCLUSIVE_EXCLUSIVE(前面包括,后面不包括)、Spanned.SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,后面包括)、Spanned.SPAN_INCLUSIVE_INCLUSIVE(前后都包括)。

那么,这种方法和上面的方法有什么区别呢,其实使用上面的那种方法,最后也是一样的调用第二种方式来格式化的,只不过android系统帮我们解析了html而已。我们使用起来比较方便,但是尽量的使用第二种方法,因为,性能更高。并且使用第二种方法的时候,还有其他的优势,就是我们可以自定义span,比如:还是那个需求,再增加一个功能,点击详细信息,可以弹出个框,提示用户一些重要的信息。
我们自定义个span继承ClickableSpan,URLSpan也是继承ClickableSpan的:

    private class MyClickPan extends ClickableSpan{

private final String mURL;

public MyClickPan(String url){
mURL = url;
}

@Override
public void onClick(View widget) {

if(mURL != null){
Toast.makeText(widget.getContext(),"uri = "+mURL,Toast.LENGTH_SHORT).show();
}
}

@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
//取消下划线
ds.setUnderlineText(false);
ds.setColor(Color.RED);
}
}

然后再给SpannableString.setPan就可以了:

   SpannableString spannableString = new SpannableString(values[0]);
spannableString.setSpan(new MyClickPan("Nipuream"), values[0].indexOf("!") + 1, values[0].length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
uber.setText(spannableString);
uber.setHighlightColor(Color.WHITE);
uber.setMovementMethod(LinkMovementMethod.getInstance());

这样就实现了我们的需求。


推荐阅读
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文介绍了Java中Currency类的getInstance()方法,该方法用于检索给定货币代码的该货币的实例。文章详细解释了方法的语法、参数、返回值和异常,并提供了一个示例程序来说明该方法的工作原理。 ... [详细]
  • 代理模式的详细介绍及应用场景
    代理模式是一种在软件开发中常用的设计模式,通过在客户端和目标对象之间增加一层中间层,让代理对象代替目标对象进行访问,从而简化系统的复杂性。代理模式可以根据不同的使用目的分为远程代理、虚拟代理、Copy-on-Write代理、保护代理、防火墙代理、智能引用代理和Cache代理等几种。本文将详细介绍代理模式的原理和应用场景。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • 展开全部可以用反射根据给定的类名来动态生成实例62616964757a686964616fe59b9ee7ad9431333337613839比如你定义了一个类packagesam ... [详细]
  • 四、连接屏幕流各位读者好!我们已经到了应用开发的一个重要阶段——连接屏幕。如您所知,我们在上一章 ... [详细]
  • 先上图引入插件在pubspec.yaml中引入charts_flutter插件使用的时候版本到0.6.0,插件地址:https:github.comgooglecharts使用插件 ... [详细]
  • 4、迭代器标准STL容器提供了四种不同的迭代器:iterator、const_iterator、reverse_iterator和const_reverse_iter ... [详细]
author-avatar
mobiledu2502882721
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有