完全理解Android TouchEvent事件分發(fā)機(jī)制(二)

此文接于上一篇完全理解Android TouchEvent事件分發(fā)機(jī)制(一)

可以看出來,事件一旦被某一層消費(fèi)掉伪货,其它層就不會(huì)再消費(fèi)了

到這里其實(shí)對事件分發(fā)的機(jī)制就有個(gè)大概了解,知道里面的原理是怎么回事。

下面就讓我們來去梳理一下這個(gè)事件分發(fā)所走的邏輯替蛉。

我們仔細(xì)思考一下盗似,為什么有的事件有UP有的沒有俺亮?

為什么Up和Down的順序不同呢?

為什么要按照這個(gè)順序執(zhí)行呢罩润?

這個(gè)例子主要是為了說明分發(fā)玖翅、攔截、消費(fèi)的流程

以例一為例割以,在每個(gè) View 都不攔截 down 事件的情況下金度,down 事件是這樣傳遞的

super.dispatchTouchEvent方法,上面我們介紹過严沥,

這個(gè)方法內(nèi)部實(shí)際上是調(diào)用的onTouchEvent方法

所以最后的輸出日志順序就是從父到子依次調(diào)用分發(fā)和攔截猜极,然后從子到父依次調(diào)用消費(fèi)。

例二也是同理消玄,區(qū)別在于

當(dāng)Father拿到事件的時(shí)候跟伏,選擇了攔截下來不再詢問其他,

但是Father也沒消費(fèi),直接又還回給了Grandpa翩瓜,

Grandpa同樣也沒有消費(fèi)這個(gè)事件受扳。

所以最終的順序就是,從Grandpa到Father再返回Grandpa就結(jié)束了兔跌,沒有經(jīng)過LogImageView勘高。

例三的情況就不太一樣了

  • 當(dāng)Grandpa->Father->LogImageView 傳遞到LogImageView時(shí),LogImageView不消費(fèi)又返回給了Father浮定,F(xiàn)ather在onTouchEvent消費(fèi)掉了事件相满。
  • 然后反饋給Father說事件已經(jīng)消費(fèi)。桦卒,就等于parent.dispatchTouchEvent返回true給上一級(jí)的Grandpa立美,
    Grandpa不會(huì)再調(diào)用grandpa.onTouchEvent方法。

從這里我們可以總結(jié)出來:

dispatchTouchEvent返回值的作用是用于標(biāo)志這個(gè)事件是否“消費(fèi)了”方灾,
無論是自己或者下面的子一級(jí)用掉了都算是消費(fèi)掉建蹄。

再如這個(gè)例子中,如果我們讓LogImageView消費(fèi)掉事件裕偿,

那么Father收到LogImageView的消息后洞慎,也會(huì)調(diào)用parent.dispatchTouchEvent返回true給Grandpa,

所以這個(gè)方法返回值的true是只要用掉就行嘿棘,無論自己還是下面某一級(jí)劲腿,

而非我把事件傳遞下去就是true了,下面沒人消費(fèi)最終其實(shí)還是返回false的鸟妙。

至此焦人,我們來總結(jié)一下這三個(gè)方法的大致作用:

  • dispatchTouchEvent方法內(nèi)容里處理的是分發(fā)過程挥吵。可以理解為從Grandpa->Father->LogImageView一層層分發(fā)的動(dòng)作
  • dispatchTouchEvent的返回值則代表是否將事件分發(fā)出去用掉了花椭,自己用或者給某一層子級(jí)用都算分發(fā)成功忽匈。比如Father消費(fèi)了事件,或者他發(fā)出去給的LogImageView消費(fèi)了事件矿辽,這兩種情況下B的dispatchTouchEvent都會(huì)返回true給Grandpa

  • onInterceptTouchEvent會(huì)在第一輪從父到子的時(shí)候在分發(fā)時(shí)調(diào)用丹允,以它去決定是否攔截掉此事件不再向下分發(fā)。如果攔截下來袋倔,就會(huì)調(diào)用自己的onTouchEvent處理雕蔽;如果不攔截,則繼續(xù)向下傳遞

  • onTouchEvent代表消費(fèi)掉事件奕污。方法內(nèi)容是具體的事件處理方法萎羔,如何處理點(diǎn)擊滑動(dòng)等。

  • onTouchEvent的返回值則代表對上級(jí)的反饋碳默,通知這個(gè)東西我用掉啦,然后他的父級(jí)就會(huì)讓分發(fā)方法也返回true

下面我們來解釋為什么例一缘眶、二中沒有Up嘱根,而例三中有

一個(gè)Action_DOWN,一個(gè)ACTION_UP巷懈,若干個(gè)ACTION_MOVE该抒,才構(gòu)成完整的事件。

前倆例子里為什么沒有Up呢顶燕,很好理解凑保,

因?yàn)樗麄兌紱]有消費(fèi)事件啊,所以他們只有DOWN事件涌攻,因此只有Down欧引,沒Up。

例三做類比恳谎,F(xiàn)ather消費(fèi)掉了這個(gè)事件

  • 流程依然是先從Grandpa開始分配
    (grandpa.dispatchTouchEvent)
    (grandpa.onInterceptTouchEvent 判斷是否攔截)

  • Grandpa還是沒攔下來,繼續(xù)分發(fā)事件(grandpa不攔截,然后調(diào)用child.dispatchTouchEvent)

  • 事件到了Father掉瞳,F(xiàn)ather進(jìn)行了消費(fèi)硕蛹。(parent沒有調(diào)用攔截方法)

  • Father調(diào)用onTouchEvent返回true消費(fèi)掉事件,完成了整個(gè)行為鸵膏。

【例四】
在Grandpa類的onInterceptTouchEvent中添加個(gè)判斷膊升,
如果動(dòng)作是UP就return true攔截掉,DOWN則不攔截和之前一樣

打印如下:

04-04 07:16:43.353 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: GrandPaViewGroup  dispatchTouchEvent  Event 0
04-04 07:16:43.355 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: GrandPaViewGroup  onInterceptTouchEvent  Event 0
04-04 07:16:43.355 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: FatherViewGroup  dispatchTouchEvent  Event 0
04-04 07:16:43.356 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: FatherViewGroup  onInterceptTouchEvent  Event 0
04-04 07:16:43.356 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: LogImageView  dispatchTouchEvent  Event 0
04-04 07:16:43.357 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: LogImageView  onTouchEvent  Event 0
04-04 07:16:43.357 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: FatherViewGroup  onTouchEvent  Event 0
04-04 07:16:43.392 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: GrandPaViewGroup  dispatchTouchEvent  Event 1
04-04 07:16:43.392 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: GrandPaViewGroup  onInterceptTouchEvent  Event 1
04-04 07:16:43.392 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: FatherViewGroup  dispatchTouchEvent  Event 3
04-04 07:16:43.392 2344-2344/com.shanlovana.rcimageview E/ShanCanCan: FatherViewGroup  onTouchEvent  Event 3

前面Down行為和例三一樣谭企,后面就不同了
UP流程變了廓译,然后多了個(gè)CANCEL的動(dòng)作
這里我們可以理解為

  • GrandPa調(diào)用dispatchTouchEvent分發(fā)UP事件

  • GrandPa調(diào)用onInterceptTouchEvent返回true评肆,攔截UP,DOWN事件則是正常的傳遞

  • FatherView調(diào)用dispatchTouchEvent分發(fā)CANCEL動(dòng)作

  • FatherView使用CANCEL動(dòng)作調(diào)用onTouchEvent方法责循,結(jié)束

大概也就了解的差不多了糟港,還剩一個(gè)TouchTarget目標(biāo)的概念,
為什么例三中Up和Down流程不同院仿?

回頭去看完整源碼:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

    boolean handled = false;
    if (onFilterTouchEventForSecurity(ev)) {
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // 1.每次起始動(dòng)作就重置之前的TouchTarget等參數(shù)
            cancelAndClearTouchTargets(ev);
            resetTouchState();
        }

        final boolean intercepted;
        if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
            // 2.如果是起始動(dòng)作才攔截秸抚,或者已經(jīng)有人消費(fèi)掉了事件,再去判斷攔截
            // 起始動(dòng)作是第一次向下分發(fā)的時(shí)候歹垫,每個(gè)view都可以決定是否攔截剥汤,然后進(jìn)一步判斷是否消費(fèi),很好理解
            // 如果有人消費(fèi)掉了事件排惨,那么也攔截~ 就像例四中的情況吭敢,也可以再次判斷是否攔截的
            final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
            if (!disallowIntercept) {
                // 3.這里可以設(shè)置一個(gè)disallowIntercept標(biāo)志,如果是true暮芭,就是誰收到事件后都不準(zhǔn)攔截B雇铡!辕宏!
                intercepted = onInterceptTouchEvent(ev);
                ev.setAction(action);
            } else {
                intercepted = false;
            }
        } else {
            intercepted = true;
        }

        TouchTarget newTouchTarget = null;
        boolean alreadyDispatchedToNewTouchTarget = false;
        if (!canceled && !intercepted) {
            // 4.如果未攔截畜晰,只有Down動(dòng)作才去子一級(jí)去找目標(biāo)對象~
            // 因?yàn)檎夷繕?biāo)這個(gè)操作只有Down中才會(huì)處理
            if (actionMasked == MotionEvent.ACTION_DOWN ) {
                final int childrenCount = mChildrenCount;
                if (newTouchTarget == null && childrenCount != 0) {
                    for (int i = childrenCount - 1; i >= 0; i--) {
                        newTouchTarget = getTouchTarget(child);
                        if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                            newTouchTarget = addTouchTarget(child, idBitsToAssign);
                            alreadyDispatchedToNewTouchTarget = true;
                            break;
                        }
                    }
                }
            }
        }

        if (mFirstTouchTarget == null) {
            // 5.把自己當(dāng)做目標(biāo),去判斷自己的onTouchEvent是否消費(fèi)
            handled = dispatchTransformedTouchEvent(ev, canceled, null,
                    TouchTarget.ALL_POINTER_IDS);
        } else {
            // 6.如果有人消費(fèi)掉了事件瑞筐,找出他~
            TouchTarget target = mFirstTouchTarget;
            while (target != null) {
                // 7.消費(fèi)對象信息其實(shí)是一個(gè)鏈?zhǔn)綄ο笃啾牵涊d著一個(gè)一個(gè)傳遞的人的信息,遍歷調(diào)用它c(diǎn)hild的分發(fā)方法
                final TouchTarget next = target.next;
                if (dispatchTransformedTouchEvent(ev, cancelChild,
                        target.child, target.pointerIdBits)) {
                    handled = true;
                }
                target = next;
            }
        }
    }

    return handled;
}

dispatchTransformedTouchEvent方法聚假,內(nèi)部簡化代碼為:

private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
        View child, int desiredPointerIdBits) {
    final boolean handled;

    if (child == null) {
        handled = super.dispatchTouchEvent(transformedEvent);
    } else {
        handled = child.dispatchTouchEvent(transformedEvent);
    }

    return handled;
}

就是判斷如果沒child了(是ViewGroup但是沒子控件块蚌,或者自己就是View),
如果沒child膘格,就調(diào)用View的dispatchTouchEvent方法峭范,
實(shí)質(zhì)就是調(diào)用onTouchEvent判斷是否消費(fèi)掉事件
如果有child,就調(diào)用child的dispatchTouchEvent將事件一層層向下分發(fā)

例三四中的復(fù)雜情況
其中關(guān)鍵主要在于多了一個(gè)TouchTarget的處理.

向下傳遞的核心主要是在于dispatchTransformedTouchEvent方法

第一輪動(dòng)作的Down時(shí)闯袒,只要不攔截虎敦,就會(huì)在注釋4代碼處遍歷所有child調(diào)用該方法層層傳遞下去

而后續(xù)其他動(dòng)作時(shí),就會(huì)進(jìn)入注釋6代碼條件政敢,然后遍歷TouchTarget中的信息用該方法層層分發(fā)

注意不要誤解:

第一次Down的時(shí)候會(huì)for循環(huán)所有child

第二輪Up的時(shí)候也會(huì)while(target.next)的迭代循環(huán)挨個(gè)判斷,但是next是遍歷同級(jí)其徙,不是子級(jí)

dispatchTrancformTouchEvent(target.child)這里的.child才是向子一級(jí)一層一層分發(fā)傳遞的地方.

這個(gè)TouchTarget對象,主要保存的是傳遞路線信息喷户,它是一個(gè)鏈?zhǔn)浇Y(jié)構(gòu)

不過這個(gè)路線不是Grandpa->Father->LogImageView的一個(gè)單子唾那,而是每個(gè)ViewGroup都會(huì)保存一個(gè)向下的路線信息.

Cancel部分

dispatchTrancformTouchEvent中會(huì)判斷,如果cancel=true動(dòng)作,
則會(huì)把動(dòng)作改成ACTION_CANCEL一層一層的傳下去.

注意:

onTouch和onTouchEvent有什么區(qū)別闹获,又該如何使用期犬?

從源碼中可以看出,這兩個(gè)方法都是在View的dispatchTouchEvent中調(diào)用的避诽,onTouch優(yōu)先于onTouchEvent執(zhí)行龟虎。如果在onTouch方法中通過返回true將事件消費(fèi)掉,onTouchEvent將不會(huì)再執(zhí)行沙庐。

另外需要注意的是鲤妥,onTouch能夠得到執(zhí)行需要兩個(gè)前提條件,第一mOnTouchListener的值不能為空拱雏,第二當(dāng)前點(diǎn)擊的控件必須是enable的棉安。因此如果你有一個(gè)控件是非enable的,那么給它注冊onTouch事件將永遠(yuǎn)得不到執(zhí)行铸抑。對于這一類控件贡耽,如果我們想要監(jiān)聽它的touch事件,就必須通過在該控件中重寫onTouchEvent方法來實(shí)現(xiàn)鹊汛。

到這里蒲赂,我們的事件傳遞就全部講解完成了,下面讓我們看看他的實(shí)際用途吧刁憋。

用途:

滑動(dòng)事件沖突的解決方法:

外部攔截法

外部攔截法是指在有點(diǎn)擊事件時(shí)都要經(jīng)過父容器凳宙,那么在父容器時(shí)如果需要攔截就攔截自己處理,不需要?jiǎng)t傳遞給下一層進(jìn)行處理职祷,

下面看個(gè)例子

首先定義一個(gè)水平滑動(dòng)的HorizontalScrollView,看主要代碼

主要的攔截是需要重寫onInterceptTouchEvent

此示例是借鑒于lylodlig的一篇文章届囚,在此感謝有梆。

@Override  
   public boolean onInterceptTouchEvent(MotionEvent ev) {  
       boolean intercepted = false;  
       int x = (int) ev.getX();  
       int y = (int) ev.getY();  
       switch (ev.getAction()) {  
           case MotionEvent.ACTION_DOWN:  
               //down事件不攔截,否則無法傳給子元素  
               intercepted = false;  
               if (!mScroller.isFinished()) {  
                   mScroller.abortAnimation();  
                   intercepted = true;  
               }  
               break;  
           case MotionEvent.ACTION_MOVE:  
               int deltaX = x - mLastXIntercept;  
               int deltaY = y - mLastYIntercept;  
               //水平滑動(dòng)則攔截  
               if (Math.abs(deltaX) > Math.abs(deltaY) + 5) {  
                   intercepted = true;  
               } else {  
                   intercepted = false;  
               }  
               break;  
           case MotionEvent.ACTION_UP:  
               //不攔截意系,否則子元素?zé)o法收到  
               intercepted = false;  
               break;  
       }  
       //因?yàn)楫?dāng)ViewGroup中的子View可能消耗了down事件泥耀,在onTouchEvent無法獲取,  
       // 無法對mLastX賦初值蛔添,所以在這里賦值一次  
       mLastX = x;  
       mLastY = y;  
       mLastYIntercept = y;  
       mLastXIntercept = x;  
       return intercepted;  
   }  

在down事件不需要攔截痰催,返回false,否則的話子view無法收到事件迎瞧,將全部會(huì)由父容器處理夸溶,這不是希望的;up事件也要返回false凶硅,否則最后子view收不到

看看move事件缝裁,當(dāng)水平滑動(dòng)距離大于豎直距離時(shí),代表水平滑動(dòng)足绅,返回true捷绑,由父類來進(jìn)行處理韩脑,否則交由子view處理。這里move事件就是主要的攔截條件判斷粹污,如果你遇到的不是水平和豎直的條件這么簡單段多,就可以在這里進(jìn)行改變,比如壮吩,ScrollView嵌套了ListView进苍,條件就變成,當(dāng)ListView滑動(dòng)到底部或頂部時(shí)粥航,返回true琅捏,交由父類滑動(dòng)處理,否則自身ListView滑動(dòng)递雀。

在onTouchEvent中主要是做的滑動(dòng)切換的處理

@Override  
    public boolean onTouchEvent(MotionEvent event) {  
        mVelocityTracker.addMovement(event);  
        int x = (int) event.getX();  
        int y = (int) event.getY();  
        switch (event.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                if (!mScroller.isFinished()) {  
                    mScroller.abortAnimation();  
                }  
                break;  
            case MotionEvent.ACTION_MOVE:  
                int deltaX = x - mLastX;  
                int deltaY = y - mLastY;  
                if (getScrollX() < 0) {  
                    scrollTo(0, 0);  
                }  
                scrollBy(-deltaX, 0);  
                break;  
            case MotionEvent.ACTION_UP:  
                int scrollX = getScrollX();  
                mVelocityTracker.computeCurrentVelocity(1000);  
                float xVelocityTracker = mVelocityTracker.getXVelocity();  
                if (Math.abs(xVelocityTracker) > 50) {//速度大于50則滑動(dòng)到下一個(gè)  
                    mChildIndex = xVelocityTracker > 0 ? mChildIndex - 1 : mChildIndex + 1;  
                } else {  
                    mChildIndex = (scrollX + mChildWith / 2) / mChildWith;  
                }  
                mChildIndex = Math.max(0, Math.min(mChildIndex, mChildrenSize - 1));  
                int dx = mChildIndex * mChildWith - scrollX;  
                smoothScrollBy(dx, 0);  
                mVelocityTracker.clear();  
                break;  
        }  
        mLastY = y;  
        mLastX = x;  
        return true;  
    }  

在這個(gè)嵌套一個(gè)普通的ListView柄延,這樣就可以解決水平和豎直滑動(dòng)沖突的問題了。

<com.shanlovana.rcimageview.HorizontalScrollViewEx  
        android:layout_width="match_parent"  
        android:layout_height="200dp">  
  
        <ListView  
            android:id="@+id/listView"  
            android:layout_width="match_parent"  
            android:layout_height="match_parent" />  
  
        <Button  
            android:layout_width="match_parent"  
            android:layout_height="match_parent"  
            android:background="@android:color/holo_blue_bright"  
            android:text="2" />  
  
        <Button  
            android:layout_width="match_parent"  
            android:layout_height="match_parent"  
            android:background="@android:color/holo_green_dark"  
            android:text="3" />  
    </com.shanlovana.rcimageview.HorizontalScrollView>  

內(nèi)部攔截法

內(nèi)部攔截法是父容器不攔截任何事件缀程,所有事件都傳遞給子view搜吧,如果需要就直接消耗掉,不需要再傳給父容器處理
下面重寫一個(gè)ListView杨凑,只需要重寫一個(gè)dispatchTouchEvent方法就OK

    @Override  
    public boolean dispatchTouchEvent(MotionEvent ev) {  
        int x = (int) ev.getX();  
        int y = (int) ev.getY();  
  
        switch (ev.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                //子View的所有父ViewGroup都會(huì)跳過onInterceptTouchEvent的回調(diào)  
                getParent().requestDisallowInterceptTouchEvent(true);  
                break;  
            case MotionEvent.ACTION_MOVE:  
                int deltaX = x - mLastX;  
                int deltaY = y - mLastY;  
                if (Math.abs(deltaX) > Math.abs(deltaY) + 5) {//水平滑動(dòng)滤奈,使得父類可以執(zhí)行onInterceptTouchEvent  
                    getParent().requestDisallowInterceptTouchEvent(false);  
                }  
                break;  
        }  
        mLastX = x;  
        mLastY = y;  
        return super.dispatchTouchEvent(ev);  
    }  

在down事件調(diào)用getParent().requestDisallowInterceptTouchEvent(true),這句代碼的意思是使這個(gè)view的父容器都會(huì)跳過onInterceptTouchEvent撩满,在move中判斷如果是水平滑動(dòng)就由父容器去處理蜒程,父容器只需要把之前的onInterceptTouchEvent改為下面那樣,其他不變.

@Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        int x = (int) ev.getX();  
        int y = (int) ev.getY();  
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {  
            mLastX = x;  
            mLastY = y;  
            if (!mScroller.isFinished()) {  
                mScroller.abortAnimation();  
                return true;  
            }  
            return false;  
        } else {  
            //如果是非down事件伺帘,說明子View并沒有攔截父類的onInterceptTouchEvent  
            //說明該事件交由父類處理昭躺,所以不需要再傳遞給子類,返回true  
            return true;  
        }  
    }  

解決這些問題的基本的思想就是這些伪嫁,希望可以幫助到您领炫。

Github源碼下載地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市张咳,隨后出現(xiàn)的幾起案子帝洪,更是在濱河造成了極大的恐慌,老刑警劉巖脚猾,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葱峡,死亡現(xiàn)場離奇詭異,居然都是意外死亡婚陪,警方通過查閱死者的電腦和手機(jī)族沃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人脆淹,你說我怎么就攤上這事常空。” “怎么了盖溺?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵漓糙,是天一觀的道長。 經(jīng)常有香客問我烘嘱,道長昆禽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任蝇庭,我火速辦了婚禮醉鳖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哮内。我一直安慰自己盗棵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布北发。 她就那樣靜靜地躺著纹因,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琳拨。 梳的紋絲不亂的頭發(fā)上瞭恰,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音狱庇,去河邊找鬼惊畏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛密任,可吹牛的內(nèi)容都是我干的陕截。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼批什,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了社搅?” 一聲冷哼從身側(cè)響起驻债,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎形葬,沒想到半個(gè)月后合呐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笙以,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年淌实,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拆祈,死狀恐怖恨闪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情放坏,我是刑警寧澤咙咽,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站淤年,受9級(jí)特大地震影響钧敞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜麸粮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一溉苛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧弄诲,春花似錦愚战、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至洛搀,卻和暖如春敢茁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背留美。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工彰檬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谎砾。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓逢倍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親景图。 傳聞我的和親對象是個(gè)殘疾皇子较雕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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