Android 一步一步分析CoordinatorLayout.Behavior

在MD系列的前幾篇文章中漆诽,通過(guò)基礎(chǔ)知識(shí)和實(shí)戰(zhàn)案例配合講解的形式介紹了CoordinatorLayoutAppBarLayout盐股、Toolbar侄非、CollapsingToolbarLayout的使用睡扬,并實(shí)現(xiàn)了幾種MD風(fēng)格下比較炫酷的交互效果谬哀。學(xué)會(huì)怎么用之后,我們?cè)傧胂胝雷澹瑸槭裁此鼈冎g能夠產(chǎn)生這樣的交互行為呢姨涡?其實(shí)就是因?yàn)?code>CoordinatorLayout.Behavior的存在,這也是本文所要講述的內(nèi)容项秉。至此绣溜,Android Material Design系列的學(xué)習(xí)已進(jìn)行到第八篇,大家可以點(diǎn)擊以下鏈接查看之前的文章:

關(guān)于Behavior


官網(wǎng)對(duì)于CoordinatorLayout.Behavior的介紹已經(jīng)將它的作用說(shuō)明得很清楚了岁诉,就是用來(lái)協(xié)調(diào)CoordinatorLayout的Child Views之間的交互行為:

Interaction behavior plugin for child views of CoordinatorLayout.

A Behavior implements one or more interactions that a user can take on a child view. These interactions may include drags, swipes, flings, or any other gestures.

之前學(xué)習(xí)CoordinatorLayout的使用案例時(shí)锚沸,用的都是系統(tǒng)的特定控件,比如design包中的FloatingActionButton涕癣、AppBarLayout等哗蜈,而不是普通的控件,如ImageButton之類(lèi)的坠韩,就是因?yàn)閐esign包中的這些特定控件已經(jīng)被系統(tǒng)默認(rèn)定義了繼承自CoordinatorLayout.Behavior的各種Behavior距潘,比如FloatingActionButton.Behavior
AppBarLayout.Behavior。而像系統(tǒng)的ToolBar控件就沒(méi)有自己的Behavior只搁,所以只能將其擱置到AppBarLayout容器里才能產(chǎn)生相應(yīng)的交互效果音比。

看到這里就能清楚一點(diǎn)了,如果我們想實(shí)現(xiàn)控件之間任意的交互效果氢惋,完全可以通過(guò)自定義Behavior的方式達(dá)到洞翩。看到這里大家可能會(huì)有一個(gè)疑惑焰望,就是CoordinatorLayout如何獲取Child Views的Behavior的呢骚亿,為什么在布局中,有些滑動(dòng)型控件定義了app:layout_behavior屬性而系統(tǒng)類(lèi)似FloatingActionButton的控件則不需要明確定義該屬性呢熊赖?看完CoordinatorLayout.Behavior的構(gòu)造函數(shù)就明白了来屠。

        /**
         * Default constructor for instantiating Behaviors.
         */
        public Behavior() {
        }

        /**
         * Default constructor for inflating Behaviors from layout. The Behavior will have
         * the opportunity to parse specially defined layout parameters. These parameters will
         * appear on the child view tag.
         *
         * @param context
         * @param attrs
         */
        public Behavior(Context context, AttributeSet attrs) {
        }

CoordinatorLayout.Behavior有兩個(gè)構(gòu)造函數(shù),注意看第二個(gè)帶參數(shù)的構(gòu)造函數(shù)的注釋?zhuān)锩嫣岬秸痧模谶@個(gè)構(gòu)造函數(shù)中的妖,Behavior會(huì)解析控件的特殊布局屬性,也就是通過(guò)parseBehavior方法獲取對(duì)應(yīng)的Behavior足陨,從而協(xié)調(diào)Child Views之間的交互行為,可以在CoordinatorLayout類(lèi)中查看娇未,具體源碼如下:

    static Behavior parseBehavior(Context context, AttributeSet attrs, String name) {
        if (TextUtils.isEmpty(name)) {
            return null;
        }

        final String fullName;
        if (name.startsWith(".")) {
            // Relative to the app package. Prepend the app package name.
            fullName = context.getPackageName() + name;
        } else if (name.indexOf('.') >= 0) {
            // Fully qualified package name.
            fullName = name;
        } else {
            // Assume stock behavior in this package (if we have one)
            fullName = !TextUtils.isEmpty(WIDGET_PACKAGE_NAME)
                    ? (WIDGET_PACKAGE_NAME + '.' + name)
                    : name;
        }

        try {
            Map<String, Constructor<Behavior>> constructors = sConstructors.get();
            if (constructors == null) {
                constructors = new HashMap<>();
                sConstructors.set(constructors);
            }
            Constructor<Behavior> c = constructors.get(fullName);
            if (c == null) {
                final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true,
                        context.getClassLoader());
                c = clazz.getConstructor(CONSTRUCTOR_PARAMS);
                c.setAccessible(true);
                constructors.put(fullName, c);
            }
            return c.newInstance(context, attrs);
        } catch (Exception e) {
            throw new RuntimeException("Could not inflate Behavior subclass " + fullName, e);
        }
    }

parseBehavior方法告訴我們墨缘,給Child Views設(shè)置Behavior有兩種方式:

  1. app:layout_behavior布局屬性
    在布局中設(shè)置,值為自定義Behavior類(lèi)的名字字符串(包含路徑),類(lèi)似在AndroidManifest.xml中定義四大組件的名字一樣镊讼,有兩種寫(xiě)法宽涌,包含包名的全路徑和以"."開(kāi)頭的省略項(xiàng)目包名的路徑。

  2. @CoordinatorLayout.DefaultBehavior類(lèi)注解
    在需要使用Behavior的控件源碼定義中添加該注解蝶棋,然后通過(guò)反射機(jī)制獲取卸亮。這個(gè)方式就解決了我們前面產(chǎn)生的疑惑,系統(tǒng)的AppBarLayout玩裙、FloatingActionButton都采用了這種方式兼贸,所以無(wú)需在布局中重復(fù)設(shè)置。

看到這里吃溅,也告訴我們一點(diǎn)溶诞,在自定義Behavior時(shí),一定要重寫(xiě)第二個(gè)帶參數(shù)的構(gòu)造函數(shù)决侈,否則這個(gè)Behavior是不會(huì)起作用的螺垢。

根據(jù)CoordinatorLayout.Behavior提供的方法,這里將自定義Behavior分為兩類(lèi)來(lái)講解赖歌,一種是dependent機(jī)制枉圃,一種是nested機(jī)制,對(duì)應(yīng)著不同的使用場(chǎng)景庐冯。

dependent機(jī)制


這種機(jī)制描述的是兩個(gè)Child Views之間的綁定依賴(lài)關(guān)系孽亲,設(shè)置Behavior屬性的Child View跟隨依賴(lài)對(duì)象Dependency View的大小位置改變而發(fā)生變化,對(duì)應(yīng)需要實(shí)現(xiàn)的方法常見(jiàn)有兩個(gè):

        /**
         * Determine whether the supplied child view has another specific sibling view as a
         * layout dependency.
         *
         * <p>This method will be called at least once in response to a layout request. If it
         * returns true for a given child and dependency view pair, the parent CoordinatorLayout
         * will:</p>
         * <ol>
         *     <li>Always lay out this child after the dependent child is laid out, regardless
         *     of child order.</li>
         *     <li>Call {@link #onDependentViewChanged} when the dependency view's layout or
         *     position changes.</li>
         * </ol>
         *
         * @param parent the parent view of the given child
         * @param child the child view to test
         * @param dependency the proposed dependency of child
         * @return true if child's layout depends on the proposed dependency's layout,
         *         false otherwise
         *
         * @see #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)
         */
        public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
            return false;
        }

        /**
         * Respond to a change in a child's dependent view
         *
         * <p>This method is called whenever a dependent view changes in size or position outside
         * of the standard layout flow. A Behavior may use this method to appropriately update
         * the child view in response.</p>
         *
         * <p>A view's dependency is determined by
         * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or
         * if {@code child} has set another view as it's anchor.</p>
         *
         * <p>Note that if a Behavior changes the layout of a child via this method, it should
         * also be able to reconstruct the correct position in
         * {@link #onLayoutChild(CoordinatorLayout, android.view.View, int) onLayoutChild}.
         * <code>onDependentViewChanged</code> will not be called during normal layout since
         * the layout of each child view will always happen in dependency order.</p>
         *
         * <p>If the Behavior changes the child view's size or position, it should return true.
         * The default implementation returns false.</p>
         *
         * @param parent the parent view of the given child
         * @param child the child view to manipulate
         * @param dependency the dependent view that changed
         * @return true if the Behavior changed the child view's size or position, false otherwise
         */
        public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) {
            return false;
        }

具體含義在注釋中已經(jīng)很清楚了肄扎,layoutDependsOn()方法用于決定是否產(chǎn)生依賴(lài)行為墨林,onDependentViewChanged()方法在依賴(lài)的控件發(fā)生大小或者位置變化時(shí)產(chǎn)生回調(diào)。dependent機(jī)制最常見(jiàn)的案例就是FloatingActionButtonSnackBar的交互行為犯祠,效果如下:

Behavior-01

系統(tǒng)的FloatingActionButton已經(jīng)默認(rèn)定義了一個(gè)Behavior來(lái)協(xié)調(diào)交互旭等,如果不用系統(tǒng)的FAB控件,比如改用GitHub上的一個(gè)庫(kù)futuresimple/android-floating-action-button衡载,再通過(guò)自定義一個(gè)Behavior搔耕,也能很簡(jiǎn)單的實(shí)現(xiàn)與SnackBar的協(xié)調(diào)效果:

package com.yifeng.mdstudysamples;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by yifeng on 16/9/20.
 *
 */
public class DependentFABBehavior extends CoordinatorLayout.Behavior {

    public DependentFABBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 判斷依賴(lài)對(duì)象
     * @param parent
     * @param child
     * @param dependency
     * @return
     */
    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof Snackbar.SnackbarLayout;
    }

    /**
     * 當(dāng)依賴(lài)對(duì)象發(fā)生變化時(shí),產(chǎn)生回調(diào),自定義改變child view
     * @param parent
     * @param child
     * @param dependency
     * @return
     */
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
        child.setTranslationY(translationY);
        return true;
    }
}

很簡(jiǎn)單的一個(gè)自定義Behavior處理,然后再為對(duì)應(yīng)的Child View設(shè)置該屬性即可痰娱。由于這里我們用的是第三方庫(kù)弃榨,采用遠(yuǎn)程依賴(lài)的形式引入的,無(wú)法修改源碼鲸睛,所以不方便使用注解的方式為其設(shè)置Behavior,所以在布局中為其設(shè)置坡贺,并且使用了省略包名的方式:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

    </android.support.design.widget.AppBarLayout>

    <com.getbase.floatingactionbutton.FloatingActionButton
        xmlns:fab="http://schemas.android.com/apk/res-auto"
        android:id="@+id/fab_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/dp_16"
        android:layout_gravity="bottom|right"
        android:onClick="onClickFab"
        fab:fab_icon="@mipmap/ic_toolbar_add"
        fab:fab_colorNormal="?attr/colorPrimary"
        fab:fab_colorPressed="?attr/colorPrimaryDark"
        app:layout_behavior=".DependentFABBehavior"/>

</android.support.design.widget.CoordinatorLayout>

這樣官辈,采用dependent機(jī)制自定義Behavior箱舞,與使用系統(tǒng)FAB按鈕一樣,即可與SnackBar控件產(chǎn)生如上圖所示的協(xié)調(diào)交互效果拳亿。

比如我們?cè)倏匆幌逻@樣一個(gè)效果:

Behavior-03

列表上下滑動(dòng)式晴股,底部評(píng)論區(qū)域隨著頂部Toolbar的移動(dòng)而移動(dòng),這里我們就可以自定義一個(gè)Dependent機(jī)制的Behavior肺魁,設(shè)置給底部視圖电湘,讓其依賴(lài)于包裹ToolbarAppBarLayout控件:

package com.yifeng.mdstudysamples;

import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by yifeng on 16/9/23.
 *
 */

public class CustomExpandBehavior extends CoordinatorLayout.Behavior {

    public CustomExpandBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        int delta = dependency.getTop();
        child.setTranslationY(-delta);
        return true;
    }
}

布局內(nèi)容如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_56"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_56"
        android:layout_gravity="bottom"
        app:layout_behavior=".CustomExpandBehavior"
        android:padding="8dp"
        android:background="@color/blue">

        <Button
            android:id="@+id/btn_send"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="Send"
            android:layout_alignParentRight="true"
            android:background="@color/white"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_toLeftOf="@id/btn_send"
            android:layout_marginRight="4dp"
            android:padding="4dp"
            android:hint="Please input the comment"
            android:background="@color/white"/>

    </RelativeLayout>

</android.support.design.widget.CoordinatorLayout>

注意,這里將自定義的Behavior設(shè)置給了底部?jī)?nèi)容的外層容器RelativeLayout鹅经,即可實(shí)現(xiàn)上述效果寂呛。

Nested機(jī)制


Nested機(jī)制要求CoordinatorLayout包含了一個(gè)實(shí)現(xiàn)了NestedScrollingChild接口的滾動(dòng)視圖控件,比如v7包中的RecyclerView瞬雹,設(shè)置Behavior屬性的Child View會(huì)隨著這個(gè)控件的滾動(dòng)而發(fā)生變化昧谊,涉及到的方法有:

onStartNestedScroll(View child, View target, int nestedScrollAxes)

onNestedPreScroll(View target, int dx, int dy, int[] consumed)

onNestedPreFling(View target, float velocityX, float velocityY)

onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)

onNestedFling(View target, float velocityX, float velocityY, boolean consumed)

onStopNestedScroll(View target)

其中,onStartNestedScroll方法返回一個(gè)boolean類(lèi)型的值酗捌,只有返回true時(shí)才能讓自定義的Behavior接受滑動(dòng)事件呢诬。同樣的,舉例說(shuō)明一下胖缤。

通過(guò)查看系統(tǒng)FAB控件的源碼可以知道尚镰,系統(tǒng)FAB定義的Behavior能夠處理兩個(gè)交互,一個(gè)是與SnackBar的位置交互哪廓,效果如上面的圖示一樣狗唉,另一個(gè)就是與AppBarLayout的展示交互,都是使用的Dependent機(jī)制涡真,效果在之前的文章 -- Android CoordinatorLayout 實(shí)戰(zhàn)案例學(xué)習(xí)《二》 中可以查看分俯,也就是AppBarLayout 滾動(dòng)到一定程度時(shí),F(xiàn)AB控件的動(dòng)畫(huà)隱藏與展示哆料。下面我們使用Nested機(jī)制自定義一個(gè)Behavior缸剪,實(shí)現(xiàn)如下與列表協(xié)調(diào)交互的效果:

Behavior-02

為了能夠使用系統(tǒng)FAB控件提供的隱藏與顯示的動(dòng)畫(huà)效果,這里直接繼承了系統(tǒng)FAB控件的Behavior

package com.yifeng.mdstudysamples;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by yifeng on 16/8/23.
 *
 */
public class NestedFABBehavior extends FloatingActionButton.Behavior {

    public NestedFABBehavior(Context context, AttributeSet attrs) {
        super();
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
                super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target,
                        nestedScrollAxes);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
            //系統(tǒng)FAB控件提供的隱藏動(dòng)畫(huà)
            child.hide();
        } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
            //系統(tǒng)FAB控件提供的顯示動(dòng)畫(huà)
            child.show();
        }
    }
}

然后在布局中添加RecyclerView东亦,并為系統(tǒng)FAB控件設(shè)置自定義的Behavior杏节,內(nèi)容如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/dp_16"
        android:src="@mipmap/ic_toolbar_add"
        app:layout_anchor="@id/rv_content"
        app:layout_anchorGravity="bottom|right"
        app:backgroundTint="@color/fab_ripple"
        app:layout_behavior="com.yifeng.mdstudysamples.NestedFABBehavior"/>

</android.support.design.widget.CoordinatorLayout>

這樣,即可實(shí)現(xiàn)系統(tǒng)FAB控件與列表滑動(dòng)控件的交互效果典阵。

@string/appbar_scrolling_view_behavior


這是一個(gè)系統(tǒng)字符串奋渔,值為:

android.support.design.widget.AppBarLayout$ScrollingViewBehavior

CoordinatorLayout容器中,通常用在AppBarLayout視圖下面(不是里面)的內(nèi)容控件中壮啊,比如上面的RecyclerView嫉鲸,如果我們不給它添加這個(gè)BehaviorToolbar將覆蓋在列表上面歹啼,出現(xiàn)重疊部分充坑,如圖

behavior-removed

添加之后减江,RecyclerView將位于Toolbar下面,類(lèi)似在RelativeLayout中設(shè)置了below屬性捻爷,如圖:

beharior-added

示例源碼


我在GitHub上建立了一個(gè)Repository,用來(lái)存放整個(gè)Android Material Design系列控件的學(xué)習(xí)案例份企,會(huì)伴隨著文章逐漸更新完善也榄,歡迎大家補(bǔ)充交流,Star地址:

https://github.com/Mike-bel/MDStudySamples

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末司志,一起剝皮案震驚了整個(gè)濱河市甜紫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌骂远,老刑警劉巖囚霸,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異激才,居然都是意外死亡拓型,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)瘸恼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)劣挫,“玉大人,你說(shuō)我怎么就攤上這事东帅⊙构蹋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵靠闭,是天一觀的道長(zhǎng)帐我。 經(jīng)常有香客問(wèn)我,道長(zhǎng)愧膀,這世上最難降的妖魔是什么拦键? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮扇调,結(jié)果婚禮上矿咕,老公的妹妹穿的比我還像新娘。我一直安慰自己狼钮,他們只是感情好碳柱,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著熬芜,像睡著了一般莲镣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涎拉,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天瑞侮,我揣著相機(jī)與錄音的圆,去河邊找鬼。 笑死半火,一個(gè)胖子當(dāng)著我的面吹牛越妈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钮糖,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼梅掠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了店归?” 一聲冷哼從身側(cè)響起阎抒,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎消痛,沒(méi)想到半個(gè)月后且叁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秩伞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年逞带,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稠歉。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掰担,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怒炸,到底是詐尸還是另有隱情带饱,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布阅羹,位于F島的核電站勺疼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捏鱼。R本人自食惡果不足惜执庐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望导梆。 院中可真熱鬧轨淌,春花似錦、人聲如沸看尼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)藏斩。三九已至躏结,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狰域,已是汗流浹背媳拴。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工黄橘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屈溉。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓塞关,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親子巾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子描孟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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