炫酷的loadingView

最近比較忙,煩心的事情也不少弓候。就迷上了一款游戲《守望先鋒》,差點(diǎn)就沒回來他匪。

言歸正傳菇存,前些日子看到一個(gè)很炫酷的loadingView打掘,看到的時(shí)候感覺迈套,這個(gè)感覺怎么說呢,用英語說就是amazing(太TM吊了)兆览。
我也僅僅只是通過別人的博客悼沈,加上一點(diǎn)自己的理解寫的這篇博客贱迟,目的是想要和大家分享,順便記錄一下絮供。感覺實(shí)現(xiàn)一個(gè)這么炫酷的動(dòng)畫還是感覺挺有成就感動(dòng)的(畢竟菜鳥一枚)衣吠。這里先放上原博主的鏈接,感謝這位大神壤靶。這邊博客把實(shí)現(xiàn)過程已經(jīng)寫的很清晰的建議有些自定義view基礎(chǔ)的人缚俏,先去看這里先放上原博主的博客,然后自己實(shí)現(xiàn)以下贮乳,我這里會(huì)對(duì)整個(gè)view的實(shí)現(xiàn)過程詳細(xì)的講一下忧换。

此次時(shí)間有點(diǎn)倉(cāng)促,沒有對(duì)代碼進(jìn)行優(yōu)化向拆,同時(shí)也有部分原作者的代碼亚茬。希望大家諒解,主要是給大家提供一個(gè)思路浓恳。

先看一下效果圖:



怎么樣刹缝,我沒說錯(cuò)吧碗暗,第一眼看見就眼前一亮。下面我們就對(duì)整個(gè)過程進(jìn)行詳細(xì)的講解赞草。

拆分動(dòng)畫

  • 和葉子一樣顏色的進(jìn)度條
  • 右側(cè)旋轉(zhuǎn)的白色電風(fēng)扇
  • 漂浮的葉子(原博主說的很細(xì)致我這里直接引用原話)
    1.葉子的隨機(jī)產(chǎn)生讹堤;
    2.葉子隨著一條正余弦曲線移動(dòng);
    3.葉子在移動(dòng)的時(shí)候旋轉(zhuǎn)厨疙,旋轉(zhuǎn)方向隨機(jī)洲守,正時(shí)針或逆時(shí)針;
    4.葉子遇到進(jìn)度條沾凄,似乎是融合進(jìn)入梗醇;
    5.葉子不能超出最左邊的弧角;
    7.葉子飄出時(shí)的角度不是一致撒蟀,走的曲線的振幅也有差別叙谨,否則太有規(guī)律性,缺乏美感保屯;
  • 最后又一個(gè)結(jié)束動(dòng)畫手负,風(fēng)扇消失,然后“100%”出現(xiàn)

整個(gè)動(dòng)畫就是這樣子的姑尺,難點(diǎn)就是繪制葉子要滿足以上的7點(diǎn)竟终。

定義屬性

    private static final int DEFAULT_BG_OUTER = 0xfffde399; // 外部邊框的背景顏色
    private static final String DEFAULT_WHITE = "#fffefd";
    private static final int DEFAULT_BG_INNER = 0xffffa800;  //內(nèi)部進(jìn)度條的顏色
    private static final String DEFAULT_BG_FAN = "#fcce5b";  // 風(fēng)扇 扇葉的顏色

    private static final int DEFAULT_WIDTH = 300;
    private static final int DEFAULT_HEIGHT = 600;

    //振幅的強(qiáng)度
    private static final int LOW_AMPLITUDE = 0;
    private static final int NORMAL_AMPLITUDE = 1;
    private static final int HIGH_AMPLITUDE = 2;

    private static final int DEFAULT_AMPLITUDE = 20;

    // 葉子飄動(dòng)一個(gè)周期所花的時(shí)間
    private static final int LEAF_FLY_TIME = 2000;
    private static final int LEAF_ROTATE_TIME = 2000;

    private Resources mResources;

    // 定義畫筆
    private Paint innerPaint;
    private Paint outerPaint;
    private Paint fanPaint;
    private Paint fanBgPaint;
    private Paint textPaint;

    // view的大小 和 “100%”的高度
    private int mWidth;
    private int mHeight;
    private float textHeight;

    //外部圓半徑 內(nèi)部圓半徑  風(fēng)扇背景的半徑
    private float outerRadius;
    private float innerRadius;
    private float fanBgRadius;

    //各種路徑
    private RectF outerCircle;
    private RectF outerRectangle;
    private RectF innerCircle;
    private RectF innerRectangle;
    private RectF fanWhiteRect;

    //電風(fēng)扇 扇葉路徑
    private Path mPath;
    private Path nPath;

    // 定義結(jié)束的屬性動(dòng)畫
    private ValueAnimator progressAnimator;
    private ValueAnimator completedAnimator;

    //進(jìn)度值
    private float maxProgress = 100;
    private float currentProgress;
    private float completedProgress;

    //計(jì)算時(shí)間增量和progress增量
    private long preTime ;
    private long addTime;
    private float addProgress;
    private float preProgress;

    //先填充半圓的進(jìn)度 和 長(zhǎng)方形的時(shí)間
    private float firstStepTime;
    private float secondStepTime;

    //和葉片相關(guān)
    private Bitmap mLeafBitmap;
    private int mLeafWidth;
    private int mLeafHeight;
    private int mLeafFlyTime = LEAF_FLY_TIME;
    private int mLeafRotateTime = LEAF_ROTATE_TIME;
    private int mAddTime;
    private float mAmplitudeDisparity = DEFAULT_AMPLITUDE;

    //判斷是否加載完畢 然后執(zhí)行結(jié)束動(dòng)畫
    private boolean isFinished;

    //精度條的總長(zhǎng)度
    private float mProgressWidth;

    private List<Leaf> leafInfos;

    //對(duì) 外面的邊框緩存
    private WeakReference<Bitmap> outBorderBitmapCache;

這里定義的屬性比較多,但是還是都通熟易懂的切蟋。

OnDraw()

我們這先看一下onDraw方法吧统捶,整個(gè)的繪制流程是都放生在這個(gè)方法里面。我們先梳理一下繪制的流程柄粹,具體畫每個(gè)圖形后面我會(huì)詳細(xì)講解喘鸟。

protected void onDraw(Canvas canvas) {

        //判斷背景有沒有緩存(這里的背景是指,黃色進(jìn)度條外面的邊框)
        Bitmap outBorderBitmap = outBorderBitmapCache == null ? null : outBorderBitmapCache.get();

        if (outBorderBitmap == null || outBorderBitmap.isRecycled()) {
            outBorderBitmap = getBitmap();
            outBorderBitmapCache = new WeakReference<Bitmap>(outBorderBitmap);
        }
  
        //對(duì)畫布保存主要是要用Xfermode對(duì)圖像處理驻右,主要是不想讓葉子飛出邊界
        //如果不了解Xfermode的同學(xué)建議先去看一下什黑,很有用的一個(gè)東西
        int sc = canvas.saveLayer(0, 0, mWidth, mHeight, null, Canvas.MATRIX_SAVE_FLAG |
                Canvas.CLIP_SAVE_FLAG |
                Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
                Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
                Canvas.CLIP_TO_LAYER_SAVE_FLAG);

        canvas.drawBitmap(outBorderBitmap, 0, 0, outerPaint);
        //        canvas.translate(mWidth / 10, mHeight / 2);

        //畫葉子
        drawLeaf(canvas);
        //恢復(fù)畫布
        canvas.restoreToCount(sc);

        canvas.translate(mWidth / 10, mHeight / 2);

        //畫內(nèi)部圓
        drawInnerCircle(canvas);

        //畫風(fēng)扇白色的背景
        canvas.drawArc(fanWhiteRect, 90, 360, true, fanPaint);

        //畫風(fēng)扇的黃色背景
        canvas.save();
        canvas.scale(0.9f, 0.9f, 8 * outerRadius, 0);
        canvas.drawArc(fanWhiteRect, 90, 360, true, fanBgPaint);
        canvas.restore();

        //畫扇葉
        canvas.save();
        drawFan(canvas, true);
        canvas.restore();

        //結(jié)束動(dòng)畫
        //結(jié)束動(dòng)畫是指 電風(fēng)扇的扇葉從扇葉變成100%字樣
        if (isFinished) {
            showCompletedText(canvas);
        } else {
            //這里重新繪制 主要是為了畫葉子
            invalidate();
        }

    }

首先我們先說一下畫背景(這里的背景指的是進(jìn)度條外面的邊框)

先看一下具體實(shí)現(xiàn)

public Bitmap getBitmap() {
          //這里先產(chǎn)生一個(gè)一個(gè)畫布,畫布的大小就是view的大小
        Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight,Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.translate(mWidth / 10, mHeight / 2);

        canvas.drawArc(outerCircle, 90, 180, true, outerPaint);
        canvas.drawRect(outerRectangle, outerPaint);
        return bitmap;
    }

這里我們讓背景作為bitmap返回主要是 要使用Xfermode方法旺入。先移動(dòng)坐標(biāo)系到我們想要的位置兑凿,然后背景是由一個(gè)左半圓和一個(gè)矩形組成。至于為什么要使用Xfermode茵瘾,這里先說明一下礼华,我們期望葉子是不可以飄出背景外的。(就是說葉子飄出背景外的地方要變成透明的)拗秘。

畫進(jìn)度條

    //先填充半圓
    private void drawInnerCircle(Canvas canvas) {
        firstStepProgress = innerRadius / (innerRadius + 7 * outerRadius);
        if (currentProgress > firstStepProgress) {
            canvas.drawArc(innerCircle, 90, 180, true, innerPaint);
            drawInnerRectangle(canvas);
        } else {
            //這里就是繪制半圓的執(zhí)行(方法是繪制圓皇バ酢)
            canvas.drawArc(innerCircle, 180 - 90 * currentProgress / firstStepTime, 180 * currentProgress / firstStepTime, false, innerPaint);
        }
    }

    //填充剩下的長(zhǎng)方形
    private void drawInnerRectangle(Canvas canvas) {
        secondStepProgress = 1 - firstStepProgress;
        //判斷是否結(jié)束,結(jié)束了會(huì)執(zhí)行結(jié)束動(dòng)畫
        if (currentProgress >= 1) {
            if (!isFinished) {
                isFinished = true;
                completedAnimator.start();
            }
        } else {
            canvas.drawRect(-1, -innerRadius, 7 * outerRadius * (currentProgress - firstStepProgress) / secondStepProgress, innerRadius, innerPaint);

        }
    }

進(jìn)度條和背景是一樣的雕旨,都是先都前半圓和一個(gè)矩形組成的扮匠。先計(jì)算半圓所占進(jìn)度捧请,當(dāng)currentProgress沒有超過firstStepProgress時(shí)候,先繪制半圓部分棒搜,之后繪制矩形疹蛉。

繪制風(fēng)扇

參數(shù)分別是 canvas 畫布,isNeedRotate 風(fēng)扇是否旋轉(zhuǎn)力麸。

    //畫扇葉
    private void drawFan(Canvas canvas, boolean isNeedRotate) {
        canvas.save();
        //加載的時(shí)候旋轉(zhuǎn)風(fēng)扇可款,負(fù)數(shù)是逆時(shí)針旋轉(zhuǎn),默認(rèn)旋轉(zhuǎn)5圈
        if (isNeedRotate) {
            canvas.rotate(-currentProgress * 360 * 5, 8 * outerRadius, 0);
        }
        //結(jié)束動(dòng)畫時(shí)候需要不斷的縮小風(fēng)扇克蚂,然后“100%”從小變大
        if (completedProgress != 0) {
            canvas.scale(1 - completedProgress, 1 - completedProgress, 8 * outerRadius, 0);
        }
        //旋轉(zhuǎn)畫扇葉闺鲸,扇葉使用path繪制的
        for (float i = 0; i <= 270; i = i + 90) {
            canvas.rotate(i, 8 * outerRadius, 0);
            canvas.drawPath(mPath, fanPaint);
        }
        //這個(gè)是風(fēng)扇中間的小點(diǎn)
        canvas.drawCircle(8 * outerRadius, 0, 5 * (1 - completedProgress), fanPaint);
        canvas.restore();
    }

繪制結(jié)束動(dòng)畫

結(jié)束動(dòng)畫 這里我們用的是屬性動(dòng)畫提供的0-1的值實(shí)現(xiàn)的。這個(gè)過程主要是把進(jìn)度條補(bǔ)齊以及風(fēng)扇消失埃叭,然后“100%”字樣顯示摸恍。

    //結(jié)束時(shí)動(dòng)畫 展示“100%”字樣
    private void showCompletedText(Canvas canvas) {
        //補(bǔ)齊進(jìn)度條
        canvas.drawRect(-1, -innerRadius, (7 + completedProgress) * outerRadius, innerRadius, innerPaint);
        canvas.drawArc(fanWhiteRect, 90, 360, true, fanPaint);
           
        //繪制風(fēng)扇的背景
        canvas.save();
        canvas.scale(0.9f, 0.9f, 8 * outerRadius, 0);
        canvas.drawArc(fanWhiteRect, 90, 360, true, fanBgPaint);
        canvas.restore();
        
        if (completedProgress == 1) {
            textPaint.setTextSize(60);
            canvas.drawText("100%", 8 * outerRadius, textHeight, textPaint);
        } else {
            drawFan(canvas, completedProgress, false);
            textPaint.setTextSize(60 * completedProgress);
            canvas.drawText("100%", 8 * outerRadius, textHeight, textPaint);
        }

    }

繪制葉子

因?yàn)槿~子是一直在飄蕩的,這里利用系統(tǒng)的時(shí)間赤屋,來計(jì)算葉子的坐標(biāo)立镶。


private class Leaf {
        // 在繪制部分的位置
        float x, y;
        // 控制葉子飄動(dòng)的幅度
        int type;
        // 旋轉(zhuǎn)角度
        int rotateAngle;
        // 旋轉(zhuǎn)方向--0代表順時(shí)針,1代表逆時(shí)針
        int rotateDirection;
        // 起始時(shí)間(ms)
        long startTime;
    }

    /**
     * 畫葉子
     */
    private void drawLeaf(Canvas canvas) {

        long currentTime = System.currentTimeMillis();
        canvas.save();
        //這里進(jìn)行了 一次畫布平移
        canvas.translate(mWidth / 10 - innerRadius, mHeight / 2 - outerRadius);
        for (Leaf leaf : leafInfos) {
            //如果系統(tǒng)當(dāng)前的時(shí)間大于葉子開始繪制的時(shí)間类早,就去獲取葉子的坐標(biāo)
            if (currentTime > leaf.startTime && leaf.startTime != 0) {
                getLocation(leaf, currentTime);
                // 通過時(shí)間關(guān)聯(lián)旋轉(zhuǎn)角度谜慌,則可以直接通過修改LEAF_ROTATE_TIME調(diào)節(jié)葉子旋轉(zhuǎn)快慢
                float rotateFraction = ((currentTime - leaf.startTime) % mLeafRotateTime)
                        / (float) mLeafRotateTime;
                int angle = (int) (rotateFraction * 360);
                int rotate = leaf.rotateDirection == 0 ? angle + leaf.rotateAngle : -angle
                        + leaf.rotateAngle;
                //用矩陣進(jìn)行坐標(biāo)轉(zhuǎn)換
                Matrix matrix = new Matrix();
                matrix.reset();
                matrix.postTranslate(leaf.x, leaf.y);

                matrix.postRotate(rotate, leaf.x + mLeafWidth / 2, leaf.y + mLeafHeight / 2);
                //對(duì)畫筆設(shè)置Xfermode
                outerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
                canvas.drawBitmap(mLeafBitmap, matrix, outerPaint);
                outerPaint.setXfermode(null);
            } else {
                continue;
            }

        }
        canvas.restore();
    }

    //獲取葉子當(dāng)前的位置
    public void getLocation(Leaf leaf, long currentTime) {
        //計(jì)算當(dāng)前的時(shí)間和葉子繪制的時(shí)間的差值
        long intervalTime = currentTime - leaf.startTime;
        if (intervalTime < 0) {
            //不對(duì)此片葉子進(jìn)行繪制,還沒到它出場(chǎng)的時(shí)間
            return;
        } else if (intervalTime > mLeafFlyTime) {
            //重置葉子的出場(chǎng)時(shí)間
            leaf.startTime = System.currentTimeMillis()
                    + new Random().nextInt(mLeafFlyTime);
        }
        float fraction = (float) intervalTime / mLeafFlyTime;
        leaf.x = getLeafX(fraction);
        leaf.y = getLeafY(leaf);
    }

    //獲取葉子x坐標(biāo)
    public float getLeafX(float fraction) {
        return mProgressWidth * (1 - fraction);
    }

    //獲取葉子y坐標(biāo)莺奔,用到sin函數(shù),多處用到random是為了讓葉子顯的更加自然
    public float getLeafY(Leaf leaf) {
        float w = (float) (2 * Math.PI / mProgressWidth);
        float a = outerRadius / 2;
        switch (leaf.type) {
            case LOW_AMPLITUDE:
                // 小振幅 = 中等振幅 - 振幅差
                a = -mAmplitudeDisparity;
                break;
            case NORMAL_AMPLITUDE:
                break;
            case HIGH_AMPLITUDE:
                // 小振幅 = 中等振幅 + 振幅差
                a = +mAmplitudeDisparity;
                break;
            default:
                break;
        }

        return (float) (a * Math.sin((w * leaf.x))) - mLeafHeight / 2 + outerRadius;
    }



最后放上效果圖

可能看著和原著有點(diǎn).......变泄,嘿嘿令哟,原諒我沒有進(jìn)行優(yōu)化,大家看看思路就可以了妨蛹。代碼地址

本文參考了一個(gè)絢麗的loading動(dòng)效分析與實(shí)現(xiàn)屏富!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蛙卤,隨后出現(xiàn)的幾起案子狠半,更是在濱河造成了極大的恐慌,老刑警劉巖颤难,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件神年,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡行嗤,警方通過查閱死者的電腦和手機(jī)已日,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栅屏,“玉大人飘千,你說我怎么就攤上這事堂鲜。” “怎么了护奈?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵缔莲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我霉旗,道長(zhǎng)痴奏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任奖慌,我火速辦了婚禮抛虫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘简僧。我一直安慰自己建椰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布岛马。 她就那樣靜靜地躺著棉姐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啦逆。 梳的紋絲不亂的頭發(fā)上伞矩,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音夏志,去河邊找鬼乃坤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛沟蔑,可吹牛的內(nèi)容都是我干的湿诊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼瘦材,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼厅须!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起食棕,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤朗和,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后簿晓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眶拉,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年抢蚀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了镀层。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖唱逢,靈堂內(nèi)的尸體忽然破棺而出吴侦,到底是詐尸還是另有隱情,我是刑警寧澤坞古,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布备韧,位于F島的核電站,受9級(jí)特大地震影響痪枫,放射性物質(zhì)發(fā)生泄漏织堂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一奶陈、第九天 我趴在偏房一處隱蔽的房頂上張望易阳。 院中可真熱鬧,春花似錦吃粒、人聲如沸潦俺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽事示。三九已至,卻和暖如春僻肖,著一層夾襖步出監(jiān)牢的瞬間肖爵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工臀脏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劝堪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓揉稚,卻偏偏與公主長(zhǎng)得像幅聘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窃植,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,522評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件荐糜、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,030評(píng)論 4 62
  • 轉(zhuǎn)自 http://blog.csdn.net/shimiso** 前言:**介于許多人對(duì)項(xiàng)目經(jīng)理這個(gè)職位的陌生和...
    酒紅色的小貓一閱讀 500評(píng)論 0 4
  • 貓大人的一個(gè)“好消息”:我被選上班級(jí)圖書管理員啦巷怜! 此處鼓掌三百下! 嘿嘿暴氏,老子也是圖書管理員哦~博覽群書之后寫出...
    瞅瞅君與貓大人閱讀 969評(píng)論 0 2
  • 自古以來延塑,中國(guó)的謙卑文化教育我們說:謙虛使人進(jìn)步,驕傲使人落后答渔。讓我們一直活在一種壓抑的情緒里关带。明明心里很開心,卻...
    呂桂平閱讀 1,175評(píng)論 0 0