Android動(dòng)畫——View動(dòng)畫

一.View動(dòng)畫的介紹

Android的動(dòng)畫分為兩種:View動(dòng)畫(幀動(dòng)畫也屬于View動(dòng)畫)漾岳,屬性動(dòng)畫墓卦。

View動(dòng)畫的作用對(duì)象是View十酣,它支持4種動(dòng)畫效果:平移動(dòng)畫灾杰,縮放動(dòng)畫,旋轉(zhuǎn)動(dòng)畫飘蚯,透明度動(dòng)畫馍迄。幀動(dòng)畫也屬于View動(dòng)畫,但幀動(dòng)畫的表現(xiàn)形式和上面的四種變換效果不太一樣局骤。

本文將介紹:

  • View動(dòng)畫的四種類型以及動(dòng)畫集合set
  • View動(dòng)畫的使用
  • View動(dòng)畫的監(jiān)聽
  • 自定義View動(dòng)畫
  • 幀動(dòng)畫
  • View動(dòng)畫的特殊使用場(chǎng)景

二.View動(dòng)畫的種類

View動(dòng)畫四種變換效果對(duì)應(yīng)著Animation的四個(gè)子類:

  • TranslateAnimation(平移動(dòng)畫,<translate>)
  • ScaleAnimation(縮放動(dòng)畫,<scale>)
  • RotateAnimation(旋轉(zhuǎn)動(dòng)畫,<rotate>)
  • AlphaAnimation(透明度動(dòng)畫<alpha>)攀圈。

這四種動(dòng)畫既可以通過XML來定義,也可以通過代碼來動(dòng)態(tài)創(chuàng)建峦甩。對(duì)于View動(dòng)畫來說赘来,建議采用XML來定義動(dòng)畫,因?yàn)閄ML格式的動(dòng)畫可讀性更好凯傲。

View動(dòng)畫的XML格式的文件路徑為:res/anim/**.xml犬辰。

三.View動(dòng)畫的四種類型的xml格式基本屬性

所有value值都為float類型。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:repeatMode="reverse"
    android:shareInterpolator="true">

    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="300"
        android:toYDelta="300" />

    <alpha
        android:fromAlpha="0.1" 
        android:toAlpha="1.0" />

    <scale
        android:fromXScale="1.0"
        android:fromYScale="0.5"
        android:pivotX="10"
        android:pivotY="10"
        android:toXScale="1.5"
        android:toYScale="1.5" />

    <rotate
        android:fromDegrees="0"
        android:pivotX="10"
        android:pivotY="10"
        android:toDegrees="180" />
</set>
1.動(dòng)畫集合set

對(duì)應(yīng)AnimationSet類,可以包含若干個(gè)動(dòng)畫冰单,并且它的內(nèi)部也是可以嵌套其他動(dòng)畫集合的

  • android:interpolator:表示動(dòng)畫集合所采用的插值器幌缝,插值器影響動(dòng)畫的速度,比如非勻速動(dòng)畫就需要通過插值器來控制動(dòng)畫的播放過程诫欠。該屬性可以不指定涵卵,默認(rèn)為@android:anim/accelerate_decelerate_interpolator浴栽,即加速減速插值器。
  • android:shareInterpolator:表示集合中的動(dòng)畫是否和集合共享同一個(gè)插值器轿偎。如果不指定插值器典鸡,那么子動(dòng)畫就需要單獨(dú)指定所需的插值器或者使用默認(rèn)值。
2.1 平移動(dòng)畫translate

對(duì)應(yīng)TranslateAnimation類贴硫,View在水平和豎直方向的平移

  • android:fromXDelt:表示x的起始值
  • android:fromYDelt:表示y的起始值
  • android:toXDelta:表示x的結(jié)束值
  • android:toYDelta:表示y的結(jié)束值
2.2透明度動(dòng)畫alpha

對(duì)應(yīng)AlphaAnimation類椿每,改變View的透明度

  • android:fromAlpha:表示透明度的起始值,比如0.1
  • android:toAlpha:表示透明度的結(jié)束值英遭,比如1
2.3縮放動(dòng)畫scale

對(duì)應(yīng)ScaleAnimation類,使View具有放大和縮小的動(dòng)畫效果

  • android:fromXScale:水平方向縮放的起始值
  • android:fromYScale:豎直方向縮放的起始值
  • android:pivotX:縮放的軸點(diǎn)x坐標(biāo)亦渗,會(huì)影響縮放的效果
  • android:pivotY:縮放的軸點(diǎn)y坐標(biāo)挖诸,會(huì)影響縮放的效果
  • android:toXScale:水平方向的結(jié)束值
  • android:toYScale:豎直方向的結(jié)束值
2.4旋轉(zhuǎn)動(dòng)畫rotate

對(duì)應(yīng)RotateAnimation類,使View具有旋轉(zhuǎn)的動(dòng)畫效果

  • android:fromDegrees:旋轉(zhuǎn)開始的角度
  • android:pivotX:旋轉(zhuǎn)的軸點(diǎn)x坐標(biāo)
  • android:pivotY:旋轉(zhuǎn)的軸點(diǎn)y坐標(biāo)
  • android:toDegrees:旋轉(zhuǎn)結(jié)束的角度
View動(dòng)畫還有一些常用的屬性:
  • android:duration:動(dòng)畫的持續(xù)時(shí)間法精;
  • android:fillAfter:動(dòng)畫結(jié)束以后View是否停留在結(jié)束位置多律,true表示View停留在結(jié)束位置,false則不停留搂蜓。

四.View 動(dòng)畫的使用

1.使用xml格式定義View動(dòng)畫
TextView tv = findViewById(R.id.tv);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.animation_tv);
tv.startAnimation(animation);
2.使用通過代碼創(chuàng)建的View 動(dòng)畫
/**這里寫一個(gè)透明度動(dòng)畫狼荞,其他類型動(dòng)畫寫法類似*/
AlphaAniamation alphaAnimation = new AlphaAnimation(0,1);//透明度由0到1
alphaAnimation.setDuration(300);//動(dòng)畫時(shí)間300ms
tv.startAnimation(alphaAnimation);

五.View 動(dòng)畫的監(jiān)聽

通過Animation的setAnimationListener給View動(dòng)畫添加過程監(jiān)聽。

    public static interface AnimationListener {
        void onAnimationStart(Animation animation);
        void onAnimationEnd(Animation animation);
        void onAnimationRepeat(Animation animation);
    }

六.自定義View 動(dòng)畫

自定義view動(dòng)畫既簡(jiǎn)單又復(fù)雜帮碰。簡(jiǎn)單是因?yàn)橹恍枥^承Animation這個(gè)抽象類相味,然后重寫initialize和applyTransformation方法就好了,在initialize方法中做一些初始化工作殉挽,在applyTransformation中進(jìn)行相應(yīng)的矩陣變換即可丰涉,里面經(jīng)常需要采用Camera來簡(jiǎn)化矩陣變換的過程。復(fù)雜是因?yàn)樽远xview動(dòng)畫的過程主要是矩陣變換的過程斯碌,需要有線性代數(shù)的功底一死。

我們就來個(gè)例子吧,谷歌 APIDemo 里的自定義3d動(dòng)畫Rotate3dAnimation傻唾。圍繞y軸旋轉(zhuǎn)并且同時(shí)沿著z軸平移從而實(shí)現(xiàn)類似于3d的效果投慈。先上效果圖,效果圖如下冠骄。

QQ圖片20200107153625.gif

代碼量很少伪煤,如下圖。

public class Rotate3dAnimation extends Animation {
    private final float mFromDegrees;
    private final float mToDegrees;
    private final float mCenterX;
    private final float mCenterY;
    private final float mDepthZ;
    private final boolean mReverse;
    private Camera mCamera;
    float scale = 1;    // <------- 像素密度

    /**
     * 創(chuàng)建一個(gè)繞y軸旋轉(zhuǎn)的3D動(dòng)畫效果猴抹,旋轉(zhuǎn)過程中具有深度調(diào)節(jié)带族,可以指定旋轉(zhuǎn)中心。
     * @param context     <------- 添加上下文,為獲取像素密度準(zhǔn)備
     * @param fromDegrees 起始時(shí)角度
     * @param toDegrees   結(jié)束時(shí)角度
     * @param centerX     旋轉(zhuǎn)中心x坐標(biāo)
     * @param centerY     旋轉(zhuǎn)中心y坐標(biāo)
     * @param depthZ      最遠(yuǎn)到達(dá)的z軸坐標(biāo)
     * @param reverse     true 表示由從0到depthZ蟀给,false相反
     */
    public Rotate3dAnimation(Context context, float fromDegrees, float toDegrees,
                             float centerX, float centerY, float depthZ, boolean reverse) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mCenterX = centerX;
        mCenterY = centerY;
        mDepthZ = depthZ;
        mReverse = reverse;

        // 獲取手機(jī)像素密度 (即dp與px的比例)
        scale = context.getResources().getDisplayMetrics().density;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float fromDegrees = mFromDegrees;
        float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Camera camera = mCamera;
        final Matrix matrix = t.getMatrix();
        camera.save();

        // 調(diào)節(jié)深度
        if (mReverse) {
            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
        } else {
            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
        }

        // 繞y軸旋轉(zhuǎn)
        camera.rotateY(degrees);

        camera.getMatrix(matrix);
        camera.restore();

        // 修正失真蝙砌,主要修改 MPERSP_0 和 MPERSP_1
        float[] mValues = new float[9];
        matrix.getValues(mValues);              //獲取數(shù)值
        mValues[6] = mValues[6]/scale;          //數(shù)值修正
        mValues[7] = mValues[7]/scale;          //數(shù)值修正
        matrix.setValues(mValues);              //重新賦值

        // 調(diào)節(jié)中心點(diǎn)
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }
}

使用:我這里是在fragment里寫的阳堕,布局文件這里沒貼出來,因?yàn)榫褪且粋€(gè)簡(jiǎn)單的ImageView择克。

        ImageView imageView = view.findViewById(R.id.iv);

        //括號(hào)內(nèi)參數(shù)分別為(上下文恬总,開始角度,結(jié)束角度肚邢,x軸中心點(diǎn)壹堰,y軸中心點(diǎn),深度骡湖,是否扭曲)
        final Rotate3dAnimation rotation = new Rotate3dAnimation(Objects.requireNonNull(getContext()),
                0, 360, 150, 75, 0f, true);

        rotation.setDuration(3000);                         //設(shè)置動(dòng)畫時(shí)長(zhǎng)
        rotation.setRepeatCount(5);                         //設(shè)置重復(fù)次數(shù)
        rotation.setFillAfter(true);                        //保持旋轉(zhuǎn)后效果
        rotation.setInterpolator(new LinearInterpolator());    //設(shè)置插值器
        imageView.startAnimation(rotation);

七.幀動(dòng)畫

幀動(dòng)畫也是屬于View動(dòng)畫贱纠。幀動(dòng)畫是順序播放一組預(yù)先定義好的圖片。系統(tǒng)提供了單獨(dú)一個(gè)類AnimationDrawable來使用幀動(dòng)畫响蕴。幀動(dòng)畫使用比較簡(jiǎn)單谆焊,通過XML來定義一個(gè)AnimationDrawable,其地址為:res/drawable/***.xml浦夷。

在drawable目錄下新建一個(gè)以根節(jié)點(diǎn)為animaion-list的xml文件辖试。一個(gè)item對(duì)應(yīng)一幀圖片。android:oneshot="true",只播放一次劈狐,android:oneshot="false"無限循環(huán)罐孝,如果不設(shè)置則值默認(rèn)為false無限循環(huán)。代碼如下圖所示肥缔。

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <item
        android:drawable="@drawable/img1"
        android:duration="500" />
    <item
        android:drawable="@drawable/img2"
        android:duration="500" />
    <item
        android:drawable="@drawable/img3"
        android:duration="500" />

</animation-list>

將上述的drawable作為View的背景并通過Draw able來播放動(dòng)畫即可莲兢。使用如下圖。

        View v = findViewById(R.id.iv);
        v.setBackgroundResource(R.drawable.animation_frame);
        AnimationDrawable animationDrawable = (AnimationDrawable) v.getBackground();
        animationDrawable.start();

幀動(dòng)畫使用簡(jiǎn)單辫继,但是注意圖片不要太大怒见,否則容易引起OOM。

八.View動(dòng)畫的特殊使用場(chǎng)景

View動(dòng)畫除了上面介紹的四種以外姑宽,還可以在一些特殊的場(chǎng)景下使用遣耍,比如:

  • 在ViewGroup中控制子元素的出場(chǎng)效果。
  • 在Activity中實(shí)現(xiàn)不同Activity之間的切換炮车。
1.ViewGroup中控制子元素的出場(chǎng)效果——LayoutAnimation

LayoutAnimaton作用于ViewGroup舵变,為View Group指定一個(gè)動(dòng)畫,這樣當(dāng)它的子元素出場(chǎng)時(shí)都會(huì)具有這種動(dòng)畫效果瘦穆。
LayoutAnimaton有四個(gè)屬性:animationOrder纪隙,animation,delay扛或,interpolator绵咱。

  • animationOrder:有三個(gè)選項(xiàng):normal,reverse,random。normal表示順序顯示(即排在前面的子元素先開始播放入場(chǎng)動(dòng)畫)熙兔,reverse表示逆向顯示(即排在后面的子元素先開始播放入場(chǎng)動(dòng)畫)悲伶,randow表示隨機(jī)播放入場(chǎng)動(dòng)畫艾恼。
  • animation:為子元素指定具體的入場(chǎng)動(dòng)畫。
  • delay:表示子元素開始動(dòng)畫的時(shí)間延遲麸锉。即delay=第一個(gè)子元素動(dòng)畫時(shí)間/第二個(gè)子元素動(dòng)畫時(shí)間钠绍。怎么理解呢,打個(gè)比方花沉,如果delay的值為0.5柳爽,那么第一個(gè)子元素動(dòng)畫執(zhí)行到一半的時(shí)候,第二個(gè)子元素動(dòng)畫開始碱屁;如果delay的值為1磷脯,那么第一個(gè)子元素動(dòng)畫執(zhí)行完后才開始緊接著執(zhí)行;
  • interpolator:插值器娩脾,控制動(dòng)畫變化的速率争拐,不寫則默認(rèn)為是加速減速插值器。

我們有個(gè)經(jīng)典的例子——RecycleView的item都以一定的動(dòng)畫的形式出現(xiàn)晦雨。我們先上效果圖。

QQ圖片20200107183900.gif

我們現(xiàn)在就開始寫RecycleView的item的動(dòng)畫啦隘冲,關(guān)鍵步驟和代碼如下:

1.在res/anim目錄中新建一個(gè)根節(jié)點(diǎn)為set的anim_recycle_view_item.xml文件闹瞧,這里將其作為子元素入場(chǎng)動(dòng)畫(每個(gè)Item的動(dòng)畫),代碼如下圖展辞。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="false"
    android:shareInterpolator="true">

    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />

    <translate
        android:fromXDelta="-500"
        android:toXDelta="0" />

</set>

2.在res/anim目錄中新建一個(gè)根節(jié)點(diǎn)為layoutAnimation 的anim_recycle_view.xml文件奥邮,在里面引用步驟1寫好的子元素動(dòng)畫即可。代碼如下圖罗珍。

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/anim_recycle_view_item"
    android:animationOrder="normal"
    android:delay="0.5">

</layoutAnimation>

3.給RecycleView添加layoutAnimation有2種方式洽腺,布局中添加或者java代碼添加。

  • 方式一:在布局文件中對(duì)RecycleView添加layoutAnimation屬性覆旱,引用步驟2寫好的layoutAnimation即可,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ebf2fa"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="match_parent"
        android:layoutAnimation="@anim/anim_recycle_view"
        android:layout_height="match_parent"
        android:padding="5dip" />


</LinearLayout>
  • 方式二:在java代碼中對(duì)RecycleView添加layoutAnimation屬性蘸朋,引用步驟2寫好的layoutAnimation即可,代碼如下:
        RecyclerView recyclerView=findViewById(R.id.recycleView);
        Animation animation= AnimationUtils.loadAnimation(this,R.anim.recycle_view);
        LayoutAnimationController controller=new LayoutAnimationController(animation);
        controller.setDelay(0.5f);
        controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
        recyclerView.setLayoutAnimation(controller);

4.其它代碼就是正常的RecycleView的使用了扣唱,比如java代碼和item的布局代碼這里就不貼啦∨号鳎現(xiàn)在運(yùn)行一下,就可以看見跟效果圖的一樣的動(dòng)畫啦噪沙。

2.Activity的切換效果

Activity是有默認(rèn)的切換效果炼彪,我們也可以自定義這個(gè)Activity的切換效果,主要用到overridePendingTransition(int enterAnim,int exitAnim)這個(gè)方法正歼,但是該方法必須寫在在startActivity(Intent intent)或者finish()之后才能生效辐马,不然動(dòng)畫效果將不起作用。

  • enterAnim——Activity被打開時(shí)局义,所需要的動(dòng)畫資源id喜爷。
  • exitAnim——Activity被暫停時(shí)所需要的動(dòng)畫資源id冗疮。

啟動(dòng)Activity時(shí)添加自定義的切換效果,代碼如下:

Intent intent = new Intent(this, DetailActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);

退出Activity時(shí)添加自定義的切換效果贞奋,代碼如下:

    @Override
    public void finish() {
        super.finish();
        overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
    }

小結(jié):Android View動(dòng)畫的所有知識(shí)都在這里了赌厅。這是看完《Android開發(fā)藝術(shù)探索》做的筆記與一些思考感悟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末轿塔,一起剝皮案震驚了整個(gè)濱河市特愿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌勾缭,老刑警劉巖揍障,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異俩由,居然都是意外死亡毒嫡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門幻梯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兜畸,“玉大人,你說我怎么就攤上這事碘梢∫б。” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵煞躬,是天一觀的道長(zhǎng)肛鹏。 經(jīng)常有香客問我,道長(zhǎng)恩沛,這世上最難降的妖魔是什么在扰? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮雷客,結(jié)果婚禮上芒珠,老公的妹妹穿的比我還像新娘。我一直安慰自己佛纫,他們只是感情好妓局,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著呈宇,像睡著了一般好爬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甥啄,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天存炮,我揣著相機(jī)與錄音,去河邊找鬼。 笑死穆桂,一個(gè)胖子當(dāng)著我的面吹牛宫盔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播享完,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼灼芭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了般又?” 一聲冷哼從身側(cè)響起彼绷,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茴迁,沒想到半個(gè)月后寄悯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡堕义,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年猜旬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倦卖。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洒擦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怕膛,到底是詐尸還是另有隱情秘遏,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布嘉竟,位于F島的核電站,受9級(jí)特大地震影響洋侨,放射性物質(zhì)發(fā)生泄漏舍扰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一希坚、第九天 我趴在偏房一處隱蔽的房頂上張望边苹。 院中可真熱鬧,春花似錦裁僧、人聲如沸个束。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茬底。三九已至,卻和暖如春获洲,著一層夾襖步出監(jiān)牢的瞬間阱表,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留最爬,地道東北人涉馁。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像爱致,于是被迫代替她去往敵國(guó)和親烤送。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355