荣耀彩票代理

IT技术互动交流平台

AndroidSpannableString浅析

来源:IT165收集  发布日期:2016-05-16 20:47:49

引言

ZAIYINGYONGCHENGXUKAIFAGUOCHENGJINGCHANGXUYAODUIWENBENJINXINGCHULI,BIRUSHUODUIYIDUANMIAOSHUWENZIDEQIZHONGYIDUANJIARUDIANJISHIJIAN,HUOZHEDUIQISHEZHIBUYIYANGDEQIANJINGSE,YOUSHENMEFANGFAKEYISHIXIANYAOQIUDEGONGNENGNA?

需求样例

比如我们需要实现如下图所示的功能,将文本:#重磅消息#近日谷歌放出Android N的第二个开发者预览版(Developer Preview) 处理成第二种或者第三种的形式。

这里写图片描述

实现方案

GENJUSHANGTU,WOMENKEYICAIYONGRUXIADEFANGFALAISHIXIANSHANGSUYAOQIUDEXIAOGUO。

方案1

BIRUXIANSHIXIAOGUOERNIKEYINENGHUISHUO,WOMENKEYICAIYONGSANGETextViewLAISHIXIAN,DIYIGETextViewSHEZHIBUYIYANGDEYANSE,DIERGEZHENGCHANGXIANSHINEIRONG,DISANGECHULIDIANJISHIJIAN。GAIFANGSHIDUITUERKENENGSHINENGGOUSHIXIANDE,DANSHIRUGUODIERXINGLIMIANJIUYOUBUFENNEIRONGXUYAOJINXINGDIANJICHULI,JIUBIJIAONANYISHIXIANLE。

荣耀彩票代理DUIYUTUSANDEXIAOGUOSHANGSHUDEFANGSHIJIUHENNANSHIXIANLE。BIXUYAODUITextViewDENEIRONGJINXINGCHULILE!!

方案2

如果文案的处理只是简单的对齐,颜色,大小的变换,我们还可以采用自定义view来实现,在前面的文章中我们就采用了自定义view来显示了一个文字的排版效果,具体实现可以查看Android文本排版实现;

方案3

CHULESHANGMIANDEFANGAN,WOMENHAIKEYICAIYONGLINGWAIYIGEZHONGFANGSHILAISHIXIAN,CAIYONGhtmlLAIXIANSHI,KEYIJIANGYAOXIANSHIDENEIRONGZHUANHUANCHENGhtmlDEGESHI,YONGTextViewLAIJINXINGJIAZAI。SHUOLEZHEIMEDUO,WOMENLAIKANKANDAIMABA!

private void setText() {
    String originText = '#重磅消息#近日谷歌放出Android N的第二个开发者预览版(Developer Preview)';

    String effect1 = '<font color='#FF0000'>#重磅消息#</font> <br> 近日谷歌放出Android ' +
            'N的第二个开发者预览版<a href='http://developer.android.com/index.html'>(Developer Preview)</a>';

    String effect2 = '<font color='#303F9F'>#重磅消息#</font> 近日谷歌放出Android ' +
            'N的第二个开发者预览版<a href='http://developer.android.com/index.html'>(Developer Preview)</a>';
    StringBuilder sb = new StringBuilder(originText);
    sb.append('<br><br><br><br>');
    sb.append(effect1);
    sb.append('<br><br><br><br>');
    sb.append(effect2);
    textView.setText(Html.fromHtml(sb.toString()));
    textView.setMovementMethod(LinkMovementMethod.getInstance());
}

XIEDAOZHEI,TURANFAXIANYAOPAOTI,JINJINSHIHtmlDESHIXIANJIUKEYIFENXICHUHENDUODEZHISHIDIAN,BUGUOZHEILIHAISHIXIANQIHEZHUTI,XIANZHEILIWAYIGEKENG,HOUXUDUIhtmlJINXINGFENXI,CHAKANLIANJIE,XIANZAIHAIWEISHIXIAN

方案4

荣耀彩票代理ZHONGYUHUIDAOWOMENDEZHUTILE,ZHEILIWOMENCAIYONGSpannableStringLAISHIXIANSHANGSHUDEXIAOGUO。DAIMARUXIA:

private void setSpan() {
    String originText = '#重磅消息#近日谷歌放出Android N的第二个开发者预览版(Developer Preview)';

    SpannableStringBuilder sb = new SpannableStringBuilder(originText);
    sb.append('
').append('
').append('
');
    getEffect1Span(sb);
    sb.append('
').append('
').append('
');
    getEffect2Span(sb);
    textView.setText(sb);
    textView.setMovementMethod(LinkMovementMethod.getInstance());
}

private void getEffect1Span(SpannableStringBuilder sb) {
    String source1 = '#重磅消息#';
    SpannableString span = new SpannableString(source1);
    span.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorAccent)), 0, source1.length(),
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    sb.append(span);
    sb.append('
');
    String source2 = '近日谷歌放出Android N的第二个开发者预览版';
    sb.append(source2);

    final String source3 = '(Developer Preview)';
    SpannableString clickSpan = new SpannableString(source3);
    clickSpan.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            ToastUtil.showLong(source3);
        }
    }, 0, source3.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    sb.append(clickSpan);
}

private void getEffect2Span(SpannableStringBuilder sb) {
    String source1 = '#重磅消息#近日谷歌放出Android N的第二个开发者预览版';
    SpannableString span = new SpannableString(source1);
    span.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorPrimaryDark)), 0, 6, Spanned
            .SPAN_EXCLUSIVE_EXCLUSIVE);
    sb.append(span);

    final String source2 = '(Developer Preview)';
    SpannableString clickSpan = new SpannableString(source2);
    clickSpan.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            ToastUtil.showLong(source2);
        }
    }, 0, source2.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    sb.append(clickSpan);
}

SHANGSHUDAIMACAIYONGLEYINGBIANMAFANGSHISHIXIAN,ZHENGCHANGSHIXIAN,XUYAOGENJUXUQIUJINXINGSHEZHI。JIDEYAOTIANJIAtextView.setMovementMethod(LinkMovementMethod.getInstance());LAIJIESHOUDIANJISHIJIAN。

SpnnableString详解

荣耀彩票代理SpannableStringJICHENGLESpannableStringInternal,TONGSHISHIXIANLECharSequence, GetChars, SpannableSANGEJIEKOU,ZHENGCHANGCHULIWENBENDEHANSHUWEIsetSpanHANSHU:

public void setSpan(Object what, int start, int end, int flags) {
    super.setSpan(what, start, end, flags);
}

该函数有四个参数,第一个为一个span类型,第二个参数为开始位置,第三个位置为span的结束位置,最后一个为flag参数。
荣耀彩票代理 what可以设置如下类型:

1, AbsoluteSizeSpan SHEZHIWENZIZITIDEJUEDUIDAXIAO, YOULIANGGECANSHU,DIYIGESHIZITIDAXIAO,DIERGESHIDANWEISHIFOUSHIdip

public AbsoluteSizeSpan(int size, boolean dip) {
        mSize = size;
        mDip = dip;
    }

荣耀彩票代理2,AlignmentSpan ZHUYAOSHEZHIWENBENDEDUIQIFANGSHI,YOUSANZHONGFANGSHIZHENGCHANG,JUZHONG,XIANGFANDEFANGSHIDUIQI,MORENSHIXIANWEIStandard

   public Standard(Layout.Alignment align) {
        mAlignment = align;
    }

3,BackgroundColorSpan SHEZHIWENZIDEBEIJINGSE

private void setfCS(){
    String source1 = '#重磅消息#';
    SpannableString span = new SpannableString(source1);
    span.setSpan(new BackgroundColorSpan(getResources().getColor(R.color.colorAccent)), 0, source1.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(span);
}

荣耀彩票代理4,BulletSpan JIWENBENDEKAISHICHUJIASHANGXIANGMUFUHAO。BIRUQIANMIANJIAYIGE .

private void setBSpan() {
    final String source3 = '近日谷歌放出Android N的第二个开发者预览版';
    SpannableString bSpan = new SpannableString(source3);
    bSpan.setSpan(new BulletSpan(), 0, source3.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(bSpan);
}

荣耀彩票代理5, ClickableSpan SHEZHIWENBENDEDIANJISHIJIAN,YAOSHIXIANonClickHANSHU,KEYIFUXIEupdateDrawState,SHEZHIXIAHUAXIAN,HUOZHEQUXIAOXIAHUAXIAN,HAIKEYISHEZHIXIAHUAXIANYANSE

private void setCS(){
    final String source2 = '(Developer Preview)';
    SpannableString clickSpan = new SpannableString(source2);
    clickSpan.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            ToastUtil.showLong(source2);
        }
    }, 0, source2.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(clickSpan);
}

6,DrawableMarginSpan KEYISHEZHIYIGETUBIAO,BINGQIEKEYISHEZHIYUWENZIDEKUANDU

private void setDMSpan() {
    final String source3 = '(Developer Preview)';
    SpannableString dmSpan = new SpannableString(source3);
    dmSpan.setSpan(new DrawableMarginSpan(getResources().getDrawable(R.mipmap.ic_launcher), 30), 0, source3
            .length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(dmSpan);
}

7,DynamicDrawableSpan SHEZHIMOUDUANWENZIBEITUBIAOTIHUAN,XUYAOFANHUIYIGEdrawable

8,EasyEditSpan DANGWENBENGAIBIANHUOZHESHANCHUSHIDIAOYONG, LIRURUXIAZHANGANKEYIHENRONGYISHANCHUYIXING

private void setEdit() {
    editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    editText.setSingleLine(false);
    editText.setText('近日
谷歌放出Android N的
第二个开发者预览版');
    editText.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            final Layout layout = editText.getLayout();
            final int line = layout.getLineForOffset(editText.getSelectionStart());
            final int start = layout.getLineStart(line);
            final int end = layout.getLineEnd(line);
            editText.getEditableText().setSpan(new EasyEditSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            return true;
        }
    });
}

荣耀彩票代理9,ForegroundColorSpan SHEZHIWENZIQIANJINGSE

private void setfCS(){
    String source1 = '#重磅消息#';
    SpannableString span = new SpannableString(source1);
    span.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorAccent)), 0, source1.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setText(span);
}

荣耀彩票代理XIEDAOZHEILIWOTINGXIALAILE。TIANLALU,30DUOGEspan,KEYIQUXITONGDAIMApackage android.text.styleBAOXIACHAKAN,ZHEIMEDUO,ZHENGGERENDOUBUHAOLE。

这里写图片描述
荣耀彩票代理 因此先就针对上面的做了部分样例,之后会专门实现一下每个span的效果。仔细理解一个就行,其他的都是类似的,我们继续看看后面的参数。

DIERCANSHUstartHEDISANGECANSHUend,BIAOSHIDANGSHISHEZHIDEspanZUOYONGXIAOGUODEFANWEI,startBIAOSHIKAISHIWEIZHI,endBIAOSHIJIESHUWEIZHI,DISIGECANSHUSHIYIGEflagBIAOQIAN。ZHEILIZHUYAOSHEZHIYIXIADEZHI:

/**
 * Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand
 * to include text inserted at their starting point but not at their
 * ending point.  When 0-length, they behave like marks.
 */
public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;

/**
 * Spans of type SPAN_INCLUSIVE_INCLUSIVE expand
 * to include text inserted at either their starting or ending point.
 */
public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;

/**
 * Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand
 * to include text inserted at either their starting or ending point.
 * They can never have a length of 0 and are automatically removed
 * from the buffer if all the text they cover is removed.
 */
public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;

/**
 * Non-0-length spans of type SPAN_EXCLUSIVE_INCLUSIVE expand
 * to include text inserted at their ending point but not at their
 * starting point.  When 0-length, they behave like points.
 */
public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;

常用的就是上述的四个值,这里我们来分别解释以下:
1. SPAN_INCLUSIVE_EXCLUSIVE表示左闭右开区间 “[ )”
2. SPAN_INCLUSIVE_INCLUSIVE表示左右都是闭区间 ‘( )’
3. SPAN_EXCLUSIVE_EXCLUSIVE表示左右都是闭区间 ‘[ ]’
4. SPAN_EXCLUSIVE_INCLUSIVE表示左右都是闭区间 ‘( ]’

WOMENJIXULAIKANDAIMA,SpannableStringDEsetSpanYOUJIXUDIAOYONGLESpannableStringInternalDEsetSpanHANSHU。

/* package */ void setSpan(Object what, int start, int end, int flags) {
    int nstart = start;
    int nend = end;

    checkRange('setSpan', start, end);

    if ((flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPH) {
        if (start != 0 && start != length()) {
            char c = charAt(start - 1);

            if (c != '
')
                throw new RuntimeException(
                        'PARAGRAPH span must start at paragraph boundary' +
                        ' (' + start + ' follows ' + c + ')');
        }

        if (end != 0 && end != length()) {
            char c = charAt(end - 1);

            if (c != '
')
                throw new RuntimeException(
                        'PARAGRAPH span must end at paragraph boundary' +
                        ' (' + end + ' follows ' + c + ')');
        }
    }

    int count = mSpanCount;
    Object[] spans = mSpans;
    int[] data = mSpanData;

    for (int i = 0; i < count; i++) {
        if (spans[i] == what) {
            int ostart = data[i * COLUMNS + START];
            int oend = data[i * COLUMNS + END];

            data[i * COLUMNS + START] = start;
            data[i * COLUMNS + END] = end;
            data[i * COLUMNS + FLAGS] = flags;

            sendSpanChanged(what, ostart, oend, nstart, nend);
            return;
        }
    }

    if (mSpanCount + 1 >= mSpans.length) {
        Object[] newtags = ArrayUtils.newUnpaddedObjectArray(
                GrowingArrayUtils.growSize(mSpanCount));
        int[] newdata = new int[newtags.length * 3];

        System.arraycopy(mSpans, 0, newtags, 0, mSpanCount);
        System.arraycopy(mSpanData, 0, newdata, 0, mSpanCount * 3);

        mSpans = newtags;
        mSpanData = newdata;
    }

    mSpans[mSpanCount] = what;
    mSpanData[mSpanCount * COLUMNS + START] = start;
    mSpanData[mSpanCount * COLUMNS + END] = end;
    mSpanData[mSpanCount * COLUMNS + FLAGS] = flags;
    mSpanCount++;

    if (this instanceof Spannable)
        sendSpanAdded(what, nstart, nend);
}

/* package */ void removeSpan(Object what) {
    int count = mSpanCount;
    Object[] spans = mSpans;
    int[] data = mSpanData;

    for (int i = count - 1; i >= 0; i--) {
        if (spans[i] == what) {
            int ostart = data[i * COLUMNS + START];
            int oend = data[i * COLUMNS + END];

            int c = count - (i + 1);

            System.arraycopy(spans, i + 1, spans, i, c);
            System.arraycopy(data, (i + 1) * COLUMNS,
                             data, i * COLUMNS, c * COLUMNS);

            mSpanCount--;

            sendSpanRemoved(what, ostart, oend);
            return;
        }
    }
}

SHOUXIANDIAOYONGLEcheckRange,PANDUANLEWEIZHIDEHEFAXING,RUGUOstartXIAOYUend,HUOZHEWEIZHIXIABIAOYUEJIEDOUHUIPAOCHUIndexOutOfBoundsExceptionYICHANG。

ZHIHOUPANDUANLE(flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPHSHIFOUXIANGDENG,ZHEILIRUGUOSHEZHIDESHISHANGSHUSIGEZHI,ZHEILISHIBUDENGDE,SUOYIBUHUIJINRUGAIPANDUAN。

SHEZHILEcount,DIYICIcountWEI0,SHEZHILEspansSHUZUYUdata,DIYICISHEZHIDEZHISHIZAIGOUZAOHANSHUZHONGCHUSHIHUADEZHI。

YINWEIcountWEI0,YINCIforXUNHUANYEBUHUIJINRU

ZHIHOUPANDUANLEmSpanCount + 1 >= mSpans.length,ZHEILIQIANMIANWEI1,HOUMIANWEI0,YINCIHUIJINRUifPANDUAN,SHOUXIANSHENQINGLEYIGE3GEZHANGDUDEnewtagsSHUZU,YIGE9GEZHANGDUDEintSHUZU, ZHIHOUJINXINGLELIANGCISHUJUKAOBEI,JIANGYIYOUDEspanKAOBEIDAOXINSHENQINGDESHUZUZHONG,JIANGQITACANSHUKAOBEIDAOXINDEintSHUZUZHONG。

ZHIHOUJIANGGAICHENGSHEZHIDEspanSHEZHIDAOmSpansSHUZUZHONG,JIANGQITADECANSHUSHEZHIDAOmSpanData,SANGECANSHUSHILIANXUSHEZHIDE。

ZUIHOUDIAOYONGLEsendSpanAdded,DAIMARUXIA:

private void sendSpanAdded(Object what, int start, int end) {
    SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
    int n = recip.length;

    for (int i = 0; i < n; i++) {
        recip[i].onSpanAdded((Spannable) this, what, start, end);
    }
}

ZHEIGEDIAOYONGLEgetSpans,FANHUILEYIGESpanWatcherSHUZU,SpanWatcherSHIYIGEJIEKOU,MultiTapKeyListener, TextKeyListenerSHIXIANLEGAILEI,YINCIDANGDIAOYONGLETextKeyListenerHUOZHEMultiTapKeyListenerHUIDUIXIANGYINGDEspanJINXINGCHULI。

总结

ZHEILIZHISHIDAZHIDEJIEXILESpannableString,TAHAIXUYAOJIEHETextViewJINXINGFENXI,KANKANZAIJIEMIANHUIZHIDESHIHOUSHIZENYANGJIEXIXIANSHIDE。HOUXUYOUSHIJIANHUILUXUJINXINGJIEXIDE。

荣耀彩票代理ZUIHOUFUYIGELIANJIE,ZAIWOJIEXIspanDESHIHOU,JIEXILEJIGEGANJUETAIDUO,JIUSOUSUOYIXIASHIFOUYIJINGYOURENJIEXIGUO,YINCIZHEIGEZHEILIJIASHANGTIAOZHUANLIANJIE,RUGUOYOUBANQUANHUOZHEBURANGDAOHANG,QINGGAOZHI,WOHAOSHANCHU。CHUANSONGMEN

延伸阅读:

Tag标签:   
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规