字符級(jí)Span解析

1 簡(jiǎn)介

之前已經(jīng)講過(guò)TextView的基礎(chǔ)知識(shí),和段落級(jí)別的Span割捅,現(xiàn)在在這進(jìn)一步進(jìn)行講解,這篇文字主要講解如何給TextView設(shè)置字符級(jí)別的Span。如果一個(gè)Span想要影響段落層次的文本格式咖楣,則需要繼承CharacterStyle。


2 CharacterStyle

CharacterStyle是個(gè)抽象類芦昔,字符級(jí)別的Span都需要繼承這個(gè)類诱贿,這個(gè)類里面有一個(gè)抽象方法:

public abstract void updateDrawState(TextPaint tp)

通過(guò)改變TextPaint的屬性就可以得到不同的展現(xiàn)形式。在這個(gè)抽象類里面還有一個(gè)靜態(tài)方法:

public static CharacterStyle wrap(CharacterStyle cs)

一個(gè)CharacterStyle類型的Span只能給一個(gè)Spaned片段使用,如果想這個(gè)Span給多個(gè)片段使用可以使用wrap方法珠十。wrap方法的具體代碼如下:

public static CharacterStyle wrap(CharacterStyle cs) {
    if (cs instanceof MetricAffectingSpan) {
        return new MetricAffectingSpan.Passthrough((MetricAffectingSpan) cs);
    } else {
        return new Passthrough(cs);
    }
}

再看Passthrough的代碼

private static class Passthrough extends CharacterStyle {
    private CharacterStyle mStyle;

    /**
     * Creates a new Passthrough of the specfied CharacterStyle.
     */
    public Passthrough(CharacterStyle cs) {
        mStyle = cs;
    }

    /**
     * Passes updateDrawState through to the underlying CharacterStyle.
     */
    @Override
    public void updateDrawState(TextPaint tp) {
        mStyle.updateDrawState(tp);
    }

    /**
     * Returns the CharacterStyle underlying this one, or the one
     * underlying it if it too is a Passthrough.
     */
    @Override
    public CharacterStyle getUnderlying() {
        return mStyle.getUnderlying();
    }
}

不難發(fā)現(xiàn)其實(shí)就是復(fù)制了一個(gè)CharacterStyle料扰。


3 UpdateAppearance

如果一個(gè)Span修改字符級(jí)別的文本外觀,則實(shí)現(xiàn)UpdateAppearance焙蹭。


UpdateAppearance

上面的Span都實(shí)現(xiàn)了UpdateAppearance接口晒杈,上面的諸多Span都是通過(guò)updateDrawState(TextPaint ds)方法來(lái)實(shí)現(xiàn)相應(yīng)的效果。

  1. BackgroundColorSpan:ds.bgColor = mColor孔厉;
  2. ForegroundColorSpan:ds.setColor(mColor)拯钻;
  3. StrikethroughSpan:ds.setStrikeThruText(true);
  4. UnderlineSpan:ds.setUnderlineText(true)撰豺;
  5. MaskFilterSpan:ds.setMaskFilter(mFilter)粪般;

BackgroundColorSpan和ForegroundColorSpan


BackAndFront

UnderlineSpan和StrikethroughSpan:


UnderAndStrike

MaskFilterSpan:
Mask

可以看一下ClickableSpan的源代碼

public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {

    /**
     * Performs the click action associated with this span.
     */
    public abstract void onClick(View widget);
   
    /**
     * Makes the text underlined and in the link color.
     */
    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setColor(ds.linkColor);
        ds.setUnderlineText(true);
    }
}

點(diǎn)擊后通過(guò)updateDrawState(TextPaint ds)方法改變字體外觀,onClick(View widget)則交給子類實(shí)現(xiàn)相應(yīng)的邏輯污桦。
MaskFilterSpan中ds.setMaskFilter(mFilter)可以給字體設(shè)置模糊和浮雕效果亩歹。

span = new MaskFilterSpan(new BlurMaskFilter(density*2, BlurMaskFilter.Blur.NORMAL));
span = new MaskFilterSpan(new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f));

4 UpdateLayout

如果一個(gè)Span修改字符級(jí)文本度量|大小,則實(shí)現(xiàn)UpdateLayout凡橱。在Android源碼中捆憎,只有MetricAffectingSpan實(shí)現(xiàn)了UpdateLayout接口。


UpdateLayout

UpdateLayout

接下來(lái)看一下MetricAffectingSpan的源碼梭纹。

public abstract class MetricAffectingSpan
extends CharacterStyle
implements UpdateLayout {

    public abstract void updateMeasureState(TextPaint p);

    /**
     * Returns "this" for most MetricAffectingSpans, but for 
     * MetricAffectingSpans that were generated by {@link #wrap},
     * returns the underlying MetricAffectingSpan.
     */
    @Override
    public MetricAffectingSpan getUnderlying() {
        return this;
    }

    /**
     * A Passthrough MetricAffectingSpan is one that
     * passes {@link #updateDrawState} and {@link #updateMeasureState}
     * calls through to the specified MetricAffectingSpan 
     * while still being a distinct object,
     * and is therefore able to be attached to the same Spannable
     * to which the specified MetricAffectingSpan is already attached.
     */
    /* package */ static class Passthrough extends MetricAffectingSpan {
        private MetricAffectingSpan mStyle;
        
        /**
         * Creates a new Passthrough of the specfied MetricAffectingSpan.
         */
        public Passthrough(MetricAffectingSpan cs) {
            mStyle = cs;
        }

        /**
         * Passes updateDrawState through to the underlying MetricAffectingSpan.
         */
        @Override
        public void updateDrawState(TextPaint tp) {
            mStyle.updateDrawState(tp);
        }

        /**
         * Passes updateMeasureState through to the underlying MetricAffectingSpan.
         */
        @Override
        public void updateMeasureState(TextPaint tp) {
            mStyle.updateMeasureState(tp);
        }
    
        /**
         * Returns the MetricAffectingSpan underlying this one, or the one
         * underlying it if it too is a Passthrough.
         */
        @Override
        public MetricAffectingSpan getUnderlying() {
            return mStyle.getUnderlying();
        }
    }
}

可以看見(jiàn)MetricAffectingSpan同樣繼承了CharacterStyle躲惰,因此同樣繼承了抽象方法updateDrawState(TextPaint tp),這個(gè)方法可以交給子類實(shí)現(xiàn)变抽,從而實(shí)現(xiàn)字體外觀的改變础拨。在MetricAffectingSpan類中定義了一個(gè)抽象方法updateMeasureState(TextPaint p),繼承MetricAffectingSpan類的子類可以實(shí)現(xiàn)這個(gè)抽象方法绍载,從而實(shí)現(xiàn)對(duì)字體大小的改變诡宗。在MetricAffectingSpan中同樣也提供了一個(gè)Passthrough的類,從而完成CharacterStyle中定義的wrap方法击儡。
接下來(lái)分別對(duì)MetricAffectingSpan的實(shí)現(xiàn)類進(jìn)行講述塔沃。


4.1 SubscriptSpan和SuperscriptSpan

SubscriptSpan和SuperscriptSpan實(shí)現(xiàn)字體的上下標(biāo)展示,效果如下面的圖片所示:


SubscriptSpan

SuperscriptSpan

其實(shí)這兩個(gè)Span的實(shí)現(xiàn)特別簡(jiǎn)單阳谍,通過(guò)查看這兩個(gè)類的實(shí)現(xiàn)蛀柴,能夠幫助我們對(duì)Android的字體有著更深入的理解。
SuperscriptSpan:

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.baselineShift += (int) (tp.ascent() / 2);
    }

    @Override
    public void updateMeasureState(TextPaint tp) {
        tp.baselineShift += (int) (tp.ascent() / 2);
    }

SubscriptSpan:

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.baselineShift -= (int) (tp.ascent() / 2);
    }

    @Override
    public void updateMeasureState(TextPaint tp) {
        tp.baselineShift -= (int) (tp.ascent() / 2);
    }

4.2 AbsoluteSizeSpan和RelativeSizeSpan

AbsoluteSizeSpan和RelativeSizeSpan用來(lái)改變相應(yīng)字符的字體大小矫夯。

/**
* size: 大小
* dip: false鸽疾,size單位為px,true训貌,size單位為dip(默認(rèn)為false)制肮。
*/
//設(shè)置文字大小為24dp
span = new AbsoluteSizeSpan(24, true);
AbsoluteSizeSpan
//設(shè)置文字大小為大2倍
span = new RelativeSizeSpan(2.0f);
RelativeSizeSpan

AbsoluteSizeSpan:

    @Override
    public void updateDrawState(TextPaint ds) {
        if (mDip) {
            ds.setTextSize(mSize * ds.density);
        } else {
            ds.setTextSize(mSize);
        }
    }

    @Override
    public void updateMeasureState(TextPaint ds) {
        if (mDip) {
            ds.setTextSize(mSize * ds.density);
        } else {
            ds.setTextSize(mSize);
        }
    }

RelativeSizeSpan:

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setTextSize(ds.getTextSize() * mProportion);
    }

    @Override
    public void updateMeasureState(TextPaint ds) {
        ds.setTextSize(ds.getTextSize() * mProportion);
    }

4.3 ScaleXSpan

ScaleXSpan影響字符集的文本格式冒窍。它可以在x軸方向上縮放字符集。

//設(shè)置水平方向上放大3倍
span = new ScaleXSpan(3.0f);
ScaleXSpan

源碼:

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setTextScaleX(ds.getTextScaleX() * mProportion);
    }

    @Override
    public void updateMeasureState(TextPaint ds) {
        ds.setTextScaleX(ds.getTextScaleX() * mProportion);
    }

4.4 StyleSpan豺鼻、TypefaceSpan和TextAppearanceSpan

StyleSpan综液、TypefaceSpan和TextAppearanceSpan都可以字體的樣式進(jìn)行改變,StyleSpan可以對(duì)字體設(shè)置bold或者italic的字符樣式儒飒,TypefaceSpan可以對(duì)字體設(shè)置其他的樣式意乓,TextAppearanceSpan通過(guò)xml文件從而對(duì)字體進(jìn)行設(shè)置。

//設(shè)置bold+italic的字符樣式
span = new StyleSpan(Typeface.BOLD | Typeface.ITALIC);
StyleSpan
//設(shè)置serif family
span = new TypefaceSpan("serif");
TypefaceSpan
span = new TextAppearanceSpan(this, R.style.SpecialTextAppearance);
<-- style.xml -->
<style name="SpecialTextAppearance" parent="@android:style/TextAppearance">
<item name="android:textColor">@color/color1</item>
<item name="android:textColorHighlight">@color/color2</item>
<item name="android:textColorHint">@color/color3</item>
<item name="android:textColorLink">@color/color4</item>
<item name="android:textSize">28sp</item>
<item name="android:textStyle">italic</item>
</style>
TextAppearanceSpan

StyleSpan:

    @Override
    public void updateDrawState(TextPaint ds) {
        apply(ds, mStyle);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        apply(paint, mStyle);
    }

    private static void apply(Paint paint, int style) {
        int oldStyle;

        Typeface old = paint.getTypeface();
        if (old == null) {
            oldStyle = 0;
        } else {
            oldStyle = old.getStyle();
        }

        int want = oldStyle | style;

        Typeface tf;
        if (old == null) {
            tf = Typeface.defaultFromStyle(want);
        } else {
            tf = Typeface.create(old, want);
        }

        int fake = want & ~tf.getStyle();

        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

        if ((fake & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(tf);
    }

TypefaceSpan:

@Override
    public void updateDrawState(TextPaint ds) {
        apply(ds, mFamily);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        apply(paint, mFamily);
    }

    private static void apply(Paint paint, String family) {
        int oldStyle;

        Typeface old = paint.getTypeface();
        if (old == null) {
            oldStyle = 0;
        } else {
            oldStyle = old.getStyle();
        }

        Typeface tf = Typeface.create(family, oldStyle);
        int fake = oldStyle & ~tf.getStyle();

        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

        if ((fake & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(tf);
    }

TextAppearanceSpan:

    @Override
    public void updateDrawState(TextPaint ds) {
        updateMeasureState(ds);

        if (mTextColor != null) {
            ds.setColor(mTextColor.getColorForState(ds.drawableState, 0));
        }

        if (mTextColorLink != null) {
            ds.linkColor = mTextColorLink.getColorForState(ds.drawableState, 0);
        }
    }

    @Override
    public void updateMeasureState(TextPaint ds) {
        if (mTypeface != null || mStyle != 0) {
            Typeface tf = ds.getTypeface();
            int style = 0;

            if (tf != null) {
                style = tf.getStyle();
            }

            style |= mStyle;

            if (mTypeface != null) {
                tf = Typeface.create(mTypeface, style);
            } else if (tf == null) {
                tf = Typeface.defaultFromStyle(style);
            } else {
                tf = Typeface.create(tf, style);
            }

            int fake = style & ~tf.getStyle();

            if ((fake & Typeface.BOLD) != 0) {
                ds.setFakeBoldText(true);
            }

            if ((fake & Typeface.ITALIC) != 0) {
                ds.setTextSkewX(-0.25f);
            }

            ds.setTypeface(tf);
        }

        if (mTextSize > 0) {
            ds.setTextSize(mTextSize);
        }
    }

4.5 LocaleSpan

LocaleSpan用來(lái)對(duì)字體設(shè)置不同的地區(qū)约素,由于不同地區(qū)的字體會(huì)導(dǎo)致字體大小的變化届良,因此LocaleSpan也需要繼承MetricAffectingSpan。


LineHeightDemo

源碼:

    @Override
    public void updateDrawState(TextPaint ds) {
        apply(ds, mLocale);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        apply(paint, mLocale);
    }

    private static void apply(Paint paint, Locale locale) {
        paint.setTextLocale(locale);
    }

5 ReplacementSpan

ReplacementSpan繼承了MetricAffectingSpan圣猎,但是ReplacementSpan比較復(fù)雜因此在這單獨(dú)講解士葫。在ReplacementSpan里新增加了兩個(gè)抽象方法,ReplacementSpan源碼如下:

public abstract class ReplacementSpan extends MetricAffectingSpan {

    public abstract int getSize(Paint paint, CharSequence text,
                         int start, int end,
                         Paint.FontMetricsInt fm);
    public abstract void draw(Canvas canvas, CharSequence text,
                     int start, int end, float x,
                     int top, int y, int bottom, Paint paint);

    /**
     * This method does nothing, since ReplacementSpans are measured
     * explicitly instead of affecting Paint properties.
     */
    public void updateMeasureState(TextPaint p) { }

    /**
     * This method does nothing, since ReplacementSpans are drawn
     * explicitly instead of affecting Paint properties.
     */
    public void updateDrawState(TextPaint ds) { }
}

抽象方法getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm)返回所占的寬度送悔。其實(shí)根據(jù)getSize方法的參數(shù)我們能夠計(jì)算原本那些字符所占用的寬度慢显,計(jì)算方法如下:

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
        //return text with relative to the Paint
        mWidth = (int) paint.measureText(text, start, end);
        return mWidth;
    }

通過(guò)這個(gè)寬度我們可以給文字制作相應(yīng)的效果。
抽象方法draw欠啤,可以讓我們?cè)诤线m的區(qū)域繪制相應(yīng)的圖形荚藻,start和end分別為span作用的起始和結(jié)束字符的index,x為起始橫坐標(biāo)洁段,y為baseline對(duì)應(yīng)的坐標(biāo)应狱,top為起始高度,bottom為結(jié)束高度祠丝。
在Android提供的源碼里面提供了一個(gè)抽象類DynamicDrawableSpan來(lái)繼承ReplacementSpan疾呻,而DynamicDrawableSpan又有一個(gè)子類ImageSpan。


5.1 DynamicDrawableSpan

DynamicDrawableSpan是一個(gè)抽象類写半,DynamicDrawableSpan可以做到使用Drawable替代相對(duì)應(yīng)的字符序列岸蜗,展現(xiàn)效果如下所示:


ImageSpan

下面我們來(lái)分析一下DynamicDrawableSpan的源碼。

public abstract class DynamicDrawableSpan extends ReplacementSpan {
    private static final String TAG = "DynamicDrawableSpan";
    
    /**
     * A constant indicating that the bottom of this span should be aligned
     * with the bottom of the surrounding text, i.e., at the same level as the
     * lowest descender in the text.
     */
    public static final int ALIGN_BOTTOM = 0;
    
    /**
     * A constant indicating that the bottom of this span should be aligned
     * with the baseline of the surrounding text.
     */
    public static final int ALIGN_BASELINE = 1;
    
    protected final int mVerticalAlignment;
    
    public DynamicDrawableSpan() {
        mVerticalAlignment = ALIGN_BOTTOM;
    }

    /**
     * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}.
     */
    protected DynamicDrawableSpan(int verticalAlignment) {
        mVerticalAlignment = verticalAlignment;
    }

    /**
     * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM} or
     * {@link #ALIGN_BASELINE}.
     */
    public int getVerticalAlignment() {
        return mVerticalAlignment;
    }

    /**
     * Your subclass must implement this method to provide the bitmap   
     * to be drawn.  The dimensions of the bitmap must be the same
     * from each call to the next.
     */
    public abstract Drawable getDrawable();

    @Override
    public int getSize(Paint paint, CharSequence text,
                         int start, int end,
                         Paint.FontMetricsInt fm) {
        Drawable d = getCachedDrawable();
        Rect rect = d.getBounds();
        if (fm != null) {
            fm.ascent = -rect.bottom; 
            fm.descent = 0; 

            fm.top = fm.ascent;
            fm.bottom = 0;
        }
        return rect.right;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text,
                     int start, int end, float x, 
                     int top, int y, int bottom, Paint paint) {
        Drawable b = getCachedDrawable();
        canvas.save();
        int transY = bottom - b.getBounds().bottom;
        if (mVerticalAlignment == ALIGN_BASELINE) {
            transY -= paint.getFontMetricsInt().descent;
        }
        canvas.translate(x, transY);
        b.draw(canvas);
        canvas.restore();
    }

    private Drawable getCachedDrawable() {
        WeakReference<Drawable> wr = mDrawableRef;
        Drawable d = null;
        if (wr != null)
            d = wr.get();
        if (d == null) {
            d = getDrawable();
            mDrawableRef = new WeakReference<Drawable>(d);
        }
        return d;
    }

    private WeakReference<Drawable> mDrawableRef;
}
  1. 抽象方法getDrawable()告訴子類需要提供一個(gè)Drawable用來(lái)繪制叠蝇;
  2. getSize方法中璃岳,通過(guò)設(shè)置FontMetricsInt,從而使得替代字符序列的baseline和圖片的尾部對(duì)齊悔捶,而替代字符序列的垂直高度就為圖片的高度铃慷;
  3. draw方法中,需要繪制圖片的其實(shí)x坐標(biāo)很明確就是x炎功,y坐標(biāo)可以通過(guò)多種方式獲取枚冗,在baseline對(duì)齊的情況下可以等于top缓溅,也可以等于y-b.getBounds().bottom蛇损,還可以等于bottom-b.getBounds().bottom-descent,各種方法都可以。

在Android系統(tǒng)中淤齐,提供了一個(gè)ImageSpan繼承了DynamicDrawableSpan股囊,實(shí)現(xiàn)了通過(guò)多種方式生成Drawable。

6 相關(guān)鏈接

Textview圖文基礎(chǔ)
段落級(jí)span
字符級(jí)span
自定義span

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末更啄,一起剝皮案震驚了整個(gè)濱河市稚疹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌祭务,老刑警劉巖内狗,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異义锥,居然都是意外死亡柳沙,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門拌倍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)赂鲤,“玉大人,你說(shuō)我怎么就攤上這事柱恤∈酰” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵梗顺,是天一觀的道長(zhǎng)泡孩。 經(jīng)常有香客問(wèn)我,道長(zhǎng)寺谤,這世上最難降的妖魔是什么珍德? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮矗漾,結(jié)果婚禮上锈候,老公的妹妹穿的比我還像新娘。我一直安慰自己敞贡,他們只是感情好泵琳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著誊役,像睡著了一般获列。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛔垢,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天击孩,我揣著相機(jī)與錄音,去河邊找鬼鹏漆。 笑死巩梢,一個(gè)胖子當(dāng)著我的面吹牛创泄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播括蝠,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼鞠抑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了忌警?” 一聲冷哼從身側(cè)響起搁拙,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎法绵,沒(méi)想到半個(gè)月后箕速,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朋譬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年弧满,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片此熬。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庭呜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出犀忱,到底是詐尸還是另有隱情募谎,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布阴汇,位于F島的核電站数冬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏搀庶。R本人自食惡果不足惜拐纱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哥倔。 院中可真熱鬧秸架,春花似錦、人聲如沸咆蒿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)沃测。三九已至缭黔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒂破,已是汗流浹背馏谨。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留附迷,地道東北人惧互。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓哎媚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親壹哺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抄伍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,189評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理艘刚,服務(wù)發(fā)現(xiàn)管宵,斷路器,智...
    卡卡羅2017閱讀 134,672評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法攀甚,類相關(guān)的語(yǔ)法箩朴,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法秋度,異常的語(yǔ)法炸庞,線程的語(yǔ)...
    子非魚_t_閱讀 31,644評(píng)論 18 399
  • 東風(fēng)睡獅渾然醒, 一聲低吼世界驚荚斯。 主導(dǎo)全球新秩序埠居, 扼制霸權(quán)斬幽靈。 中華巨輪已揚(yáng)帆事期, 乘風(fēng)破浪萬(wàn)里行滥壕。 十三億...
    5988閱讀 2,328評(píng)論 0 0
  • 今天已經(jīng)是第三周的第一天,在經(jīng)歷了十幾天的一個(gè)跟進(jìn)后兽泣,基本上慢慢有了一些進(jìn)展绎橘。 今天又講到了所有關(guān)于成交的所有邏輯...
    馬春穎閱讀 254評(píng)論 0 0