ExpandableTextView的源碼解讀

這個(gè)自定義TextView可以實(shí)現(xiàn)內(nèi)部文字的折疊和擴(kuò)展顯示,效果如下:


有興趣的同學(xué)可以自行點(diǎn)擊下載源碼浦夷,里面的注釋已經(jīng)寫(xiě)的很完善了益涧。這里我將我的代碼整理分享出來(lái):
首先需要定義ExpandableTextView的屬性資源文件attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TextViewExpandable">
        <attr name="tvea_expandLines" format="integer"/>
        <attr name="tvea_shrinkBitmap" format="reference" />
        <attr name="tvea_expandBitmap" format="reference" />
        <attr name="tvea_textStateColor" format="color" />
        <attr name="tvea_textContentColor" format="color" />
        <attr name="tvea_textContentSize" format="dimension" />
        <attr name="tvea_textShrink" format="string" />
        <attr name="tvea_textExpand" format="string" />
    </declare-styleable>
</resources>

各屬性的意義通過(guò)名稱大家應(yīng)該也都能理解出來(lái)软瞎,論學(xué)好英語(yǔ)的重要性啊......扯遠(yuǎn)了闯割,接下來(lái)需要給ExpandableTextView指定布局文件layout_textview_expand_animation.xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ll_text_expand_animation_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_expand_text_view_animation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/color_gray_light_content_text"
        android:textSize="@dimen/sp_txt_size_content"
        tools:text="@string/tips" />

    <RelativeLayout
        android:id="@+id/rl_expand_text_view_animation_toggle_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone">

        <ImageView
            android:id="@+id/iv_expand_text_view_animation_toggle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            />

        <TextView
            android:id="@+id/tv_expand_text_view_animation_hint"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@+id/iv_expand_text_view_animation_toggle"
            android:textColor="@color/colorPrimary"
            android:textSize="@dimen/sp_txt_size_content"
            tools:text="全部" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0.1dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:layout_toLeftOf="@id/tv_expand_text_view_animation_hint"
            android:background="@color/color_divider_line_gray" />
    </RelativeLayout>
</LinearLayout>

好接下來(lái)就是我們的主題了,ExpandableTextView類的代碼編寫(xiě)了省店。代碼如下嚣崭,我已經(jīng)將需要注釋的地方都進(jìn)行了注釋。

public class TextViewExpandable extends LinearLayout implements View.OnClickListener{
    /**
     * TextView
     */
    private TextView textView;

    /**
     * 收起/全部TextView
     * <br>shrink/expand TextView
     */
    private TextView tvState;

    /**
     * 點(diǎn)擊進(jìn)行折疊/展開(kāi)的圖片
     * <br>shrink/expand icon
     */
    private ImageView ivExpandOrShrink;

    /**
     * 底部是否折疊/收起的父類布局
     * <br>shrink/expand layout parent
     */
    private RelativeLayout rlToggleLayout;

    /**
     * 提示折疊的圖片資源
     * <br>shrink drawable
     */
    private Drawable drawableShrink;
    /**
     * 提示顯示全部的圖片資源
     * <br>expand drawable
     */
    private Drawable drawableExpand;

    /**
     * 全部/收起文本的字體顏色
     * <br>color of shrink/expand text
     */
    private int textViewStateColor;
    /**
     * 展開(kāi)提示文本
     * <br>expand text
     */
    private String textExpand;
    /**
     * 收縮提示文本
     * <br>shrink text
     */
    private String textShrink;

    /**
     * 是否折疊顯示的標(biāo)示
     * <br>flag of shrink/expand
     */
    private boolean isShrink = false;

    /**
     * 是否需要折疊的標(biāo)示
     * <br>flag of expand needed
     */
    private boolean isExpandNeeded = false;

    /**
     * 是否初始化TextView
     * <br>flag of TextView Initialization
     */
    private boolean isInitTextView = true;

    /**
     * 折疊顯示的行數(shù)
     * <br>number of lines to expand
     */
    private int expandLines;

    /**
     * 文本的行數(shù)
     * <br>Original number of lines
     */
    private int textLines;

    /**
     * 顯示的文本
     * <br>content text
     */
    private CharSequence textContent;

    /**
     * 顯示的文本顏色
     * <br>content color
     */
    private int textContentColor;

    /**
     * 顯示的文本字體大小
     * <br>content text size
     */
    private float textContentSize;

    /**
     * 動(dòng)畫(huà)線程
     * <br>thread
     */
    private Thread thread;

    /**
     * 動(dòng)畫(huà)過(guò)度間隔
     * <br>animation interval
     */
    private int sleepTime = 22;

    /**
     * handler信號(hào)
     * <br>handler signal
     */
    private final int WHAT = 2;
    /**
     * 動(dòng)畫(huà)結(jié)束信號(hào)
     * <br>animation end signal of handler
     */
    private final int WHAT_ANIMATION_END = 3;

    /**
     * 動(dòng)畫(huà)結(jié)束懦傍,只是改變圖標(biāo)雹舀,并不隱藏
     * <br>animation end and expand only,but not disappear
     */
    private final int WHAT_EXPAND_ONLY = 4;

    public TextViewExpandable(Context context) {
        this(context, null);
    }

    public TextViewExpandable(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TextViewExpandable(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initValue(context, attrs);
        initView(context);
        initClick();
    }

    private void initValue(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TextViewExpandable);
        expandLines = typedArray.getInteger(
                R.styleable.TextViewExpandable_tvea_expandLines, 6);
        drawableShrink = typedArray.getDrawable(
                R.styleable.TextViewExpandable_tvea_shrinkBitmap);
        drawableExpand = typedArray
                .getDrawable(R.styleable.TextViewExpandable_tvea_expandBitmap);
        // 設(shè)置右下角顯示狀態(tài)的文字顏色
        textViewStateColor = typedArray.getColor(
                R.styleable.TextViewExpandable_tvea_textStateColor, ContextCompat.getColor(context, R.color.colorPrimary));
        textShrink = typedArray.getString(R.styleable.TextViewExpandable_tvea_textShrink);
        textExpand = typedArray.getString(R.styleable.TextViewExpandable_tvea_textExpand);
        // 設(shè)置默認(rèn)值
        if (drawableShrink == null) {
            // 支持包的獲取Drawable資源的方法
            drawableShrink = ContextCompat.getDrawable(context, R.drawable.icon_green_arrow_up);
        }
        if (drawableExpand == null) {
            drawableExpand = ContextCompat.getDrawable(context, R.drawable.icon_green_arrow_down);
        }
        if (TextUtils.isEmpty(textShrink)) {
            textShrink = context.getString(R.string.shrink);
        }

        if (TextUtils.isEmpty(textExpand)) {
            textExpand = context.getString(R.string.expand);
        }

        textContentColor = typedArray.getColor(
                R.styleable.TextViewExpandable_tvea_textContentColor, ContextCompat.getColor(context, R.color.color_gray_light_content_text));
        textContentSize = typedArray.getDimension(R.styleable.TextViewExpandable_tvea_textContentSize, 14);
        typedArray.recycle();
    }

    private void initView(Context context) {
        // 得到系統(tǒng)的布局解析器
        LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflate.inflate(R.layout.layout_textview_expand_animation, this);

        rlToggleLayout = (RelativeLayout) layout.findViewById(R.id.rl_expand_text_view_animation_toggle_layout);

        textView = (TextView) layout.findViewById(R.id.tv_expand_text_view_animation);
        textView.setTextColor(textContentColor);
        textView.getPaint().setTextSize(textContentSize);

        ivExpandOrShrink = (ImageView) layout.findViewById(R.id.iv_expand_text_view_animation_toggle);

        tvState = (TextView) layout.findViewById(R.id.tv_expand_text_view_animation_hint);
        tvState.setTextColor(textViewStateColor);
    }

    /**
     * 設(shè)置顯示文本的TextView和顯示底部標(biāo)志的Layout設(shè)置監(jiān)聽(tīng)
     */
    private void initClick() {
        textView.setOnClickListener(this);
        rlToggleLayout.setOnClickListener(this);
    }

    /**
     *
     * @param view
     */
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_expand_text_view_animation:
                clickImageToggle();
                break;
            case R.id.rl_expand_text_view_animation_toggle_layout:
                clickImageToggle();
                break;
        }
    }

    private void clickImageToggle() {
        if (isShrink) {// 如果是折疊狀態(tài)進(jìn)行非折疊處理
            doAnimation(expandLines, textLines, WHAT_EXPAND_ONLY);
        } else {
            doAnimation(textLines, expandLines, WHAT_EXPAND_ONLY);
        }
        isShrink = !isShrink;
    }

    /**
     * 對(duì)外設(shè)置文本的方法
     * @param charSequence:是String的父接口,就是字符序列
     */
    public void setText(CharSequence charSequence) {
        textContent = charSequence;
        // 設(shè)置顯示的TextView顯示文本
        textView.setText(charSequence);
        // A view tree observer is used to register listeners that can be notified of global changes in the view tree.
        // 這是一個(gè)注冊(cè)監(jiān)聽(tīng)視圖樹(shù)的觀察者(observer),在視圖樹(shù)種全局事件改變時(shí)得到通知粗俱。
        // 這里指的全局 事件包括而且不局限在以下幾個(gè):整個(gè)視圖樹(shù)的布局變化葱跋,開(kāi)始繪制視圖,觸摸模式改變等等源梭。
        ViewTreeObserver viewTreeObserver = textView.getViewTreeObserver();
        // Register a callback to be invoked when the view tree is about to be drawn.
        viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {// 返回true代表繼續(xù)當(dāng)前繪制,false代表取消
                // 判斷該View是否應(yīng)該初始化
                if (!isInitTextView) {
                    return true;
                }
                // 未初始化進(jìn)行初始化
                isInitTextView = false;
                // 得到當(dāng)前文本的總行數(shù)
                textLines = textView.getLineCount();
                // 設(shè)置是否需要顯示擴(kuò)展(總行數(shù)與當(dāng)前顯示的行數(shù)作比較)
                isExpandNeeded = textLines > expandLines;
                if (isExpandNeeded) {
                    // 是否啟用折疊標(biāo)志
                    isShrink = true;
                    // 調(diào)用動(dòng)畫(huà)
                    doAnimation(textLines, expandLines, WHAT_ANIMATION_END);
                } else {
                    isShrink = false;
                    doNotExpand();
                }
                return true;
            }
        });
    }

    /**
     * 處理消息
     */
    //Indicates that Lint should ignore the specified warnings for the annotated element.
    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case WHAT:
                    // 不斷修改當(dāng)前TextView的最大行數(shù)
                    textView.setMaxLines(msg.arg1);
                    textView.invalidate();
                    break;
                case WHAT_EXPAND_ONLY:
                    changeExpandState(msg.arg1);
                    break;
                case WHAT_ANIMATION_END:
                    setExpandState(msg.arg1);
                    break;
            }
        }
    };

    /**
     * @param startLines 開(kāi)始動(dòng)畫(huà)的起點(diǎn)行數(shù) <br> start index of animation
     * @param endLines   結(jié)束動(dòng)畫(huà)的終點(diǎn)行數(shù) <br> end index of animation
     * @param what       動(dòng)畫(huà)結(jié)束后的handler信號(hào)標(biāo)示 <br> signal of animation end
     */
    private void doAnimation(final int startLines, final int endLines, final int what) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 如果起始行大于終止行往上折疊到終止行
                if (startLines > endLines) {
                    int count = startLines;
                    while (count-- > endLines) {
                        Message msg = handler.obtainMessage(WHAT, count, 0);
                        // 休眠一定時(shí)刻
                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        handler.sendMessage(msg);
                    }
                } else if (startLines < endLines) {
                    // 如果起始行小于終止行向下擴(kuò)展到終止行
                    int count = startLines;
                    while (count++ < endLines) {
                        Message msg = handler.obtainMessage(WHAT, count, 0);

                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        handler.sendMessage(msg);
                    }
                }
                // 動(dòng)畫(huà)結(jié)束后發(fā)送結(jié)束的信號(hào)
                // animation end,send signal
                Message msg = handler.obtainMessage(what, endLines, 0);
                handler.sendMessage(msg);
            }
        }).start();
    }

    /**
     * 負(fù)責(zé)改變折疊或展開(kāi)狀態(tài)的方法
     * @param endLines
     */
    private void changeExpandState(int endLines) {
        rlToggleLayout.setVisibility(VISIBLE);
        if (endLines > expandLines) {// 顯示展開(kāi)的狀態(tài)
            ivExpandOrShrink.setBackground(drawableShrink);
            tvState.setText(textShrink);
        } else {// 顯示折疊的狀態(tài)
            ivExpandOrShrink.setBackground(drawableExpand);
            tvState.setText(textExpand);
        }
    }

    /**
     * 設(shè)置折疊或展開(kāi)的狀態(tài)方法
     * @param endLines
     */
    private void setExpandState(int endLines) {
        if (endLines < textLines) {// 小于總行數(shù)稍味,設(shè)置為可以折疊或擴(kuò)展?fàn)顟B(tài)
            isShrink = true;
            rlToggleLayout.setVisibility(VISIBLE);
            ivExpandOrShrink.setBackground(drawableExpand);
            textView.setOnClickListener(this);
            tvState.setText(textExpand);
        } else {// 設(shè)置為不顯示折疊狀態(tài)
            Log.e("xns", "not show shrink");
            isShrink = false;
            rlToggleLayout.setVisibility(GONE);
            ivExpandOrShrink.setBackground(drawableShrink);
            textView.setOnClickListener(null);
            tvState.setText(textShrink);
        }
    }

    /**
     * 無(wú)需折疊
     * do not expand
     */
    private void doNotExpand() {
        textView.setMaxLines(expandLines);
        rlToggleLayout.setVisibility(GONE);
        textView.setOnClickListener(null);
    }

    public Drawable getDrawableShrink() {
        return drawableShrink;
    }

    public void setDrawableShrink(Drawable drawableShrink) {
        this.drawableShrink = drawableShrink;
    }

    public Drawable getDrawableExpand() {
        return drawableExpand;
    }

    public void setDrawableExpand(Drawable drawableExpand) {
        this.drawableExpand = drawableExpand;
    }

    public int getExpandLines() {
        return expandLines;
    }

    public void setExpandLines(int newExpandLines) {
        int startLines = isShrink ? expandLines : textLines;
        int endLines = newExpandLines > textLines ? newExpandLines : textLines;
        doAnimation(startLines, endLines, WHAT_ANIMATION_END);
        expandLines = newExpandLines;
    }

    /**
     * 取得顯示的文本內(nèi)容
     * get content text
     *
     * @return content text
     */
    public CharSequence getTextContent() {
        return textContent;
    }

    public int getSleepTime() {
        return sleepTime;
    }

    public void setSleepTime(int sleepTime) {
        this.sleepTime = sleepTime;
    }
}
  • 整體設(shè)計(jì)的精髓即是通過(guò)handle接受Message后废麻,不斷的修改內(nèi)部TextView的最大行數(shù),然后調(diào)用該TextView的初始化方法模庐,來(lái)完成動(dòng)畫(huà)的顯示烛愧。
  • 這里還涉及到一個(gè)新的知識(shí)點(diǎn)即ViewTreeObserver類,簡(jiǎn)單來(lái)說(shuō)它是一個(gè)監(jiān)聽(tīng)ViewTree的觀察者掂碱,在視圖樹(shù)中全局事件改變時(shí)得到通知怜姿。全局事件包括但不局限于如:整個(gè)視圖樹(shù)的布局變化,開(kāi)始繪制視圖疼燥,觸摸模式改變等沧卢。
    ViewTreeObserver是不能被應(yīng)用程序?qū)嵗模驗(yàn)樗怯梢晥D提供的醉者,通過(guò)view.getViewTreeObserver()獲取但狭。
    網(wǎng)上有很多關(guān)于這個(gè)類的介紹,這里我推薦一篇博文撬即,你可以大致了解這個(gè)類的一些基本知識(shí)立磁。

其余都是一些邏輯上的代碼,通過(guò)注釋我相信大家都可以讀懂它的實(shí)現(xiàn)方法剥槐。朝陽(yáng)在前方唱歧,同志們繼續(xù)前進(jìn)吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末粒竖,一起剝皮案震驚了整個(gè)濱河市颅崩,隨后出現(xiàn)的幾起案子几于,更是在濱河造成了極大的恐慌,老刑警劉巖挨摸,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孩革,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡得运,警方通過(guò)查閱死者的電腦和手機(jī)膝蜈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)熔掺,“玉大人饱搏,你說(shuō)我怎么就攤上這事≈寐撸” “怎么了推沸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)券坞。 經(jīng)常有香客問(wèn)我鬓催,道長(zhǎng),這世上最難降的妖魔是什么恨锚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任宇驾,我火速辦了婚禮,結(jié)果婚禮上猴伶,老公的妹妹穿的比我還像新娘课舍。我一直安慰自己,他們只是感情好他挎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布筝尾。 她就那樣靜靜地躺著,像睡著了一般办桨。 火紅的嫁衣襯著肌膚如雪筹淫。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天崔挖,我揣著相機(jī)與錄音贸街,去河邊找鬼。 笑死狸相,一個(gè)胖子當(dāng)著我的面吹牛薛匪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脓鹃,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼逸尖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起娇跟,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤岩齿,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后苞俘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體盹沈,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年吃谣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乞封。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岗憋,死狀恐怖肃晚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仔戈,我是刑警寧澤关串,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站监徘,受9級(jí)特大地震影響晋修,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凰盔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一飞蚓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧廊蜒,春花似錦、人聲如沸溅漾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)添履。三九已至屁倔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間暮胧,已是汗流浹背锐借。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留往衷,地道東北人钞翔。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像席舍,于是被迫代替她去往敵國(guó)和親布轿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)汰扭,斷路器稠肘,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件萝毛、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,102評(píng)論 4 62
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程项阴,因...
    小菜c閱讀 6,409評(píng)論 0 17
  • 選擇這個(gè)視頻的初衷: 被標(biāo)題吸引,我是一個(gè)相對(duì)感性的人笆包,看到這樣的標(biāo)題环揽,就很容易被電到 聽(tīng)完之后的總結(jié): ...
    親子思維導(dǎo)圖講師燕子閱讀 246評(píng)論 2 0
  • 【清平樂(lè).夢(mèng)傷】 情深幾許?淚酒凄杯續(xù)色查。舊事沉溟歸夢(mèng)里薯演, 側(cè)轉(zhuǎn)經(jīng)年不去。高樓怨曲殘陽(yáng)秧了,隨風(fēng)透冷成寒...
    青山精神病患者閱讀 301評(píng)論 0 2