Android事件分發(fā)機(jī)制

最近因?yàn)閭€(gè)人原因需要準(zhǔn)備一些資料,所以就萌生了把應(yīng)用層所涉及的知識(shí)點(diǎn)做個(gè)基類曹洽,不僅僅是簡(jiǎn)單的知識(shí)結(jié)論鳍置,同時(shí)還希望能從源碼角度上做個(gè)積累,讓自己日后在學(xué)習(xí)中都能有時(shí)間拿出來(lái)翻翻送淆,可能每次花費(fèi)幾分鐘的時(shí)候都會(huì)有新的感悟税产,同時(shí)也是為了鍛煉自己的能力,畢竟不是做純移動(dòng)端的偷崩,技術(shù)還是挺薄弱的辟拷,而且之前去大公司面沒(méi)拿到啥好成績(jī)哈,自嘲一下<..>阐斜,希望大家共同加油吧衫冻。接下來(lái)記錄的是Android事件分發(fā)機(jī)制,其中有些圖片是借鑒別的同學(xué)谒出,大家多多包含哈隅俘。

  • 事件分發(fā)流程
  • 源碼解析
    -View分發(fā)
    -ViewGroup分發(fā)

事件分發(fā)流程

事件分發(fā)我們需要關(guān)注主要是三個(gè)方法dispatchTouchEvent、onInterceptTouchEvent笤喳、onTouchEvent为居。但是這三個(gè)方法對(duì)應(yīng)的返回值或執(zhí)行super方法都會(huì)導(dǎo)致最終事件分發(fā)的走向。

若都返回super方法杀狡,則事件分發(fā)的流程如下圖

image.png

整個(gè)事件流向應(yīng)該是從Activity---->ViewGroup--->View 從上往下調(diào)用dispatchTouchEvent方法蒙畴,一直到葉子節(jié)點(diǎn)(View)的時(shí)候,再由View--->ViewGroup--->Activity從下往上調(diào)用onTouchEvent方法呜象。

若dispatchTouchEvent和onTouchEvent返回true膳凝,則事件分發(fā)的流程如下圖

image.png

當(dāng)dispatchTouchEvent或onTouchEvent返回true碑隆,事件就會(huì)停止傳遞被消耗的。為什么會(huì)這樣呢蹬音,等下我們分析下代碼上煤。

若dispatchTouchEvent和onTouchEvent返回false,則事件分發(fā)的流程如下圖

image.png

關(guān)注下標(biāo)注藍(lán)線的部分祟绊,當(dāng)返回false時(shí),事件都會(huì)回傳給父控件的onTouchEvent處理哥捕,同樣這是為什么呢牧抽,我們也可以通過(guò)源碼來(lái)看看哈。

接下來(lái)總結(jié)一下遥赚。我們常見(jiàn)的使用場(chǎng)景如滑動(dòng)沖突控制扬舒,就需要改變?nèi)鏾nIterceptTouchEvent的返回值等。
ViewGroup和View 的dispatchTouchEvent 是做事件分發(fā)凫佛,那么這個(gè)事件可能分發(fā)出去的四個(gè)目標(biāo)

注:------> 后面代表事件目標(biāo)需要怎么做讲坎。
1、 自己消費(fèi)愧薛,終結(jié)傳遞晨炕。------->return true ;
2毫炉、 給自己的onTouchEvent處理-------> 調(diào)用super.dispatchTouchEvent()系統(tǒng)默認(rèn)會(huì)去調(diào)用 onInterceptTouchEvent瓮栗,在onInterceptTouchEvent return true就會(huì)去把事件分給自己的onTouchEvent處理。
3瞄勾、 傳給子View------>調(diào)用super.dispatchTouchEvent()默認(rèn)實(shí)現(xiàn)會(huì)去調(diào)用 onInterceptTouchEvent 在onInterceptTouchEvent return false费奸,就會(huì)把事件傳給子類。
4进陡、 不傳給子View愿阐,事件終止往下傳遞,事件開(kāi)始回溯趾疚,從父View的onTouchEvent開(kāi)始事件從下到上回歸執(zhí)行每個(gè)控件的onTouchEvent------->return false缨历;
注: 由于View沒(méi)有子View所以不需要onInterceptTouchEvent 來(lái)控件是否把事件傳遞給子View還是攔截,所以View的事件分發(fā)調(diào)用super.dispatchTouchEvent()的時(shí)候默認(rèn)把事件傳給自己的onTouchEvent處理(相當(dāng)于攔截)糙麦,對(duì)比ViewGroup的dispatchTouchEvent 事件分發(fā)戈二,View的事件分發(fā)沒(méi)有上面提到的4個(gè)目標(biāo)的第3點(diǎn)。

ViewGroup和View的onTouchEvent方法是做事件處理的喳资,那么這個(gè)事件只能有兩個(gè)處理方式:

1觉吭、自己消費(fèi)掉,事件終結(jié)仆邓,不再傳給誰(shuí)----->return true;
2鲜滩、繼續(xù)從下往上傳伴鳖,不消費(fèi)事件,讓父View也能收到到這個(gè)事件----->return false;View的默認(rèn)實(shí)現(xiàn)是不消費(fèi)的徙硅。所以super==false榜聂。

ViewGroup的onInterceptTouchEvent方法對(duì)于事件有兩種情況:

1、攔截下來(lái)嗓蘑,給自己的onTouchEvent處理--->return true;
2须肆、不攔截,把事件往下傳給子View---->return false,ViewGroup默認(rèn)是不攔截的桩皿,所以super==false豌汇;

關(guān)于ACTION_MOVE 和 ACTION_UP

上面講解的都是針對(duì)ACTION_DOWN的事件傳遞,ACTION_MOVE和ACTION_UP在傳遞的過(guò)程中并不是和ACTION_DOWN 一樣泄隔,你在執(zhí)行ACTION_DOWN的時(shí)候返回了false拒贱,后面一系列其它的action就不會(huì)再得到執(zhí)行了。簡(jiǎn)單的說(shuō)佛嬉,就是當(dāng)dispatchTouchEvent在進(jìn)行事件分發(fā)的時(shí)候逻澳,只有前一個(gè)事件(如ACTION_DOWN)返回true,才會(huì)收到ACTION_MOVE和ACTION_UP的事件暖呕。具體這句話很多博客都說(shuō)了斜做,但是具體含義是什么呢?我們來(lái)看一下下面的具體分析湾揽。

上面提到過(guò)了陨享,事件如果不被打斷的話是會(huì)不斷往下傳到葉子層(View),然后又不斷回傳到Activity钝腺,dispatchTouchEvent 和 onTouchEvent 可以通過(guò)return true 消費(fèi)事件抛姑,終結(jié)事件傳遞,而onInterceptTouchEvent 并不能消費(fèi)事件艳狐,它相當(dāng)于是一個(gè)分叉口起到分流導(dǎo)流的作用定硝,ACTION_MOVE和ACTION_UP 會(huì)在哪些函數(shù)被調(diào)用,之前說(shuō)了并不是哪個(gè)函數(shù)收到了ACTION_DOWN毫目,就會(huì)收到 ACTION_MOVE 等后續(xù)的事件的蔬啡。
下面通過(guò)幾張圖看看不同場(chǎng)景下,ACTION_MOVE事件和ACTION_UP事件的具體走向并總結(jié)一下規(guī)律镀虐。

1箱蟆、我們?cè)赩iewGroup1 的dispatchTouchEvent 方法返回true消費(fèi)這次事件
ACTION_DOWN 事件從(Activity的dispatchTouchEvent)--------> (ViewGroup1 的dispatchTouchEvent) 后結(jié)束傳遞,事件被消費(fèi)(如下圖紅色的箭頭代碼ACTION_DOWN 事件的流向)刮便。
下圖中紅色的箭頭代表ACTION_DOWN 事件的流向链方,藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

image.png

2柔吼、我們?cè)赩iewGroup2 的dispatchTouchEvent 返回true消費(fèi)這次事件

image.png

3剂陡、我們?cè)赩iew 的dispatchTouchEvent 返回true消費(fèi)這次事件
這個(gè)我不就畫(huà)圖了获黔,效果和在ViewGroup2 的dispatchTouchEvent return true的差不多淹仑,同樣的收到ACTION_DOWN 的dispatchTouchEvent函數(shù)都能收到 ACTION_MOVE和ACTION_UP。
所以我們就基本可以得出結(jié)論如果在某個(gè)控件的dispatchTouchEvent 返回true消費(fèi)終結(jié)事件,那么收到ACTION_DOWN 的函數(shù)也能收到 ACTION_MOVE和ACTION_UP。
4钝凶、我們?cè)赩iew 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

image.png

5、我們?cè)赩iewGroup 2 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

image.png

6唁影、我們?cè)赩iewGroup 1 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

image.png

7耕陷、我們?cè)贏ctivity 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

image.png

8、我們?cè)赩iew的dispatchTouchEvent 返回false并且Activity 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
image.png

9据沈、我們?cè)赩iew的dispatchTouchEvent 返回false并且ViewGroup 1 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

image.png

10哟沫、我們?cè)赩iew的dispatchTouchEvent 返回false并且在ViewGroup 2 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向

image.png

11、我們?cè)赩iewGroup2的dispatchTouchEvent 返回false并且在ViewGroup1 的onTouchEvent返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
image.png

12卓舵、我們?cè)赩iewGroup2的onInterceptTouchEvent 返回true攔截此次事件并且在ViewGroup 1 的onTouchEvent返回true消費(fèi)這次事件南用。
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向
image.png

對(duì)于在onTouchEvent消費(fèi)事件的情況:在哪個(gè)View的onTouchEvent 返回true膀钠,那么ACTION_MOVE和ACTION_UP的事件從上往下傳到這個(gè)View后就不再往下傳遞了掏湾,而直接傳給自己的onTouchEvent 并結(jié)束本次事件傳遞過(guò)程。
對(duì)于ACTION_MOVE肿嘲、ACTION_UP總結(jié):ACTION_DOWN事件在哪個(gè)控件消費(fèi)了(return true)融击, 那么ACTION_MOVE和ACTION_UP就會(huì)從上往下(通過(guò)dispatchTouchEvent)做事件分發(fā)往下傳,就只會(huì)傳到這個(gè)控件雳窟,不會(huì)繼續(xù)往下傳尊浪,如果ACTION_DOWN事件是在dispatchTouchEvent消費(fèi),那么事件到此為止停止傳遞封救,如果ACTION_DOWN事件是在onTouchEvent消費(fèi)的拇涤,那么會(huì)把ACTION_MOVE或ACTION_UP事件傳給該控件的onTouchEvent處理并結(jié)束傳遞。

分發(fā)機(jī)制源碼解析

其實(shí)在上述的結(jié)論中誉结,都是可以從源碼上一探究竟的鹅士。那我們先從View的事件分發(fā)開(kāi)始吧,主要還是看dispatchTouchEvent和onTouchEvent方法惩坑。

  • View事件分發(fā)源碼
    1. public boolean dispatchTouchEvent(MotionEvent event) {  
    2.     if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
    3.             mOnTouchListener.onTouch(this, event)) {  
    4.         return true;  
    5.     }  
    6.     return onTouchEvent(event);  
    7. }  
    1. public boolean onTouchEvent(MotionEvent event) {  
    2.     final int viewFlags = mViewFlags;  
    3.     if ((viewFlags & ENABLED_MASK) == DISABLED) {  
    4.         // A disabled view that is clickable still consumes the touch  
    5.         // events, it just doesn't respond to them.  
    6.         return (((viewFlags & CLICKABLE) == CLICKABLE ||  
    7.                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));  
    8.     }  
    9.     if (mTouchDelegate != null) {  
    10.         if (mTouchDelegate.onTouchEvent(event)) {  
    11.             return true;  
    12.         }  
    13.     }  
    14.     if (((viewFlags & CLICKABLE) == CLICKABLE ||  
    15.             (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {  
    16.         switch (event.getAction()) {  
    17.             case MotionEvent.ACTION_UP:  
    18.                 boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;  
    19.                 if ((mPrivateFlags & PRESSED) != 0 || prepressed) {  
    20.                     // take focus if we don't have it already and we should in  
    21.                     // touch mode.  
    22.                     boolean focusTaken = false;  
    23.                     if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {  
    24.                         focusTaken = requestFocus();  
    25.                     }  
    26.                     if (!mHasPerformedLongPress) {  
    27.                         // This is a tap, so remove the longpress check  
    28.                         removeLongPressCallback();  
    29.                         // Only perform take click actions if we were in the pressed state  
    30.                         if (!focusTaken) {  
    31.                             // Use a Runnable and post this rather than calling  
    32.                             // performClick directly. This lets other visual state  
    33.                             // of the view update before click actions start.  
    34.                             if (mPerformClick == null) {  
    35.                                 mPerformClick = new PerformClick();  
    36.                             }  
    37.                             if (!post(mPerformClick)) {  
    38.                                 performClick();  
    39.                             }  
    40.                         }  
    41.                     }  
    42.                     if (mUnsetPressedState == null) {  
    43.                         mUnsetPressedState = new UnsetPressedState();  
    44.                     }  
    45.                     if (prepressed) {  
    46.                         mPrivateFlags |= PRESSED;  
    47.                         refreshDrawableState();  
    48.                         postDelayed(mUnsetPressedState,  
    49.                                 ViewConfiguration.getPressedStateDuration());  
    50.                     } else if (!post(mUnsetPressedState)) {  
    51.                         // If the post failed, unpress right now  
    52.                         mUnsetPressedState.run();  
    53.                     }  
    54.                     removeTapCallback();  
    55.                 }  
    56.                 break;  
    57.             case MotionEvent.ACTION_DOWN:  
    58.                 if (mPendingCheckForTap == null) {  
    59.                     mPendingCheckForTap = new CheckForTap();  
    60.                 }  
    61.                 mPrivateFlags |= PREPRESSED;  
    62.                 mHasPerformedLongPress = false;  
    63.                 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());  
    64.                 break;  
    65.             case MotionEvent.ACTION_CANCEL:  
    66.                 mPrivateFlags &= ~PRESSED;  
    67.                 refreshDrawableState();  
    68.                 removeTapCallback();  
    69.                 break;  
    70.             case MotionEvent.ACTION_MOVE:  
    71.                 final int x = (int) event.getX();  
    72.                 final int y = (int) event.getY();  
    73.                 // Be lenient about moving outside of buttons  
    74.                 int slop = mTouchSlop;  
    75.                 if ((x < 0 - slop) || (x >= getWidth() + slop) ||  
    76.                         (y < 0 - slop) || (y >= getHeight() + slop)) {  
    77.                     // Outside button  
    78.                     removeTapCallback();  
    79.                     if ((mPrivateFlags & PRESSED) != 0) {  
    80.                         // Remove any future long press/tap checks  
    81.                         removeLongPressCallback();  
    82.                         // Need to switch from pressed to not pressed  
    83.                         mPrivateFlags &= ~PRESSED;  
    84.                         refreshDrawableState();  
    85.                     }  
    86.                 }  
    87.                 break;  
    88.         }  
    89.         return true;  
    90.     }  
    91.     return false;  
    92. }

如果要分析到上述情況掉盅,我們還要借助于ViewGroup的分發(fā)事件的源碼,馬上供上哈以舒。
dispatchTouchEvent


    1. public boolean dispatchTouchEvent(MotionEvent ev) {  
    2.     final int action = ev.getAction();  
    3.     final float xf = ev.getX();  
    4.     final float yf = ev.getY();  
    5.     final float scrolledXFloat = xf + mScrollX;  
    6.     final float scrolledYFloat = yf + mScrollY;  
    7.     final Rect frame = mTempRect;  
    8.     boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;  
    9.     if (action == MotionEvent.ACTION_DOWN) {  
    10.         if (mMotionTarget != null) {  
    11.             mMotionTarget = null;  
    12.         }  
    13.         if (disallowIntercept || !onInterceptTouchEvent(ev)) {  
    14.             ev.setAction(MotionEvent.ACTION_DOWN);  
    15.             final int scrolledXInt = (int) scrolledXFloat;  
    16.             final int scrolledYInt = (int) scrolledYFloat;  
    17.             final View[] children = mChildren;  
    18.             final int count = mChildrenCount;  
    19.             for (int i = count - 1; i >= 0; i--) {  
    20.                 final View child = children[i];  
    21.                 if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE  
    22.                         || child.getAnimation() != null) {  
    23.                     child.getHitRect(frame);  
    24.                     if (frame.contains(scrolledXInt, scrolledYInt)) {  
    25.                         final float xc = scrolledXFloat - child.mLeft;  
    26.                         final float yc = scrolledYFloat - child.mTop;  
    27.                         ev.setLocation(xc, yc);  
    28.                         child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
    29.                         if (child.dispatchTouchEvent(ev))  {  
    30.                             mMotionTarget = child;  
    31.                             return true;  
    32.                         }  
    33.                     }  
    34.                 }  
    35.             }  
    36.         }  
    37.     }  
    38.     boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||  
    39.             (action == MotionEvent.ACTION_CANCEL);  
    40.     if (isUpOrCancel) {  
    41.         mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;  
    42.     }  
    43.     final View target = mMotionTarget;  
    44.     if (target == null) {  
    45.         ev.setLocation(xf, yf);  
    46.         if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {  
    47.             ev.setAction(MotionEvent.ACTION_CANCEL);  
    48.             mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
    49.         }  
    50.         return super.dispatchTouchEvent(ev);  
    51.     }  
    52.     if (!disallowIntercept && onInterceptTouchEvent(ev)) {  
    53.         final float xc = scrolledXFloat - (float) target.mLeft;  
    54.         final float yc = scrolledYFloat - (float) target.mTop;  
    55.         mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
    56.         ev.setAction(MotionEvent.ACTION_CANCEL);  
    57.         ev.setLocation(xc, yc);  
    58.         if (!target.dispatchTouchEvent(ev)) {  
    59.         }  
    60.         mMotionTarget = null;  
    61.         return true;  
    62.     }  
    63.     if (isUpOrCancel) {  
    64.         mMotionTarget = null;  
    65.     }  
    66.     final float xc = scrolledXFloat - (float) target.mLeft;  
    67.     final float yc = scrolledYFloat - (float) target.mTop;  
    68.     ev.setLocation(xc, yc);  
    69.     if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {  
    70.         ev.setAction(MotionEvent.ACTION_CANCEL);  
    71.         target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
    72.         mMotionTarget = null;  
    73.     }  
    74.     return target.dispatchTouchEvent(ev);  
    75. }  

如果我們重寫(xiě)View的dispatchTouchEvent并返回true趾痘,我們跟蹤到ViewGroup中第29行代碼,你看執(zhí)行child.dispatchTouchEvent返回true后ViewGroup的該方法也直接return true了蔓钟,接下來(lái)ACTION_UP其他事件類型永票,我們定位到代碼74行,最終會(huì)執(zhí)行target.dispatchTouchEvent,但view的dispatchTouchEvent返回true瓦侮,說(shuō)明事件被消費(fèi)了艰赞,不會(huì)再進(jìn)入到ViewGroup的onTouchEvent里。
如果我們重寫(xiě)View的dispatchTouchEvent并返回false或super肚吏,那么在ViewGroup代碼29行里方妖,我么看到它返回false還會(huì)繼續(xù)走ViewGroup后續(xù)代碼,target為null罚攀,執(zhí)行super.dispatchTouchEvent方法(ViewGroup的父類是View)這里調(diào)用View的dispatchTouchEvent方法->內(nèi)部調(diào)用onTouchEvent方法党觅。
如果我們重寫(xiě)ViewGroup的dispatchTouchEvent方法,直接返回false斋泄,我特意弄了這樣的場(chǎng)景杯瞻,看了Activity的dispatchTouchEvent的源碼,會(huì)發(fā)現(xiàn)會(huì)執(zhí)行Activity的onTouchEvent方法

public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

其他場(chǎng)景也是差不多的炫掐,都是可以套入代碼中做分析的魁莉,這里要我繼續(xù)分析也感覺(jué)無(wú)從入手,大家可以看看源碼募胃,找到關(guān)鍵代碼分析分析場(chǎng)景旗唁。

附上別人分析的源碼解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市痹束,隨后出現(xiàn)的幾起案子检疫,更是在濱河造成了極大的恐慌,老刑警劉巖祷嘶,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屎媳,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡论巍,警方通過(guò)查閱死者的電腦和手機(jī)烛谊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嘉汰,“玉大人丹禀,你說(shuō)我怎么就攤上這事≈O郑” “怎么了湃崩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)接箫。 經(jīng)常有香客問(wèn)我攒读,道長(zhǎng),這世上最難降的妖魔是什么辛友? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任薄扁,我火速辦了婚禮剪返,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘邓梅。我一直安慰自己脱盲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布日缨。 她就那樣靜靜地躺著钱反,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匣距。 梳的紋絲不亂的頭發(fā)上面哥,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音毅待,去河邊找鬼尚卫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛尸红,可吹牛的內(nèi)容都是我干的吱涉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼外里,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼怎爵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起级乐,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疙咸,失蹤者是張志新(化名)和其女友劉穎县匠,沒(méi)想到半個(gè)月后风科,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乞旦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年贼穆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兰粉。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡故痊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玖姑,到底是詐尸還是另有隱情愕秫,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布焰络,位于F島的核電站戴甩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏闪彼。R本人自食惡果不足惜甜孤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缴川,春花似錦茉稠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至恋日,卻和暖如春吞获,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谚鄙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工各拷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人闷营。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓烤黍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親傻盟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子速蕊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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