Android動(dòng)畫之萌萌噠蠟燭吹蠟燭動(dòng)畫

一年栓、簡(jiǎn)介

最近開(kāi)始寫一些文章記錄一下以前的一些自己寫的小項(xiàng)目或者是定義View積累拆挥,積灰的東西還是要多翻出來(lái)整理整理看看的,在我的csdn上也有某抓。這個(gè)只完成了一部分燃起熄滅的動(dòng)畫纸兔,沒(méi)有為何燃起火焰的動(dòng)畫,希望有興趣的同學(xué)也可以接著完成并分享否副,話不多說(shuō)汉矿,我們來(lái)看這兩根萌萌的小蠟燭。

candle.gif

小蠟燭憋足氣把火焰燃起备禀,一下被旁邊的哥們吹滅了 0^0 ,看起來(lái)還是萌氣十足的啊洲拇。看著圖大家應(yīng)該能想到應(yīng)該怎么實(shí)現(xiàn)了吧曲尸,自定義View赋续!對(duì)了,但是具體要怎么把這個(gè)過(guò)程做好呢另患,跟著腳步一起來(lái)看一看吧纽乱。代碼稍微有點(diǎn)多,大家耐心觀看昆箕,有興趣的同學(xué)可以從我的GITHUB上clone下來(lái)鸦列,對(duì)著代碼看。

二鹏倘、過(guò)程實(shí)現(xiàn)

蠟燭的繪制和動(dòng)畫
  • 本著面向?qū)ο蟮乃枷胧磬停苊黠@這里就是兩個(gè)蠟燭嘛!既然是這樣那我們就定義一個(gè)蠟燭類具有蠟燭的基本屬性纤泵。


    image.png
public abstract class ICandle {

    //蠟燭底部左下坐標(biāo)
    protected int mCurX;
    protected int mCurY;
    //蠟燭寬高
    protected int mCandleWidth;
    protected int mCandleHeight;
    //蠟燭左眼坐標(biāo)
    protected Point mEyeLPoint;
    //蠟燭右眼坐標(biāo)
    protected Point mEyeRPoint;
    //蠟燭眼睛半徑
    protected int mEyeRadius;
    //眼睛間隔距離
    protected int mEyeDevide;
    //身體顏色
    protected int mCandleColor;
    //是否停止動(dòng)畫中
    protected boolean mIsAnimStoping = false;
    //蠟燭芯坐標(biāo)
    protected Point mCandlewickPoint;
    public void initAnim(){
    }
    public void stopAnim(){
    }
    public void drawSelf(Canvas canvas){
    }
}```
對(duì)應(yīng)著這蠟燭還有代碼骆姐,那就一目了然了。可能需要解釋的應(yīng)該就是下面的幾個(gè)方法了` public void initAnim()`诲锹, `stopAnim()`初始化開(kāi)始和結(jié)束動(dòng)畫需要的數(shù)據(jù)繁仁,小蠟燭將會(huì)實(shí)現(xiàn)這個(gè)方法,`drawSelf(Canvas canvas)`把畫布傳進(jìn)來(lái)然后蠟燭自己繪制自己归园。
現(xiàn)在就是讓我們來(lái)看一看小蠟燭身體內(nèi)部構(gòu)造的時(shí)候了黄虱,**hiahiahiahia!**
不對(duì)庸诱,和蠟燭生死相隨的還有火焰呢捻浦!先來(lái)看看火焰吧,等下小蠟燭還要燃燒自己呢桥爽。**+10086s**
+ **Flame**
一樣先來(lái)一睹我們的富勒姆真容
![flame.png](http://upload-images.jianshu.io/upload_images/2934422-44fd38d11b58617d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![flamex.png](http://upload-images.jianshu.io/upload_images/2934422-381f4978524815e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

好像也沒(méi)什么毛病朱灿,首先是里面的區(qū)域,就是Flame啦钠四,外面的呢盗扒,就是Flame先生燃燒自己散發(fā)的人性之光和飄散的骨灰(手動(dòng)抹眼淚)。
來(lái)看一下Flame的實(shí)現(xiàn)吧缀去。我們一步步分析侣灶。
private static float CHANGE_FACTOR = 20;
private Paint mPaint;
private Path mPath;
//左下點(diǎn)坐標(biāo)
private int mCurX;
private int mCurY;
//火焰寬度
private int mWidth;
//火焰高度
private int mHeight;
//記錄初始高度
private int mPreHeight;
//記錄初始寬度
private int mPreWidth;
//火焰頂部貝塞爾曲線控制點(diǎn)變化參數(shù)
private int mTopXFactor;
private int mTopYFactor;
//用于實(shí)現(xiàn)火焰的抖動(dòng)
private Random mRandom;
//光環(huán)半徑
private int mHaloRadius;
//正在燃燒
private boolean mIsFiring;
//是否啟動(dòng)停止動(dòng)畫
private boolean mIsStopAnim = false;
private boolean mFlagStop = false;
private LinearGradient mLinearGradient;
private RadialGradient mRadialGradient;

private ValueAnimator mFlameAnimator;
private ValueAnimator mHaloAnimator;```

參數(shù)就是這些了,主要是我們的動(dòng)畫實(shí)現(xiàn)過(guò)程缕碎,也就是我們的屬性動(dòng)畫ValueAnimator 這里還有兩個(gè)渲染類不知道大家用過(guò)沒(méi)有褥影,LinearGradientRadialGradient不了解的同學(xué)可以直接點(diǎn)鏈接我的csdn上我的博文了解一下。LinearGradient繪制出了火焰咏雌,RadialGradient繪制除了發(fā)散的光芒凡怎。
初始化的過(guò)程我就不寫了,大家對(duì)這代碼看吧赊抖。那主要的就是小火焰的是怎么繪制出來(lái)的呢 show the code

    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setShader(mLinearGradient);
    mPath.reset();
    mPath.moveTo(mCurX, mCurY);
    mPath.quadTo(mCurX + mWidth / 2,
            mCurY + mHeight / 3,
            mCurX + mWidth, mCurY);
    mPath.quadTo(mCurX + mWidth / 2 + ((1 - mRandom.nextFloat()) * CHANGE_FACTOR) + mTopXFactor,
            mCurY - 2 * mHeight + mTopYFactor,
            mCurX, mCurY);
    canvas.drawPath(mPath, mPaint);```
這就是火焰flame的繪制统倒,可以看到這里用到了二次貝塞爾曲線的繪制,不太清楚貝塞爾曲線的同學(xué)也可以點(diǎn)這[波浪Loading動(dòng)畫(貝塞爾曲線)](http://blog.csdn.net/xiong_1203/article/details/53453408)有簡(jiǎn)單的介紹熏迹,當(dāng)時(shí)是用在一個(gè)水波的view里面檐薯。這里的繪制是以前面那個(gè)圖里面的矩形為參照,我們?cè)賮?lái)看一下這個(gè)圖(當(dāng)然是加強(qiáng)版hiahia)注暗。
![flame.png](http://upload-images.jianshu.io/upload_images/2934422-daa719c1eda69309.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
那為什么上面的x坐標(biāo)還加了`mRandom.nextFloat()) * CHANGE_FACTOR`呢?你想啊墓猎,火焰不是會(huì)左右晃動(dòng)嗎捆昏,利用一個(gè)隨機(jī)來(lái)控制左右擺動(dòng)咯。
mFlameAnimator = ValueAnimator.ofFloat(0, 4).setDuration(4000);
mFlameAnimator.setRepeatCount(ValueAnimator.INFINITE);
mFlameAnimator.addUpdateListener(
               new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float zeroToOne = (float) animation.getAnimatedValue();
        if (zeroToOne >= 1.0f && zeroToOne <= 1.2f) {
            //火焰燃起
            zeroToOne = 1.0f - 5 * (zeroToOne - 1.0f);//1-0
            mHeight = (int) (mPreHeight * (1 - zeroToOne));
            mIsFiring = true;
        } else if (zeroToOne >= 3.5f) {
            if (mFlagStop) {
                mFlameAnimator.cancel();
                return;
            }
            //火焰被吹滅
            zeroToOne = 2 * (zeroToOne - 3.5f);//0-2
            mTopXFactor = (int) (-20 * zeroToOne);
            mTopYFactor = (int) (160 * zeroToOne);

// mWidth = (int) (mPreWidth * (1 -zeroToOne));
mIsFiring = false;
}
}
});```
在4秒的時(shí)間內(nèi)毙沾,火焰進(jìn)行了一系列活動(dòng)骗卜,從下面隨著燈芯移上來(lái),不斷的改變火焰的位置,分為了兩部分寇仓,火焰燃起火焰熄滅举户,從代碼中可以看到,火焰燃起時(shí)mHeight慢慢變大遍烦,然后就是有了升起的過(guò)程辣俭嘁,另外一個(gè)就是火焰被吹滅的時(shí)候,因?yàn)榇禍绲臅r(shí)候火焰的高度肯定是保持之前的值服猪,所以不需要改變供填,而是用了mTopXFactormTopYFactor這個(gè)兩個(gè)因子來(lái)控制火焰的位置。好了罢猪,既然火焰有了近她,蠟炬成灰淚始干啊,生命之光也該出場(chǎng)了膳帕。
光圈的繪制和動(dòng)畫就相對(duì)簡(jiǎn)單了

            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(5);
            mPaint.setShader(mRadialGradient);
            canvas.drawCircle(mCurX + mWidth / 2,
                         mCurY - mHeight / 2, mHaloRadius, mPaint);
            canvas.drawCircle(mCurX + mWidth / 2,
                         mCurY - mHeight / 2, mHaloRadius + 5, mPaint);
            canvas.drawCircle(mCurX + mWidth / 2,
                         mCurY - mHeight / 2, mHaloRadius - 5, mPaint);```
    mHaloAnimator = ValueAnimator.ofFloat(0, 1).setDuration(500);
    mHaloAnimator.setRepeatCount(ValueAnimator.INFINITE);
    mHaloAnimator.addUpdateListener(
                     new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float zeroToOne = (float) animation.getAnimatedValue();
            if (mIsFiring) {
                mHaloRadius = (int) (70 + zeroToOne % 1.0f * 20);
            }
        }
    });```

這里改變的只有一個(gè)參數(shù)粘捎,mHaloRadius也就是光圈的半徑。但是不要忘了危彩,其他參數(shù)同時(shí)也是在改變的呢攒磨,只不過(guò)是放在了mFlameAnimator里面。
好了介紹到這Flame的介紹完了恬砂,任重而道遠(yuǎn)啊咧纠,寫了這么多卻還沒(méi)完結(jié),讓我想到一某位古人說(shuō)過(guò)泻骤,不是我漆羔。

還未老死,就先累死

  • FireCandle
    這名字有點(diǎn)奇怪狱掂,火燭演痒,厲害了Word哥。前面已經(jīng)介紹過(guò)ICandle了趋惨,現(xiàn)在來(lái)看一下他的實(shí)現(xiàn)類鸟顺,蠟燭兩兄弟之FireCandle。
    初始化照例也就不說(shuō)了器虾,來(lái)看該有的變量讯嫂。
    private Paint mPaint;
    //中心X坐標(biāo)
    private int mCenterX;
    //記錄初始寬
    private int mPreWidth;
    //記錄初始高
    private int mPreHeight;
    //蠟燭芯旋轉(zhuǎn)角
    private int mCandlewickDegrees = 0;
    private Flame mFlame;
    private boolean mIsFire = false;
    private boolean mIsStateOnStart = false;
    private boolean mIsStateOnEnd = false;
    private boolean mFlagStop = false;
    private ValueAnimator mCandlesAnimator;```
命名還是挺規(guī)范的,應(yīng)該一看就知道是干嘛的兆沙。
我們還是來(lái)主要看繪制和屬性動(dòng)畫的配合欧芽,繪制就不看了(*光速打臉*)。來(lái)看動(dòng)畫葛圃。
mCandlesAnimator = ValueAnimator.ofFloat(0, 4).setDuration(4000);
mCandlesAnimator.addUpdateListener(
                 new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float zeroToOne = (float) animation.getAnimatedValue();
        if (zeroToOne <= 1.0f) {
            //蠟燭芯蓄力下拉
            mIsFire = true;
            mCandleWidth = mPreWidth + (int) (zeroToOne * 40);
            mCandleHeight = mPreHeight - (int) (zeroToOne * 30);
            mCandlewickDegrees = (int) (-60 + (180 + 60) * zeroToOne);
            refreshEyePosition();
        } else if (zeroToOne <= 2.0f) {
            zeroToOne = zeroToOne - 1.0f;
            //蠟燭芯上擺
            if (zeroToOne <= 0.2f) {
                zeroToOne = 1.0f - 5 * zeroToOne;
                mIsFire = false;
                mCandleWidth = mPreWidth + (int) (zeroToOne * 40);
                mCandleHeight = mPreHeight - (int) (zeroToOne * 30);
                mCandlewickDegrees = (int) (180 * zeroToOne);
            } else {
                if (mFlameStateListener != null && !mIsStateOnStart) {
                    mFlameStateListener.flameStart();
                    mIsStateOnStart = true;
                }
                mCandleWidth = mPreWidth;
                mCandleHeight = mPreHeight;
                mCandlewickDegrees = 0;
                if (mFlagStop) {
                    mCandlesAnimator.cancel();
                }
            }
            refreshEyePosition();
        } else if (zeroToOne >= 3.5f) {
            //蠟燭芯被吹歪
            zeroToOne = 2 * (zeroToOne - 3.5f);//0-1
            mCandlewickDegrees = (int) (-60 * zeroToOne);
            if (mFlameStateListener != null && !mIsStateOnEnd) {
                mFlameStateListener.flameEnd();
                mIsStateOnEnd = true;
            }
        }
    }
});```

這個(gè)就過(guò)程就有點(diǎn)多了千扔,但是其實(shí)一點(diǎn)都不復(fù)雜憎妙,,首先我們看動(dòng)畫里面的小<small><small>蠟燭,<big><big>一開(kāi)始曲楚,他來(lái)了一個(gè)變胖紅臉深蹲厘唾,所以呢mCandleWidth是變大的,mCandleHeight是變小的龙誊,后面那個(gè)燈芯隨著深蹲來(lái)了一個(gè)大角度旋轉(zhuǎn)抚垃,燈芯的如何旋轉(zhuǎn)大家也看到了,改變坐標(biāo)系然后就可以了载迄。用到了
canvas.rotate(mCandlewickDegrees, mCenterX, mCurY - mCandleHeight);這個(gè)方法讯柔。上擺過(guò)程也是一樣的,就不多說(shuō)了护昧。refreshEyePosition();這個(gè)方法是改變眼睛位置的魂迄,兩個(gè)地方都用到了所以稍微獨(dú)立出來(lái)了。注意mIsFire這個(gè)變量惋耙,沒(méi)有火焰的時(shí)候就做其他繪制捣炬,比如說(shuō)紅眼睛等等。好了好了绽榛,介紹到這湿酸,小蠟燭的部分就結(jié)束了。

  • SecCandle
    大<big><big>蠟燭灭美,<small><small>帥蠟燭鎮(zhèn)樓推溃,實(shí)際的繪制和小蠟燭的就差不多了,這里就不解釋了届腐。


    bigc.png
共同繪制View和控制器
  • AnimControler
    這個(gè)類的功能很簡(jiǎn)單铁坎,繪制地板部分還有就是把計(jì)算后傳過(guò)來(lái)的高度寬度賦給兩支蠟燭,然后控制兩支蠟燭各自開(kāi)始動(dòng)畫犁苏。
    mFirCandle = new FirCandle(mRelativeX + mWidth / 6, mRelativeY + mHeight);
    mFirCandle.initCandle(mFirCandleWidth, mFirCandleHeight);
    mFirCandle.initAnim();
    mSecCandle = new SecCandle(mRelativeX + mWidth / 2, mRelativeY + mHeight);
    mSecCandle.initCandle(mSecCandleWidth, mSecCandleHeight - 80);
    mSecCandle.initAnim();
    最后的最后硬萍,就是我們的View了
  • CandlesAnimView
        //16ms刷新Canvas
        mInvalidateAnimator = ValueAnimator.ofInt(0, 1).setDuration(16);
        mInvalidateAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mInvalidateAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationRepeat(Animator animation) {
                invalidate();
            }
        });
        mInvalidateAnimator.start();```
這個(gè)屬性動(dòng)畫履行的任務(wù)就是快速的刷新界面,是Candle的動(dòng)畫能夠及時(shí)顯示围详。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = measureDimension(WIDTH_DEFAULT * mDensity, 
                               widthMeasureSpec);
    int height = measureDimension(HEIGHT_DEFAULT *mDensity,
                               heightMeasureSpec);
    setMeasuredDimension(width, height);
}

public int measureDimension(int defaultSize, int measureSpec) {
    int result;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        result = defaultSize;
        if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
    }
    return result;
}

@Override
protected void onDraw(Canvas canvas) {
    if (!mIsInit) {
        initConfig();
        mIsInit = true;
    }
    mAnimControler.drawMyView(canvas);
}```

可以看到最后在view里面調(diào)用了我們的控制器朴乖,把cavas傳過(guò)去了。
最后的tip:大家有沒(méi)有發(fā)現(xiàn)每個(gè)動(dòng)畫的duration都是一樣的助赞。

三买羞、最后

<big>好了至此,本來(lái)一個(gè)簡(jiǎn)單的view自定義被我說(shuō)了這么多雹食。初次在簡(jiǎn)書上寫哩都,望大家多支持支持。
希望大家有什么建議和意見(jiàn)都可以提出婉徘。望斧正漠嵌。
期待你們的關(guān)注,一起交流android
GITHUB源碼下載
歡迎大家來(lái)我的博客逛逛,之前也沒(méi)什么時(shí)間寫博客文章的盖呼,最近開(kāi)始儒鹿,大家多多支持!<肝睢约炎!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蟹瘾,隨后出現(xiàn)的幾起案子圾浅,更是在濱河造成了極大的恐慌,老刑警劉巖憾朴,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狸捕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡众雷,警方通過(guò)查閱死者的電腦和手機(jī)灸拍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)砾省,“玉大人鸡岗,你說(shuō)我怎么就攤上這事”嘈郑” “怎么了轩性?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)狠鸳。 經(jīng)常有香客問(wèn)我揣苏,道長(zhǎng),這世上最難降的妖魔是什么碰煌? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任舒岸,我火速辦了婚禮,結(jié)果婚禮上芦圾,老公的妹妹穿的比我還像新娘蛾派。我一直安慰自己,他們只是感情好个少,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布洪乍。 她就那樣靜靜地躺著,像睡著了一般夜焦。 火紅的嫁衣襯著肌膚如雪壳澳。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天茫经,我揣著相機(jī)與錄音巷波,去河邊找鬼萎津。 笑死,一個(gè)胖子當(dāng)著我的面吹牛抹镊,可吹牛的內(nèi)容都是我干的锉屈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼垮耳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼颈渊!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起终佛,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤俊嗽,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后铃彰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绍豁,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年豌研,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妹田。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鹃共,死狀恐怖鬼佣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情霜浴,我是刑警寧澤晶衷,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站阴孟,受9級(jí)特大地震影響晌纫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜永丝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一锹漱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧慕嚷,春花似錦哥牍、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至挠说,卻和暖如春澡谭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背损俭。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工蛙奖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留潘酗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓外永,卻偏偏與公主長(zhǎng)得像崎脉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子伯顶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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