题外话—距上一次写博客已经有半年之久了,不是因为不想写,实在是懒癌晚期发作,每次准备写写博客记录一些东西的时候就想着明天吧,明天吧,不知不觉居然都有半年了,以后一定会改掉的!!!
在我们android开发中经常会遇到一些需求,就像下面这个样子: 然后大家看看我以前的实现方式吧…
textInfoDesc.setText(Html.fromHtml(String.format("我从<font color='#cc4d6c'>%s</font>上车", mPlaceEntity.getName()))); 或者是这样子的 <string name="game_table_number"><Data><![CDATA[当前处于<font color="#F3DE31"><b>%1$s</b></font>号桌]]></Data></string> table_number.setText(String.format(getString(R.string.game_table_number), obj.getBoot_no_now()));真的很复杂啊有木有,有时候时间久了,又记不住了然后又要翻翻以前的代码.好麻烦!!!
这个时候我们就需要SpannableString这个东西了.首先简单说下这个类,SpannableString和String都是字符串类型,textview可以直接设置,然后SpannableString可以通过使用其setSpan方法实现字符串各种不同样式的文本,并且可以指定区间,废话不多说,赶紧来看效果吧.
代码就是简单的几句:
SpannableString str1 = new SpannableString("设置背景色为红色"); BackgroundColorSpan colorSpan1 = new BackgroundColorSpan(0xffff0000); str1.setSpan(colorSpan1, 2, str1.length() - 3, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv1.setText(str1); SpannableString str2 = new SpannableString("设置字体颜色为绿色"); ForegroundColorSpan colorSpan2 = new ForegroundColorSpan(0xff00ff00); str2.setSpan(colorSpan2, 2, str2.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv2.setText(str2);这里顺便说的小知识点. 在java代码中如果要直接设置颜色值的话可以用0xffff0000,其中0x就代表xml中的#,其余的和xml中的用法一样,只是在java中必须添加最前面的透明度,也就是说在java中要直接设置必须是8位.
然后说一下setSpan(Object what, int start, int end, int flags)的几个参数意思,第一个意思就是文本的格式,后面2个比较简单,就是起始下标和终点下标,不过最有趣的还是最后一个参数的意思,呵呵,真的很有趣,对于理解能力不好的人来说简直就是坑人.秉着不就是几个不同的flag嘛.我大不了写4个text每个设置个不同的看看效果不就好了,写完发现.wtf?这明明就是一样的啊!!!网上其他帖子都这样说: Spanned.SPAN_INCLUSIVE_EXCLUSIVE 从起始位置到终点位置,只包括起始位置 [0,1); Spanned.SPAN_INCLUSIVE_INCLUSIVE 从起始位置到终点位置,包括起始位置和终点位置 [0,1]; Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 从起始位置到终点位置,包括起始位置和终点位置(0,1); Spanned.SPAN_EXCLUSIVE_INCLUSIVE 从起始位置到终点位置,只包括终点位置(0,1] 其实上面说的很模糊很不准确..所以大家不要记这里
顿时我就懵逼了… 后来查资料,才发现原来没那么简单…通过edittext就可以发现不同点:
SpannableString str5 = new SpannableString("大家请看这里"); ForegroundColorSpan colorSpan5 = new ForegroundColorSpan(0xffff0000); str5.setSpan(colorSpan5, 0, 5, Spanned.SPAN_EXCLUSIVE_INCLUSIVE); ed.setText(str5);就以SPAN_EXCLUSIVE_INCLUSIVE为例.刚运行完的结果: 加了几个字母: 又多加了几个字母: 是不是发现了规律了. 在以SPAN_INCLUSIVE_EXCLUSIVE 为例:
SpannableString str5 = new SpannableString("大家请看这里"); ForegroundColorSpan colorSpan5 = new ForegroundColorSpan(0xffff0000); str5.setSpan(colorSpan5, 1, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); ed.setText(str5);刚运行完的结果: 然后: 多输几个: 相信大家已经大概知道这几个参数的意思了,表达能力不好,不知道怎么概述这里,希望大家能明白(其实我觉得这个属性好鸡肋啊!!!) 好了,接下来继续介绍其他方法:RelativeSizeSpan,在原文字大小的基础上设置文字相对大小:
float[] size = new float[]{1.2f, 1.4f, 1.6f, 1.8f, 2.0f, 2.2f}; SpannableString str1 = new SpannableString("雄赳赳气昂昂"); for (int i = 0; i < 6; i++){ RelativeSizeSpan span = new RelativeSizeSpan(size[i]); str1.setSpan(span, i, i+1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } tv1.setText(str1);接下来是StrikethroughSpan,这个可以为文本添加删除线:
SpannableString str2 = new SpannableString("原价100.0元"); StrikethroughSpan span2 = new StrikethroughSpan(); str2.setSpan(span2, 0, str2.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv2.setText(str2);顺便给大家看看2年前我是怎么实现的,简直蠢到家了,下面这个是原来的实现方法
下划线UnderlineSpan:
SpannableString str = new SpannableString("原价100.0元"); UnderlineSpan span = new UnderlineSpan(); str.setSpan(span, 0, str.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv2.setText(str);SuperscriptSpan和SubscriptSpan,上标和下标:
SpannableString str = new SpannableString("设置上标"); SuperscriptSpan span = new SuperscriptSpan(); str.setSpan(span, 2, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); tv2.setText(str); SpannableString str1 = new SpannableString("设置下标"); SubscriptSpan span1 = new SubscriptSpan(); str1.setSpan(span1, 2, str1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); tv3.setText(str1);这里需要注意的是,这里的字体大小都是一样的,如果不设置padding或者不设置上下标的字体大小(RelativeSizeSpan)显示出来的效果就是这样:
StyleSpan:设置字体风格
SpannableString str = new SpannableString("粗体、斜体"); StyleSpan span1 = new StyleSpan(Typeface.BOLD); StyleSpan span2 = new StyleSpan(Typeface.ITALIC); str.setSpan(span1, 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); str.setSpan(span2, 3, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); tv2.setText(str);ImageSpan:设置表情(不调setBounds相当于宽高为0,不显示)
SpannableString str = new SpannableString("添加表情"); Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_launcher); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); ImageSpan imageSpan = new ImageSpan(drawable); str.setSpan(imageSpan, 2, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv2.setText(str);UrlSpan:超链接,注意,使用ClickableSpan的文本必须为TextView设置setMovementMethod方法,否则没有点击相应事件,另外android:textColorHighlight=”@color/colorPrimary” 可以设置colorHighLight属性,这个是设置点击时的背景色的;
SpannableString str = new SpannableString("跳转至百度首页"); URLSpan span = new URLSpan("http://www.baidu.com"); str.setSpan(span, 3, str.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv2.setMovementMethod(LinkMovementMethod.getInstance()); tv2.setText(str);ClickableSpan:点击事件.注意ClickableSpan是一个接口,需要自己实现里面的onClick点击事件,查看源码还可以知道setColor设置的文字的颜色.setUnderlineText方法是设置下划线
SpannableString str = new SpannableString("为文本添加点击事件"); MyClickSpan span = new MyClickSpan(); str.setSpan(span, 5, str.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv2.setMovementMethod(MyLinckMoveMentMehtod.getInstance()); tv2.setText(str); class MyClickSpan extends ClickableSpan{ /** * Makes the text underlined and in the link color. */ @Override public void updateDrawState(TextPaint ds) { //super.updateDrawState(ds); ds.setColor(0xff00ff00); ds.setUnderlineText(true); } @Override public void onClick(View widget) { Toast.makeText(LoginAty.this, "响应了点击事件", Toast.LENGTH_SHORT).show(); } }接下来会有一个奇怪的问题,就是点击之后的背景色的问题.这里我们需要重写ouTouch方法,复制一份源码,然后稍作修改
static class MyLinckMoveMentMehtod extends LinkMovementMethod{ private static MyLinckMoveMentMehtod sInstance; public static MovementMethod getInstance() { if (sInstance == null) sInstance = new MyLinckMoveMentMehtod(); return sInstance; } @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); buffer.setSpan(new BackgroundColorSpan(Color.TRANSPARENT), buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Selection.removeSelection(buffer); } else if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } return true; } else { Selection.removeSelection(buffer); } } return super.onTouchEvent(widget, buffer, event); } }MaskFilterSpan浮雕(EmbossMaskFilter)和模糊(BlurMaskFilter)效果
SpannableString str = new SpannableString("文字模糊效果"); MaskFilterSpan span = new MaskFilterSpan(new BlurMaskFilter(1.1f, BlurMaskFilter.Blur.SOLID)); str.setSpan(span, 2, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); tv2.setText(str);还有一个类,SpannableStringBuilder,可以通过其setSpan和append方法拼接各种各样不同的效果. 希望大家和我一样能够自己敲一遍,最后也可以写一个博客记录一下这个过程.不止印象能深刻以后忘记了也可以随时回来翻(0.0),hhh.