IT技術互動交流平台

AndroidSpannableString淺析

來源|--酷派w706软件下载:IT165收集  發布日期|118彩票怎么安装:2016-05-16 20:47:49

引言

在應用程序開發過程經常需要對文本進行處理-降价函,比如說對一段描述文字的其中一段加入點擊事件||小史可,或者對其設置不一樣的前景色|__仲博最新版下载,有什麼方法可以實現要求的功能呐|-黑帮ceo的筹码情人?

需求樣例

比如我們需要實現如下圖所示的功能||_云顶娱乐斗地主v180,將文本__01彩票是不是正规的:#重磅消息#近日穀歌放出Android N的第二個開發者預覽版(Developer Preview) 處理成第二種或者第三種的形式|-|苏州吸脂。

這裏寫圖片描述

實現方案

根據上圖__|上海哪有蹦极的地方,我們可以采用如下的方法來實現上訴要求的效果__尼采s3。

方案1

比如顯示效果二你可以能會說_-|言峰绮礼怎么死的,我們可以采用三個TextView來實現|__就医160网上预约,第一個TextView設置不一樣的顏色||-帅同文学转载,第二個正常顯示內容||-小米1s锤子rom,第三個處理點擊事件-_-银河海润。該方式對圖二可能是能夠實現的_|金庸群侠传2加强版攻略,但是如果第二行裏麵就有部分內容需要進行點擊處理_|宅男躲艳记txt下载,就比較難以實現了-_|御龙在天野蘑菇在哪。

對於圖三的效果上述的方式就很難實現了_-_365彩票有人中多少钱。必須要對TextView的內容進行處理了_|骂小佛!_|-苏州地税局网站!

方案2

如果文案的處理隻是簡單的對齊--2M全年免费资料,顏色--苏州园区博客门,大小的變換-|才子打电话骂小花,我們還可以采用自定義view來實現|-心德维拉,在前麵的文章中我們就采用了自定義view來顯示了一個文字的排版效果-|众乐彩票提现,具體實現可以查看Android文本排版實現;

方案3

除了上麵的方案--锅盔牙子,我們還可以采用另外一個種方式來實現_陈浥萍,采用html來顯示||赢咖娱乐稳定吗,可以將要顯示的內容轉換成html的格式-|诺基亚e900,用TextView來進行加載|_花为谁开。說了這麼多-|106平台彩票二维码,我們來看看代碼吧--成都男子街头杀妻!

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());
}

寫到這_-亿彩彩票规律,突然發現要跑題-_-东莞桑拿一条龙服务,僅僅是Html的實現就可以分析出很多的知識點_|铁将军防盗器接线图,不過這裏還是先契合主題__-捷安特770,先這裏挖一個坑_||雄县地图,後續對html進行分析|--白色松木家具,查看鏈接-|易彩堂能提现吗,現在還未實現

方案4

終於回到我們的主題了|-家禾康甩脂机有用吗,這裏我們采用SpannableString來實現上述的效果-阿克苏诺贝尔待遇。代碼如下--e90飞机:

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);
}

上述代碼采用了硬編碼方式實現---2628彩票账号注册,正常實現|--西单商场打折,需要根據需求進行設置|_-斗战神宠物本源技怎么升级。記得要添加textView.setMovementMethod(LinkMovementMethod.getInstance());來接受點擊事件|斯雅娇。

SpnnableString詳解

SpannableString繼承了SpannableStringInternal__青岛往事下载,同時實現了CharSequence, GetChars, Spannable三個接口|_|众盈彩票能赚钱吗,正常處理文本的函數為setSpan函數|-具人同行家具网购:

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

該函數有四個參數_-众购彩票网,第一個為一個span類型|__nba2k online外挂,第二個參數為開始位置-||优信彩票APP,第三個位置為span的結束位置|_珍爱十字绣花开富贵,最後一個為flag參數_-不思议游戏国语版。
what可以設置如下類型|_菊丸英二bg:

1, AbsoluteSizeSpan 設置文字字體的絕對大小, 有兩個參數-_-三星w2013水货,第一個是字體大小-|-陈奎元简历,第二個是單位是否是dip

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

2,AlignmentSpan 主要設置文本的對齊方式-_-云天国际,有三種方式正常_花语梦,居中--_小型飞机发动机,相反的方式對齊-__财经郎眼 余额宝,默認實現為Standard

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

3,BackgroundColorSpan 設置文字的背景色

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 給文本的開始處加上項目符號|||火焰之纹章圣魔之光石金手指。比如前麵加一個 .

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 設置文本的點擊事件__|索尼爱立信x8刷机,要實現onClick函數_|亿彩彩票,可以複寫updateDrawState-|-悦花越有刘玉龙坐牢,設置下劃線|-中央电视1台,或者取消下劃線_--antonia 霍启仁,還可以設置下劃線顏色

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 可以設置一個圖標_--lol定级赛规则,並且可以設置與文字的寬度

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 設置某段文字被圖標替換-约彩彩票软件正规吗?,需要返回一個drawable

8,EasyEditSpan 當文本改變或者刪除時調用, 例如入下長按可以很容易刪除一行

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 設置文字前景色

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);
}

寫到這裏我停下來了_甲申日。天啦嚕-_红警全能王v1 03,30多個span-|11选5南京华彩,可以去係統代碼package android.text.style包下查看-_锦江区公众信息网,這麼多_-_155是移动的吗,整個人都不好了_|moko路遥。

這裏寫圖片描述
因此先就針對上麵的做了部分樣例|__固话资费,之後會專門實現一下每個span的效果--106时时彩手机版。仔細理解一個就行__-卡门 德洛雷菲切,其他的都是類似的_网曝 查开房 网址,我們繼續看看後麵的參數__什么电影最好看。

第二參數start和第三個參數end||花城广场停车,表示當時設置的span作用效果的範圍-_-咬人猫黑历史,start表示開始位置_|何小萌萌萌新浪微博,end表示結束位置|-600741,第四個參數是一個flag標簽_|苏州哪里有洗头房。這裏主要設置以下的值|-抱抱装:

/**
 * 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表示左右都是閉區間 ‘( ]’

我們繼續來看代碼-|雷立,SpannableString的setSpan又繼續調用了SpannableStringInternal的setSpan函數_|_天然故事。

/* 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;
        }
    }
}

首先調用了checkRange|__陈俊任,判斷了位置的合法性|-|花萝卜网,如果start小於end-__永州八记的作者,或者位置下標越界都會拋出IndexOutOfBoundsException異常_|周永慷。

之後判斷了(flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPH是否相等|-脊柱宝,這裏如果設置的是上述四個值--盈众彩票注册,這裏是不等的-|-花都区教育网,所以不會進入該判斷_-|美丽霸道的授课老师。

設置了count_-_蛮荒之友成就,第一次count為0_-中国82烈士血战叙利亚,設置了spans數組與data--|重庆伟岸,第一次設置的值是在構造函數中初始化的值--|说说歌词。

因為count為0-|_袁成杰包子铺,因此for循環也不會進入

之後判斷了mSpanCount + 1 >= mSpans.length|_中国军衔胸章,這裏前麵為1|-项目投资计划书范文,後麵為0|||西瓜晶,因此會進入if判斷-|-11选5彩票人工计划软件,首先申請了一個3個長度的newtags數組|采婷,一個9個長度的int數組--优彩网官网登录密码, 之後進行了兩次數據拷貝||钱塘老娘舅2013直播,將已有的span拷貝到新申請的數組中_-掌上彩票Pro官网登录,將其他參數拷貝到新的int數組中--小爸爸拍摄地点。

之後將改成設置的span設置到mSpans數組中|公务员阳光工资标准,將其他的參數設置到mSpanData---德州双元驾校,三個參數是連續設置的_|锥子脸蒂娜。

最後調用了sendSpanAdded|__柯露玛,代碼如下|_白酒包装图片:

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);
    }
}

這個調用了getSpans||11086移动彩票下载,返回了一個SpanWatcher數組|-闪光夫妇下车,SpanWatcher是一個接口||众盈彩票有人主动带你赢钱正常吗?,MultiTapKeyListener, TextKeyListener實現了該類|我是歌手12期完整版,因此當調用了TextKeyListener或者MultiTapKeyListener會對相應的span進行處理|999桑拿会所。

總結

這裏隻是大致的解析了SpannableString|-13彩怎么玩不亏,他還需要結合TextView進行分析_塔罗牌大师tlp6868668,看看在界麵繪製的時候是怎樣解析顯示的-_wow瑟银矿。後續有時間會陸續進行解析的-长笛手。

最後附一個鏈接|_|长江电力电子商务,在我解析span的時候|_众盈彩票合法正规吗,解析了幾個感覺太多___2012年职称英语考试成绩查询,就搜索一下是否已經有人解析過|_-14胜负彩奖金,因此這個這裏加上跳轉鏈接_||养热带鱼赚钱,如果有版權或者不讓導航_|亿彩彩票钱能提现吗,請告知-||深圳电视台第一现场,我好刪除|_-众发彩票官网app下载。傳送門

延伸閱讀_|闫文杰:

Tag標簽-|-震荡波补丁: AndroidSpannableString淺析  
  • 專題推薦

  • Windows7係統入門 優化 技巧技術專題
  • Windows7係統專題 無論是升級操作係統-_爱肺金雪茄、資料備份-||索爱u5i刷机、加強資料的安全及管...... 詳細
About IT165 - 廣告服務 - 隱私聲明 - 版權申明 - 免責條款 - 網站地圖 - 網友投稿 - 聯係方式
本站內容來自於互聯網,僅供用於網絡技術學習,學習中請遵循相關法律法規
88彩票捷豹彩票9号彩票分分彩快乐时时彩聚鑫彩票

免责声明: 本站资料及图片来源互联网文章,本网不承担任何由内容信息所引起的争议和法律责任。所有作品版权归原创作者所有,与本站立场无关,如用户分享不慎侵犯了您的权益,请联系我们告知,我们将做删除处理!