Android使用Transition來更改布局

前面講了屬性動(dòng)畫。這篇博客將會(huì)給大家分享一下如何使用Transition來進(jìn)行布局的更改犬第。當(dāng)然Transition也是基于屬性動(dòng)畫的。

Transition的特點(diǎn)

當(dāng)布局更改后通過Transition可以實(shí)現(xiàn)布局的過渡動(dòng)畫仓洼。

它有如下的特點(diǎn):

  • Group-level animations:可以對一個(gè)View層級(jí)下的所有View應(yīng)用一個(gè)或多個(gè)動(dòng)畫效果
  • Built-in animations: 可以應(yīng)用提前定義好的動(dòng)畫
  • Resource file support: 可以從xml中加載內(nèi)置的動(dòng)畫
  • Lifecycle callbacks: 可以接收回調(diào)實(shí)現(xiàn)動(dòng)畫生命周期的控制

使用Transition步驟

這里直接拿官方的來進(jìn)行說明:

transition

通過這張圖可以看到宦言,整個(gè)過程由Transition Manager通過Transition將Starting Scene轉(zhuǎn)換為Ending Scene。

因此换可,這里有三部進(jìn)行Transition的使用:

  • 為Starting layout椎椰、Ending layout創(chuàng)建Scene
  • 創(chuàng)建定義好你想要的動(dòng)畫效果的Transition
  • 調(diào)用TransitionManager.go()進(jìn)行l(wèi)ayout的切換

代碼準(zhǔn)備

創(chuàng)建TransitionActivity:

class TransitionActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_transition)
        if (savedInstanceState == null) {
            val translation = supportFragmentManager.beginTransaction()
            translation.replace(R.id.container, TransitionFragment())
            translation.commit()
        }
    }
}

這個(gè)Activity很簡單,xml就是一個(gè)無子View的名為container的FramLayout沾鳄。這里就不列出來了慨飘。

然后是TransitionFragment的xml:

<?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:orientation="vertical">

    <RadioGroup
        android:id="@+id/rg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            style="?android:textAppearanceMedium"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="scene" />

        <RadioButton
            android:id="@+id/rb_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:checked="true"
            android:text="1" />

        <RadioButton
            android:id="@+id/rb_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="2" />

        <RadioButton
            android:id="@+id/rb_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="3" />

        <RadioButton
            android:id="@+id/rb_4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="4" />

    </RadioGroup>

    <FrameLayout
        android:id="@+id/scene_root"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <include layout="@layout/scene1" />

    </FrameLayout>

</LinearLayout>

這里上面RaidoGroup是用來進(jìn)行各個(gè)Scene的轉(zhuǎn)換的。

下面的FramLayout是各個(gè)變換的布局的父布局译荞,它的子View將會(huì)做Transition中定義的動(dòng)畫變換瓤的。這里在FrameLayout通過inclue來引入了scene1布局。

TransitionFragment的代碼在Scene再進(jìn)行說明吞歼。

Scene的創(chuàng)建

首先圈膏,先創(chuàng)建三個(gè)scene的xml如下:

scene1.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/accent_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/primary_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/accent_view" />

    <View
        android:id="@+id/dark_primary_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimaryDark"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/primary_view" />

</androidx.constraintlayout.widget.ConstraintLayout>

scene2.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/accent_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/primary_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent" />

    <View
        android:id="@+id/dark_primary_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimaryDark"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

scene3.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/accent_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/primary_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent" />

    <View
        android:id="@+id/dark_primary_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorPrimaryDark"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/transition_title"
        style="?android:textAppearanceMedium"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello This Transition"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

前面說明了TransitionFragment的xml,這里接著說明對應(yīng)的代碼:

class TransitionFragment : Fragment(), RadioGroup.OnCheckedChangeListener {

    private lateinit var mScene1: Scene
    private lateinit var mScene2: Scene
    private lateinit var mScene3: Scene
    private lateinit var mTransitionManagerForScene3: TransitionManager


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_transition, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        //從ViewGroup對象中獲取Scene
        mScene1 = Scene(scene_root, container).apply {
            setEnterAction {
                Toast.makeText(activity, "enter action", Toast.LENGTH_LONG).show()
            }
            setExitAction {
                Toast.makeText(activity, "exit action", Toast.LENGTH_LONG).show()
            }
        }
        //從layout中獲取Scene
        activity?.let {
            mScene2 = Scene.getSceneForLayout(scene_root, R.layout.scene2, it)
            mScene3 = Scene.getSceneForLayout(scene_root, R.layout.scene3, it)
            //獲取xml中的Transition
            mTransitionManagerForScene3 = TransitionInflater.from(it).inflateTransitionManager(R.transition.scene3_transition_manager, scene_root)
        }
        //給RaidoGroup設(shè)置監(jiān)聽器
        view.findViewById<RadioGroup>(R.id.rg).setOnCheckedChangeListener(this)
    }


    override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
        when (checkedId) {
            R.id.rb_1 -> {
                TransitionManager.go(mScene1)
            }
            R.id.rb_2 -> {
                TransitionManager.go(mScene2)
            }
            R.id.rb_3 -> {
                mTransitionManagerForScene3.transitionTo(mScene3)
            }
            R.id.rb_4 -> {
                TransitionManager.beginDelayedTransition(scene_root)
                val accentView = accent_view
                val params = accentView.layoutParams
                params.width = resources.getDimensionPixelSize(R.dimen.red_view_new_size)
                params.height = params.width
                accentView.layoutParams = params
            }
        }
    }
}

從上面的代碼可以看到這里有兩種方式獲取Scene:

然后從Transition和TransitionManager相關(guān)的內(nèi)容在稍后進(jìn)行講解稽坤。

最后桥帆,就是給RadioGroup設(shè)置監(jiān)聽器了。

Transition的使用

在上面的TransitionFragment中看到關(guān)于Transition和TransitionManager將在這里給大家詳細(xì)的介紹了慎皱。

  • Transition就是在不同Scene或者是同一個(gè)Scene的布局改變實(shí)現(xiàn)動(dòng)畫過渡效果的類老虫。

  • 你可以使用內(nèi)置的一些Transition類,比如:AutoTransition茫多、Fade祈匙、ChangeBounds等,更多的就請查看官方文檔了天揖。下面對一些常用的內(nèi)置Transition類進(jìn)行一下介紹:

    • ChangeBounds: 當(dāng)不同的Scene的View的位置或者大小發(fā)生變化后夺欲,ChangeBounds可以對它們進(jìn)行動(dòng)畫。
    • Fade: 這個(gè)Transition繼承自Visibility類今膊,F(xiàn)ade對那些出現(xiàn)些阅、消失的View進(jìn)行動(dòng)畫操作。
    • AutoTransition: 這是一個(gè)默認(rèn)使用的Transition斑唬。它是一個(gè)TransitionSet市埋。它以Fade out、ChangeBounds恕刘、Fade in為順序進(jìn)行Transition動(dòng)畫操作
  • 你還可以進(jìn)行自定義Transition缤谎。

Transition的定義和Scene的獲取是一樣的,可以通過xml或者代碼來進(jìn)行定義

在xml中定義Transition

首先褐着,創(chuàng)建res/transition/目錄

然后坷澡,新建transition xml文件到這個(gè)目錄下

最后,在xml文件添加transition

changbounds_fadein_together.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeBounds />
    <fade android:fadingMode="fade_in">
        <targets>
            <target android:targetId="@id/transition_title" />
        </targets>
    </fade>
</transitionSet>

transitionSet和前面講的animatorSet是一樣的可以包含多個(gè)Transition含蓉。

在Fade Transition中可以看到設(shè)置了target频敛,target是用來指定Transition在某個(gè)對象上執(zhí)行的

在代碼中獲取Transition:

val transition = TransitionInflater.from(this).
inflateTransition(R.transition.changbounds_fadein_together)

在代碼中進(jìn)行定義

下面是上面xml中定義的Transition在代碼中對應(yīng)的例子:

val changeBounds = ChangeBounds()
val fade = Fade(Fade.IN).apply {
    addTarget(R.id.transition_title)
}
val transitionSet = TransitionSet().apply {
    addTransition(changeBounds)
    addTransition(fade)
}

TransitionManager的使用

在上面定義好了Transition,下面就該通過TransitionManager來使用Transition了馅扣。TransitionManager仍然定義在xml和代碼中斟赚。

xml中進(jìn)行定義

scene3_transition_manager.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionManager xmlns:android="http://schemas.android.com/apk/res/android">
    <transition
        android:toScene="@layout/scene3"
        android:transition="@transition/changebounds_fadein_together" />
</transitionManager>

其中toScene表示所有Scene轉(zhuǎn)換到當(dāng)前toScene時(shí)使用changebounds_fadein_together Transition。

如果加上fromScene岂嗓,就表示從fromScene到toScene是使用changebounds_fadein_together Transition汁展。從其它的Scene跳到toScene的時(shí)候使用默認(rèn)的AutoTransition

然后通過下面的代碼獲取xml中定義的TransitionManager:

mTransitionManagerForScene3 = TransitionInflater.from(activity).
inflateTransitionManager(R.transition.scene3_transition_manager, scene_root)

代碼中定義TransitionManager

val transitionManager = TransitionManager()
transitionManager.setTransition(mScene3, changebounds_fadein_together)

使用TransitionManager進(jìn)行Scene的轉(zhuǎn)換

現(xiàn)在又回到TransitionFragment的代碼中去:

看到為RaidoGroup設(shè)置監(jiān)聽器的代碼中去。

如果你不是在xml中進(jìn)行TransitionManager的定義厌殉,那么就沒有必要實(shí)例化一個(gè)TransitionManager出來食绿。直接使用TransitionManager的go靜態(tài)方法就行。你可以不傳Transition進(jìn)去然后使用默認(rèn)AutoTransition公罕∑鹘簦或者傳入自己定義Transition。其中楼眷,rb_1铲汪、rb_2就是使用的go靜態(tài)方法熊尉。

如果你在xml中定義了TransitionManager,那么你可以想rb_3獲取TransitionManager進(jìn)行Transition動(dòng)畫過渡

rb_4中掌腰,這是不通過Scene使用Transition的情況狰住。

使用TransitionManager的beginDelayedTransition靜態(tài)方法〕萘海可以不使用Scene催植。然后在后面通過代碼對當(dāng)前布局進(jìn)行修改。對于兩個(gè)相差無幾的布局就可以不同花大力氣去定義兩個(gè)布局來通過Scene來實(shí)現(xiàn)了勺择。直接通過這樣的方式來進(jìn)行Transition的使用创南。

自定義Transition

通過繼承自Transition可以自定義Transition。

自定義Transition主要有三個(gè)方法要進(jìn)行重寫:captureStartValues省核、captureEndValues稿辙、createAnimator。

captureStartValues

這個(gè)方法用來捕獲starting Scene中所有View中我們想要捕獲的屬性气忠。這些屬性值將以鍵值對存儲(chǔ)在TransitionValues中

captureEndValues

這個(gè)方法是用來捕獲ending Scene中所有View中我們想要捕獲的屬性邻储。這些屬性值將以鍵值對存儲(chǔ)在TransitionValues中

createAnimator

當(dāng)starting Scene中的TransitionValues中的屬性值與ending Scene中TransitionValues的屬性值發(fā)生變化的時(shí)候,才會(huì)調(diào)用這個(gè)方法笔刹。在這個(gè)方法中就是定義自己的過渡動(dòng)畫了芥备。

TransitionValues

這是一個(gè)用來為一個(gè)View保存其捕獲的值冬耿、作用于它上面的Transition的數(shù)據(jù)結(jié)構(gòu)舌菜。

它里面有三個(gè)主要的屬性:

  • view:用來保存這是哪個(gè)View的TransitionValues
  • values:一個(gè)HashMap用來存儲(chǔ)捕獲的屬性值。其中鍵通常是以package_name:transition_name:property_name這樣的方式進(jìn)行命名的亦镶。比如:com.anriku.jetpackdemo.animation:custom_transition:scale_x日月。
  • mTargetedTransitions:這個(gè)屬性是用來保存作用在當(dāng)前View上的Transition的。

現(xiàn)在通過一個(gè)例子再在進(jìn)行另外的一些內(nèi)容的介紹:

@RequiresApi(Build.VERSION_CODES.KITKAT)
class CustomTransition : Transition {

    //在代碼中實(shí)例化需要的構(gòu)造器
    constructor() : super()
    //在xml中定義需要的構(gòu)造器
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)

    companion object {
        private const val PROPNAME_SCALE_X = 
        "com.anriku.jetpackdemo.animation:custom_transition:scale_x"
        private const val PROPNAME_SCALE_Y = 
        "com.anriku.jetpackdemo.animation:custom_transition:scale_y"
    }


    override fun captureStartValues(transitionValues: 
                                    androidx.transition.TransitionValues) {
        captureValues(transitionValues)
    }

    override fun captureEndValues(transitionValues: androidx.transition.TransitionValues) 
    {
        captureValues(transitionValues)
    }

    private fun captureValues(transitionValues: TransitionValues) {
        val view = transitionValues.view
        transitionValues.values[PROPNAME_SCALE_X] = view.width
        transitionValues.values[PROPNAME_SCALE_Y] = view.height
    }

    override fun createAnimator(sceneRoot: ViewGroup, startValues: TransitionValues?, 
                                endValues: TransitionValues?): Animator? {
        startValues ?: return null
        endValues ?: return null

        val x = (startValues.values[PROPNAME_SCALE_X] as Int).toFloat() / 
        endValues.values[PROPNAME_SCALE_X] as Int
        val y = (startValues.values[PROPNAME_SCALE_Y] as Int).toFloat() / 
        endValues.values[PROPNAME_SCALE_Y] as Int

        val animSet = AnimatorSet()
        //Object為endValues中的view缤骨,因?yàn)檫@是將要顯示的View爱咬,就對它進(jìn)行動(dòng)畫操作
        val scaleXAnim = ObjectAnimator.ofFloat(endValues.view, "scaleX", x, 1f)
        val scaleYAnim = ObjectAnimator.ofFloat(endValues.view, "scaleY", y, 1f)

        return animSet.apply {
            duration = 1000
            play(scaleXAnim).with(scaleYAnim)
        }
    }
}

先看到構(gòu)造器:

在代碼中進(jìn)行實(shí)例化需要無參的構(gòu)造器。在xml中定義的時(shí)候需要另外一個(gè)帶有context绊起、attrs的構(gòu)造器精拟。這個(gè)其實(shí)和自定義View有點(diǎn)像。

然后在兩個(gè)captureXXX方法中進(jìn)行了View的width虱歪、height屬性的捕獲蜂绎。

最后,進(jìn)行動(dòng)畫操作的代碼就不做詳細(xì)解釋了笋鄙。這就是講過的屬性動(dòng)畫來實(shí)現(xiàn)View的壓縮動(dòng)畫操作师枣。

自定義Transition的使用

在代碼中自定義Transition的使用和內(nèi)置的Transition是一樣的。

在xml中的使用稍有不同:

<transition class="com.anriku.jetpackdemo.animation.CustomTransition" />

這里使用transition標(biāo)簽萧落,然后在class屬性中設(shè)置自定義的Transition的類践美。

總結(jié)

在這篇博客中講解了的東西蠻清晰的洗贰。

主要是三個(gè)東西的使用:

  • Scene的創(chuàng)建使用
  • Transition的創(chuàng)建使用
  • TransitionManager的使用

參考

官方文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市陨倡,隨后出現(xiàn)的幾起案子敛滋,更是在濱河造成了極大的恐慌,老刑警劉巖兴革,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矛缨,死亡現(xiàn)場離奇詭異,居然都是意外死亡帖旨,警方通過查閱死者的電腦和手機(jī)箕昭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來解阅,“玉大人落竹,你說我怎么就攤上這事』醭” “怎么了述召?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蟹地。 經(jīng)常有香客問我积暖,道長,這世上最難降的妖魔是什么怪与? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任夺刑,我火速辦了婚禮,結(jié)果婚禮上分别,老公的妹妹穿的比我還像新娘遍愿。我一直安慰自己,他們只是感情好耘斩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布沼填。 她就那樣靜靜地躺著,像睡著了一般括授。 火紅的嫁衣襯著肌膚如雪坞笙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天荚虚,我揣著相機(jī)與錄音薛夜,去河邊找鬼。 笑死曲管,一個(gè)胖子當(dāng)著我的面吹牛却邓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播院水,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼腊徙,長吁一口氣:“原來是場噩夢啊……” “哼简十!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起撬腾,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤螟蝙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后民傻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胰默,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年漓踢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牵署。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喧半,死狀恐怖奴迅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挺据,我是刑警寧澤取具,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站扁耐,受9級(jí)特大地震影響暇检,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜婉称,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一块仆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧酿矢,春花似錦榨乎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铐姚。三九已至策肝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隐绵,已是汗流浹背之众。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留依许,地道東北人棺禾。 一個(gè)月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像峭跳,于是被迫代替她去往敵國和親膘婶。 傳聞我的和親對象是個(gè)殘疾皇子缺前,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

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

  • 1、常見結(jié)構(gòu)體的儲(chǔ)存 比較常見的結(jié)構(gòu)體:CGPoint 悬襟,CGSize衅码,CGRect。脊岳。逝段。。割捅。奶躯。我們?nèi)绾未娣诺綌?shù)組...
    Nest0912閱讀 4,207評論 0 1
  • 2016這一年對我來說是一個(gè)不一樣的一年,前半年還處在學(xué)生時(shí)代亿驾,后半年就轉(zhuǎn)變成職場人巫糙,這個(gè)階段心里的變化是最大的。...
    danielyu小于閱讀 284評論 0 0
  • 結(jié)婚后颊乘,每年的正月初五都是從婆家過完年返回的日子参淹,公公婆婆總是依依不舍的把我們送到村口,看著我們坐上車離開乏悄,我最怕...
    神仙的媽媽閱讀 572評論 7 5
  • 下輩子跟胡蘿卜組cp吧
    十三大象閱讀 384評論 5 6