Android中我们用到的最多的UI组件或许就是TextView了,也许很多初学者都会被它的中文翻译所误导,认为TextView只是像他的中文名称一样“文本框”只能用于显示普通字符串,也许还一度以为TextView是最简单的控件,其实不然TextView差不多是其他很多UI组件的基类,比如说我们熟悉的Button、CheckedTextView, DigitalClock, EditText 等等都是 直接或者间接继承了TextView。更重要的是TextView还能显示图片、超链接形式的文本、emoj表情混合字符串形式、图片混合字符串形式等等。
/*String format(String format, Object... args) 转换符就相当于是占位符*/
public static void main(String[] args) {
String str=null;
str=String.format("Hello,%s", "Wolrd");//字符串类型转换符,此时的转换符有点类似占位符,用后面的参数替换掉转换符
System.out.println(str);//Hello,Wolrd
str=String.format("Hello,%s:%s.%s", "World","Java","android");
System.out.println(str); //Hello,World:Java.android
System.out.println("字符类型转换符:%c", 'Z');
System.out.println("布尔类型转换符%b", 1>2); //false
System.out.println("整数类型转换符(10进制):%d ", 100);
System.out.println("整数类型转换符(16进制):%x ", 100);
System.out.println("整数类型转换符(8进制):%o ", 100);
System.out.println("浮点类型转换符:%f元", 99*0.15);
System.out.println("浮点类型转换符(16进制):%a %n", 65*0.85);
System.out.println("指数类型的转换符表示:%e %n", 50*0.85);
System.out.println("通用浮点类型(f和e类型中较短的):%g ", 555*0.85);
System.out.println("百分比类型是%f%% %n", 85);//百分比转换符%%
System.out.println("散列码转换符:%h", 'A');
}
String str=String.format("格式参数$的使用:%1$d,%2$s", 99,"abc"); //$使用
System.out.println(str); //格式参数$的使用:99,abc
System.out.printf("显示正负数的符号:%+d与%d%n", 99,-99); //+使用, 显示正负数的符号:+99与-99
System.out.printf("补零操作,第二个数字是补足多少位:最牛的编号是:%04d%n", 99); //补O使用,补零操作,第二个数字是补足多少位:0099
System.out.printf("Tab键的效果是:% 8d%n", 7); //空格使用,Tab键的效果是: 7
System.out.printf("用,分组会计的金额格式%,d%n", 9999999); //.使用, 整数分组的效果是:9,999,998
System.out.printf("一本书的价格是:% 50.5f元%n", 49.8); //空格和小数点后面个数 一本书的价格是: 49.80000元
System.out.printf("c 的使用输出全部日期和时间信息:%tc%n",date);///c 的使用输出全部日期和时间信息:星期四 十月 8 22:23:36 CST 2015
System.out.printf("F 的使用年-月-日格式:%tF%n",date);//F 的使用年-月-日格式:2015-10-8
System.out.printf("d 的使用月/日/年格式:%tD%n",date);//d的使用月/日/年格式:10/08/15
System.out.printf("r 的使用HH:MM:SS PM格式(12时制):%tr%n",date);//r 的使用HH:MM:SS PM格式(12时制):10:23:36 上午
System.out.printf("HH:MM格式(24时制):%tR%n",date); //R 的使用HH:MM格式(24时制):22:23
System.out.printf("t 的使用HH:MM:SS格式(24时制):%tT%n",date);//t 的使用HH:MM:SS格式(24时制):22:23:36
日期处理
public void main(){
String str=String.format(Locale.US,"使用b得到英文月份简称:%tb",date);
System.out.println(str);/*使用b得到英文月份简称:Oct
System.out.printf("使用b得到本地月份简称:%tb%n",date);//使用b得到本地月份简称:十月
str=String.format(Locale.US,"使用B得到英文月份全称:%tB",date);
System.out.println(str);//使用B得到英文月份全称:October
System.out.printf("使用B得到本地月份全称:%tB%n%n",date);//使用B得到本地月份全称:十月
str=String.format(Locale.US,"使用a得到英文星期的简称:%ta%n",date);
System.out.println(str);//使用a得到英文星期的简称:Thu
System.out.printf("使用a得到本地星期的简称:%ta%n",date);//使用a得到本地星期的简称:星期四
str=String.format(Locale.US,"使用A得到英文星期的全称:%tA%n",date);
System.out.println(str);//使用A得到英文星期的全称:Thursday
System.out.printf("使用A得到本地星期的全称:%tA%n",date);//使用A得到本地星期的全称:星期四
System.out.printf("年的前两位数字(不足两位前面补0):%tC%n",date);//年的前两位数字(不足两位前面补0):20
System.out.printf("年的后两位数字(不足两位前面补0):%ty%n",date);//年的后两位数字(不足两位前面补0):15
System.out.printf("一年中的天数(即年的第几天):%tj%n",date);//一年中的天数(即年的第几天):281
System.out.printf("两位数字的月份(不足两位前面补0):%tm%n",date);//两位数字的月份(不足两位前面补0):10
System.out.printf("两位数字的日(不足两位前面补0):%td%n",date);//两位数字的日(不足两位前面补0):08
System.out.printf("月份的日(前面不补0):%te%n",date);//月份的日(前面不补0):8
}
时间的处理
public static void main(String[] args) {
Date date = new Date();
//H的使用 :2位数字24时制的小时(不足2位前面补0):23
System.out.printf("2位数字24时制的小时(不足2位前面补0):%tH%n", date);/
//k的使用 :2位数字24时制的小时(前面不补0):23
System.out.printf("2位数字24时制的小时(前面不补0):%tk%n", date);
//I的使用 :2位数字12时制的小时(不足2位前面补0):11
System.out.printf("2位数字12时制的小时(不足2位前面补0):%tI%n", date);
//l的使用 :2位数字12时制的小时(前面不补0):11
System.out.printf("2位数字12时制的小时(前面不补0):%tl%n", date);
//M的使用 :2位数字的分钟(不足2位前面补0):04
System.out.printf("2位数字的分钟(不足2位前面补0):%tM%n", date);
//S的使用 :2位数字的秒(不足2位前面补0):00
System.out.printf("2位数字的秒(不足2位前面补0):%tS%n", date);
//L的使用 :3位数字的毫秒(不足3位前面补0):833
System.out.printf("3位数字的毫秒(不足3位前面补0):%tL%n", date);
//N的使用 :9位数字的毫秒数(不足9位前面补0):833000000
System.out.printf("9位数字的毫秒数(不足9位前面补0):%tN%n", date);
//p的使用 :小写字母的上午或下午标记(英):pm
String str = String.format(Locale.US, "小写字母的上午或下午标记(英):%tp", date);
System.out.println(str);
System.out.printf("小写字母的上午或下午标记(中):%tp%n", date);//小写字母的上午或下午标记(中):下午
//z的使用 :相对于GMT的RFC822时区的偏移量:+0800
System.out.printf("相对于GMT的RFC822时区的偏移量:%tz%n", date);
//Z的使用 :时区缩写字符串:CST
System.out.printf("时区缩写字符串:%tZ%n", date);
//s的使用 :1970-1-1 00:00:00 到现在所经过的秒数:1444316640
System.out.printf("1970-1-1 00:00:00 到现在所经过的秒数:%ts%n", date);
//Q的使用 :1970-1-1 00:00:00 到现在所经过的毫秒数:1444316640833
System.out.printf("1970-1-1 00:00:00 到现在所经过的毫秒数:%tQ%n", date);
}
接受的参数为html格式的文本(即正常语法下的html格式的字符串),可以接受绝大部分html标签,也可以处理自定义的标签。
虽然返回的是Spanned对象,但这个Spanned接口继承了CharSequence所以直接传入setText方法中设置。
String source = "<u>这是<font color='red'>添加下font>划线的部分u>这部分没有处理<font size='20px' color='green'>这部分添加了绿色color>";
txt.setText(Html.fromHtml(source));
public class Html {
public static interface ImageGetter {
public Drawable getDrawable(String source);
}
public static interface TagHandler {
public void handleTag(boolean opening, String tag,Editable output, XMLReader xmlReader);
}
}
ImageGetter imgeGetter=new Html.ImageGetter() {
//当解析到HTML的img标签时自动触发
@Override
public Drawable getDrawable(String source) {
//得到用于替换图片占位符的的真正图片,即真正要显示的图片
}
};
TagHandler tagHandler=new Html.TagHandler() {
@Override
public void handleTag(boolean opening, String tag, Editable output,XMLReader xmlReader) {
//每一个标签都会遍历到
}
};
String source="<b>这格式化后的字符串b>插入的图像<img src='ic_launcher.png'/><font color='green'> ImageGetter就是用于解析img标签的font>";
txt.setText(Html.fromHtml(source,imgeGetter,null));
核心思想就是通过fromHtml方法得到Spanned对象,如果需要解析img标签,则需要传递imgeGetter对象;反之则传递null;如果还包含自定义的标签,则需要传递tagHandler对象,反之传递null;最后再把Spanned对象赋值到SetText方法。这样的话实现表情文字混合效果就很easy了,但是不好实现点击事件。
SpannableString和SpannableStringBuilder的基类也是
CharSequence,也能直接把这两个对象赋值到SetText方法。构造了这两个对象还可以通过SetSpan方法来为存储的String添加各种样式和事件(不同的样式的实现在于设置不同的XxxSpan子类就实现了不同的效果)。还有一点值得注意的是这两者的区别和String与StringBuilder是一样的,前者是静态,后者可以动态添加。
BackgroundColorSpan, ClickableSpan, ForegroundColorSpan, MaskFilterSpan, MetricAffectingSpan, RasterizerSpan, StrikethroughSpan, UnderlineSpan ,AbsoluteSizeSpan等
给SpannableString或SpannableStringBuilder特定范围的字符串应用Span样式,如在原来String上加下划线、加背景色、改变字体颜色、用图片把指定的文字给替换掉等,可以同时设置多个(比如同时加上下划线和前景色等),Falgs参数标识了当在所标记范围前和标记范围后紧贴着插入新字符时的动作,即是否对新插入的字符应用同样的样式
void setSpan (XxxSpan what, int start, int end, int flags)
///先构造SpannableString
SpannableString spanString = new SpannableString("这是使用ForegroundColorSpan实现改变字体颜色");
//再构造一个改变字体颜色的Span
ForegroundColorSpan span = new ForegroundColorSpan(Color.GREEN);
BackgroundColorSpan spanbcg = new BackgroundColorSpan(Color.RED);
//将这个Span应用于指定范围的字体
spanString.setSpan(span, 4, 9, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
spanString.setSpan(spanbcg, 5, 12, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
txt.setText(spanString);
SpannableString spanString = new SpannableString("这是使用ImageSpan实现改变");
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
spanString.setSpan(span, 6, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
txt.setText(spanString);
///要想成功实现点击效果必须添加以下四句
//原因:当调用textview的setMovementMethod 或者 setKeyListener,
//TextView 自动修改它的属性:setFocusable(true);
//这也就是说你手动设置的focusable被覆盖掉了,也就需要我们覆写//hasFocusable方法,使其始终返回false。
//2、覆写hasFocusable之后listview的OnItemClick已经可以响应,以有限的大脑容量我以为自定义的LinkMovementMethod可以不要了,可惜注释掉之后发现ClickableSpan不工作了。。。
txt.setMovementMethod(LinkMovementMethod.getInstance());
txt.setFocusable(false);
txt.setClickable(false);
txt.setLongClickable(false);
SpannableString spanString = new SpannableString("这是使用怒戳ImageSpan这里");
ClickableSpan clickSpan=new ClickableSpan(){
@Override
public void onClick(View widget) {
Log.d("TagClick","cickSPan");
Toast.makeText(getBaseContext(), "这就是用ClickSpan实现的点击!", Toast.LENGTH_LONG).show();
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(true);
}
};
spanString.setSpan(clickSpan, 6, 16, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
txt.setText(spanString);
txt.setLinkTextColor(Color.RED);
//必须添加这一段
txt.setMovementMethod(LinkMovementMethod.getInstance());
txt.setFocusable(false);
txt.setClickable(false);
txt.setLongClickable(false);