【IOS開發基礎系列】UIScrollView專題

1 UIScrollView原理

? ? ? ?在滾動過程當中,其實是在修改原點坐標。當手指觸摸后,scroll view會暫時攔截觸摸事件,使用一個計時器。假如在計時器到點后沒有發生手指移動事件,那么scroll view 發送 tracking events 到被點擊的subview。假如在計時器到點前發生了移動事件,那么 scroll view 取消tracking 自己發生滾動。

??? 子類可以重載?

touchesShouldBegin:withEvent:inContentView:

????決定自己是否接收 touch 事件

pagingEnabled:????

????當值是 YES 會自動滾動到 subview 的邊界,默認是NO

touchesShouldCancelInContentView:????

????開始發送 tracking messages 消息給 subview 的時候調用這個方法,決定是否發送 tracking messages 消息到subview。假如返回 NO,發送。YES 則不發送。假如 canCancelContentTouches屬性是NO,則不調用這個方法來影響如何處理滾動手勢。

??? ????????scroll view 還處理縮放和平移手勢,要實現縮放和平移,必須實現委托 viewForZoomingInScrollView:和scrollViewDidEndZooming:withView:atScale: 兩個方法。另外 maximumZoomScale和minimumZoomScale 兩個屬性要不一樣。


1.1 核心原理

????????UIScrollView的核心理念是,它是一個可以在內容視圖之上,調整自己原點位置的視圖。它根據自身框架的大小,剪切視圖中的內容,通常框架是和應用程序窗口一樣大。一個滾動的視圖可以根據手指的移動,調整原點的位置。展示內容的視圖,根據滾動視圖的原點位置,開始繪制視圖的內容,這個原點位置就是滾動視圖的偏移量。ScrollView本身不能繪制,除非顯示水平和豎直的指示器。滾動視圖必須知道內容視圖的大小,以便于知道什么時候停止;一般而言,當滾動出內容的邊界時,它就返回了。

????????某些對象是用來管理內容顯示如何繪制的,這些對象應該是管理如何平鋪顯示內容的子視圖,以便于沒有子視圖可以超過屏幕的尺寸。就是當用戶滾動時,這些對象應該恰當的增加或者移除子視圖。

???? ????因為滾動視圖沒有滾動條,它必須知道一個觸摸信號是打算滾動還是打算跟蹤里面的子視圖。為了達到這個目的,它臨時中斷了一個touch-down的事件,通過建立一個定時器,在定時器開始行動之前,看是否觸摸的手指做了任何的移動。假如定時器行動時,沒有任何的大的位置改變,滾動視圖就發送一個跟蹤事件給觸摸的子視圖。如果在定時器消失前,用戶拖動他們的手指足夠的遠,滾動視圖取消子視圖的任何跟蹤事件,滾動它自己。子類可以重載touchesShouldBegin:withEvent:inContentView:,? pagingEnabled 和touchesShouldCancelInContentView:方法,從而影響滾動視圖的滾動手勢。

????????一個滾動視圖也可以控制一個視圖的縮放和平鋪。當用戶做捏合手勢時,滾動視圖調整偏移量和視圖的比例。當手勢結束的時候,管理視圖內容顯示的對象,就應該恰當的升級子視圖的顯示。當手勢在處理的過程中,滾動視圖不能夠給子視圖,發送任何跟蹤的調用。

1.2 事件處理

????????UIScrollView類有一個delegate,需要適配的協議是UIScrollViewDelegate。為了縮放和平鋪工作,代理必須實現viewForZoomingInScrollView:和scrollViewDidEndZooming:withView:atScale:方法。另外,最大和最小縮放比例應該是不同的。

????????重要的提示:在UIScrollView對象中,你不應該嵌入任何UIWebView和UITableView。假如這樣做,會出現一些異常情況,因為2個對象的觸摸事件可能被混合,從而錯誤的處理。

????????這些都是官方API的解釋,重點是理解UIScrollView怎么來控制手勢的。可以由canCancelContentTouches這個方法的運用來解釋UIScrollView如何控制手勢的。

???? ????假如你設置canCancelContentTouches為YES,那么當你在UIScrollView上面放置任何子視圖的時候,當你在子視圖上移動手指的時候,UIScrollView會給子視圖發送touchCancel的消息。而如果該屬性設置為NO,ScrollView本身不處理這個消息,全部交給子視圖處理。

????????那么這里就有疑問了,既然該屬性設置未來NO了,那么豈不是UIScrollView不能處理任何事件了,那么為何在子視圖上快速滾動的時候,UIScrollView還能移動那。這個一定要區分前面所說的UIScrollView中斷touch-Down事件,開啟一個定時器。我們設置的這個cancancelContentTouches屬性為NO時,只是讓UIScrollView不能發送cancel事件給子視圖。而前面所說的時,中斷touch-down事件,和取消touch事件是倆碼事,所以當快速在子視圖上移動的時候,當然可以滾動。但是如果你慢速的移動的話,就可以區分這個屬性了,假如設定為YES,在子視圖上慢速移動也可以滾動視圖,但是如果為NO?。因為UIScrollView,發送了cancel事件給子視圖處理了,自己當然滾動不了了。


????????首先了解下UIScrollView對于touch事件的接收處理原理:UIScrollView應該是重載了hitTest 方法,并總會返回itself 。所以所有的touch 事件都會進入到它自己里面去了。內部的touch事件檢測到這個事件是不是和自己相關的,或者處理或者除遞給內部的view。

? ??????為了檢測touch是處理還是傳遞,UIScrollView當touch發生時會生成一個timer。???

? ? ?(1)如果150ms內touch未產生移動,它就把這個事件傳遞給內部view

????(2)如果150ms內touch產生移動,開始scrolling,不會傳遞給內部的view。(如當你touch一個table時候,直接scrolling,你touch的那行永遠不會highlight。)

????(3)如果150ms內touch未產生移動并且UIScrollView開始傳遞內部的view事件,但是移動足夠遠的話,且canCancelContentTouches = YES,UIScrollView會調用touchesCancelled方法,cancel掉內部view的事件響應,并開始scrolling。(如當你touch一個table, 停止了一會,然后開始scrolling,那一行就首先被highlight,但是隨后就不在高亮了)

????????在滾動過程當中,其實是在修改原點坐標。當手指觸摸后, scroll view會暫時攔截觸摸事件,使用一個計時器。假如在計時器到點后沒有發生手指移動事件,那么 scroll view 發送 tracking events 到被點擊的 subview。假如在計時器到點前發生了移動事件,那么 scroll view 取消 tracking 自己發生滾動。


1.3 內存重用

????????事件處理看過了,就要考慮scrollView如何重用內存的,下面寫了一個例子模仿UITableView的重用的思想,這里只是模仿,至于蘋果公司怎么實現這種重用的,他們應該有更好的方法。

?????這里的例子是在scrollView上放置4個2排2列的視圖,但是內存中只占用6個視圖的內存空間。當scrollView滾動的時候,通過不停的重用之前視圖的內存空間,從而達到節省內存的效果。重用的方法如下:

????1.如果scrollView向下面滾動,一旦一排視圖滾出了可視范圍,就改變滾動出去的那個view在scrollView中的frame,也就是改變位置到達末尾,達到重用的效果。

????2.如果scrollView向上面滾動,一旦最末排的視圖view滾出了可視范圍,就改變滾動出去的那個view在scrollView中的frame,移動到最前面。

???????下面就需要在你創建的視圖控制器中,創建一個重用的視圖數組,用來把這些要顯示的視圖放入內存中,這里雖然界面上顯示的是2排2列的四個視圖,但是當拖動的時候,可能出現前面一排的視圖顯示一部分,末尾一排的視圖顯示一部分的情況,所以重用的數組中要放置6個視圖。下面是定義的一些宏:

#define?sMyViewTotal?6

#define?sMyViewWidth?150

#define?sMyViewHeight?220

#define?sMyViewGap?10


具體實現代碼如下:

_aryViews?=?[[NSMutableArray?alloc]?init];

for?(int?i?=?0;?i?<?sMyViewTotal;?i++)?{

????CGFloat?x;

????if?(i%2)?{

????????x?=?sMyViewWidth?+?sMyViewGap?+?sMyViewGap/2;

????}

????else{

????x?=?sMyViewGap/2;

????}

????CGFloat?y?=?(sMyViewHeight?+?sMyViewGap)*(i/2);

????MyView?*myView?=?[[MyView?alloc]?initWithFrame: CGRectMake(x, y,?sMyViewWidth, sMyViewHeight)];

????myView.showNumber?=?i;

????[myScrollView?addSubview: myView];

????[_aryViews?addObject: myView];

????[myView?release];

}


所以這里的核心方法是,首先要判斷是向上滾動還是向下滾動方法如下:

-?(void) scrollViewDidScroll: (UIScrollView?*)scrollView{

????BOOL?directDown;

????if?(previousOffSet.y?<?scrollView.contentOffset.y)?{

????????directDown?=?YES;

????}

????else{

????????directDown?=?NO;

????}

????previousOffSet.y?=?scrollView.contentOffset.y;

????//防止最開始就向上面拖動的時候,改變數組視圖樹的位置。

????if?(scrollView.contentOffset.y?<?0)?{

????????return;

????}


????if?(directDown)?{

????????NSLog(@"down");

????????MyView?*?subView?=?[_aryViews?objectAtIndex: firstViewIndex];

????????CGFloat?firstViewYOffset?=?subView.frame.origin.y?+?subView.frame.size.height?+?sMyViewGap;

????????//尋找第一個視圖是否滾動出去

????????if?(firstViewYOffset?<?scrollView.contentOffset.y)?{

????????????//改變數組中第一排可見視圖的位置。

????????????[self?moveIndexInViewsWithDirect: YES];

????????}

????}

????else{

????????NSLog(@"up");

????????MyView?*?subView?=?[_aryViews?objectAtIndex: (firstViewIndex?+ sMyViewTotal -?2) % sMyViewTotal];

????????CGFloat?lastViewYOffset?=?subView.frame.origin.y?-?scrollView.bounds.size.height;

????????if?(lastViewYOffset?>?scrollView.contentOffset.y)?{

????????????[self?moveIndexInViewsWithDirect: NO];

????????}

????}

}


????????每次滾動的時候先判斷滾動位置即offset,和先前的比較。如果先前的大就是向下滾動,否則就是向上滾動。

????????找到了向下滾動了,就該判斷是否子視圖已經離開了可視范圍。方法就是判斷當前offset和視圖的位置進行比較。如果判斷滾到離開了可視范圍,然后就是要改變重用視圖數組中第一個視圖的位置了。這里用了firstViewIndex來記錄scrollView中第一個可見視圖的位置,?循環使用這6個視圖達到重用的目的。自然firstViewIndex上面的一個視圖就是最后一個視圖的位置(firstViewIndex?+?sMyViewTotal?-?1) %sMyViewTotal。所以這里需要改變重用視圖中firstViewIndex即第一個可見視圖的位置。代碼如下:

-?(void) moveIndexInViewsWithDirect: (BOOL)forward{

????[UIView?setAnimationsEnabled: NO];

????if?(forward)?{

????????for?(int?i?=?firstViewIndex;?i?<?(firstViewIndex?+?2);?i++)?{

????????????MyView?*subView?=?[_aryViews?objectAtIndex: i % sMyViewTotal];

????????????subView.showNumber?=?subView.showNumber?+?sMyViewTotal;

????????????subView.frame?=?CGRectMake(subView.frame.origin.x,?subView.frame.origin.y?+?(sMyViewTotal/2)?*?(sMyViewHeight?+?sMyViewGap),?subView.frame.size.width,?subView.frame.size.height);

????????}

????????firstViewIndex?=?(firstViewIndex?+?2) % sMyViewTotal;

????}

????else{

????????int?lastViewIndex?=?firstViewIndex?+?sMyViewTotal?-?1;

????????for?(int?i?=?lastViewIndex;?i?>?(lastViewIndex?-?2);?i-)?{????????????

????????????MyView?*subView?=?[_aryViews?objectAtIndex:(firstViewIndex?+ sMyViewTotal?-?i) % sMyViewTotal];

???????????subView.showNumber?=?subView.showNumber?-?sMyViewTotal;

????????????subView.frame?=?CGRectMake(subView.frame.origin.x,?subView.frame.origin.y?-?(sMyViewTotal/2)?*?(sMyViewHeight?+?sMyViewGap),?subView.frame.size.width,?subView.frame.size.height);

????????}

????????firstViewIndex?=?(firstViewIndex?+?sMyViewTotal?-?2) % sMyViewTotal;

????}

????[UIView?setAnimationsEnabled: YES];

}


??????這里創建的子視圖數字屬性,是用來在視圖上畫數字的,這樣就可以看到視圖重用的效果了,應該是從0開始到無窮多,但是實際上內存中就創建了6個視圖。

-?(void)drawRect:(CGRect)rect

{

????//?Drawing?code

????NSString?*text?=?[NSString?stringWithFormat:@"%d",showNumber];

????[[UIColor?redColor]?set];

????[text?drawInRect: CGRectMake(rect.origin.x, rect.origin.y?+?rect.size.height/2?-?30, rect.size.width, 30) withFont:[UIFont??????fontWithName: @"Helvetica"?size:20] lineBreakMode: UILineBreakModeWordWrap alignment: UITextAlignmentCenter];

}


2 開發運用

2.1 重要屬性

2.1.1 Contentsize與contentInset

????????contentsize是內容的寬和高,contentsize.width是內容的寬度,contentsize.heght是高度,contentsize是UIScrollView的一個屬性,它是一個CGSize,是由核心圖形所定義的架構,那定義了你可以滾軸內容的寬度和高度,你也可以添加可以上下滾動的額外區域。第一種方法是你可以通過添加內容的大小來完成。另外一個比較動態的選擇是UIScrollView的另一個屬性contentInset,contentInset增加你在contentsize中指定的內容能夠滾動的上下左右區域數量contentInset.top以及contentInset.buttom分別表示上面和下面的距離。

????????在滾軸視圖中,有一個叫做ContentOffset的屬性跟蹤UIScrollView的具體位置,你能夠自己獲取和設置它,ContentOffset是你當前可視內容在滾軸視圖邊界的左上角那個點。如圖:

????????可以看出,ContentOffset內容中的那個點不是從contentInset的左上角開始的,而是內容的左上角,此時的ContentOffset是正值,但有時也是負值,如下圖所示:

2.1.2 API介紹

touchesShouldBegin:withEvent:inContentView:?

????決定自己是否接收 touch 事件

pagingEnabled:

????當值是 YES 會自動滾動到 subview 的邊界,默認是NO

touchesShouldCancelInContentView:?

? ? 開始發送 tracking messages 消息給 subview 的時候調用這個方法,決定是否發送 tracking messages 消息到subview。假如返回 NO,發送。YES 則不發送。假如 canCancelContentTouches屬性是NO,則不調用這個方法來影響如何處理滾動手勢。


????????scroll view 還處理縮放和平移手勢,要實現縮放和平移,必須實現委托 viewForZoomingInScrollView:和scrollViewDidEndZooming:withView:atScale:兩個方法。另外 maximumZoomScale和minimumZoomScale 兩個屬性要不一樣。

????幾個屬性介紹:

tracking

????當 touch 后還沒有拖動的時候值是YES,否則NO

zoomBouncing

????當內容放大到最大或者最小的時候值是 YES,否則NO

zooming

????當正在縮放的時候值是 YES,否則NO

decelerating

????當滾動后,手指放開但是還在繼續滾動中。這個時候是 YES,其它時候是NO

decelerationRate

????設置手指放開后的減速率

maximumZoomScale

????一個浮點數,表示能放最大的倍數

minimumZoomScale

????一個浮點數,表示能縮最小的倍數

pagingEnabled

????當值是 YES 會自動滾動到 subview 的邊界。默認是NO

scrollEnabled

????決定是否可以滾動

delaysContentTouches

????是個布爾值,當值是 YES 的時候,用戶觸碰開始,scroll view要延遲一會,看看是否用戶有意圖滾動。假如滾動了,那么捕捉 touch-down 事件,否則就不捕捉。假如值是NO,當用戶觸碰, scroll view 會立即觸發touchesShouldBegin:withEvent:inContentView:,默認是YES

canCancelContentTouches

????當值是 YES 的時候,用戶觸碰后,然后在一定時間內沒有移動,scrollView 發送 tracking events,然后用戶移動手指足夠長度觸發滾動事件,這個時候,scrollView 發送了 touchesCancelled:withEvent: 到 subview,然后 scroView 開始滾動。假如值是 NO,scrollView 發送 tracking events 后,就算用戶移動手指,scrollView 也不會滾動。

contentSize

????里面內容的大小,也就是可以滾動的大小,默認是0,沒有滾動效果。

showsHorizontalScrollIndicator

????滾動時是否顯示水平滾動條

showsVerticalScrollIndicator

????滾動時是否顯示垂直滾動條

bounces

????默認是 yes,就是滾動超過邊界會反彈有反彈回來的效果。假如是 NO,那么滾動到達邊界會立刻停止。

bouncesZoom

????和 bounces 類似,區別在于:這個效果反映在縮放上面,假如縮放超過最大縮放,那么會反彈效果;假如是 NO,則到達最大或者最小的時候立即停止。

directionalLockEnabled

????默認是 NO,可以在垂直和水平方向同時運動。當值是 YES 時,假如一開始是垂直或者是水平運動,那么接下來會鎖定另外一個方向的滾動。 假如一開始是對角方向滾動,則不會禁止某個方向

indicatorStyle

????滾動條的樣式,基本只是設置顏色。總共3個顏色:默認、黑、白

scrollIndicatorInsets

????設置滾動條的位置


2.2 具體使用范例

使用一個ScrollView

// 創建一個UIScrollView

CGRectframe = CGRectMake( 0, 0, 200, 200);

scrollView = [[UIScrollView alloc] initWithFrame: frame];

// 添加子視圖(框架可以超過scroll view的邊界)

frame = CGRectMake( 0, 0, 500, 500);

myImageView = [[UIImageView alloc] initWithFrame: frame];

[scrollView addSubview: myImageView];

// 設置內容尺寸

scrollView.contentSize = CGSize(500,500);


2.3 擴展ScrollView的行為

????????應用程序通常需要知道有關的滾圖的事件:

????scrolloffset改變的時候

????拖動開始和結束

? ? 減速的開始和結束


2.3.1 通過子類化擴展ScrollView的行為

????????創建一個子類

????????重寫一些功能并改變行為

????????關于這種方式的爭議

? ? ? ? 應用程序的邏輯和行為變成了視圖本身的一部分,就像,你可能有一些定制的滾軸邏輯,,在那你只在意一個視圖控制,但你想在不同地方重復使用你的滾軸視圖,如果你必須為每個都子類化,你最后會有很多不同的滾軸視圖子類以及在視圖中的特定應用邏輯。

? ? ? ? 編寫很多子類是很沉悶的事情,你最后會有很多無法重復使用的單獨視圖,而MVC的視圖部分的一個重點是視圖是可以在不同的控制器和不同的模式之中重復使用的,如果我們把所有邏輯都放在視圖中,它減少了可復用性。

? ? ? ?你的代碼變得很牢固地配對在一起,它實際上變成了超類的一部分,你無法從UIScrollView中析取它,之后用其它東西代替,如果它在你控制器中且為控制器的一部分,在之后更容易改變它工作的方式和重新安排你應用程序的一些部分。


2.3.2 通過委托來擴展ScrollView的行為(常用的)

????????委托是一個單獨的對象,協議,定義了委托會實現的一系列功能的Objective-C協議,它創建了一系列很清晰的撤銷點,在那里你能定制行為和外觀。它在這些對象之間保持了松散的配對,視圖本身與視圖控制器或任何其它的控制器對象,委托不是滾軸視圖的直接子類,它比起牢固配對的子類更加的松散。


2.4 開發技巧

2.4.1 計算當前頁面數

- (void) scrollViewDidEndDecelerating: (UIScrollView*)scrollView {

????// 得到每頁寬度

??? CGFloat pageWidth = CGRectGetWidth(self.paggingScrollView.frame);


??? // 根據當前的x坐標和頁寬度計算出當前頁數

??? //此屬性變化會調用Set方法

??? self.currentPage = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;

}


- (void) setCurrentPage: (NSInteger)currentPage {

??? if (_currentPage==currentPage)

??????? return;

??? _lastPage = _currentPage;

??? _currentPage= currentPage;

??? self.paggingNavbar.currentPage= currentPage;


??? [self setupScrollToTop];

??? [self callBackChangedPage];

}


2.4.2? 指定Cell大小與間距



2.4.3 支持點擊狀態欄回到頁面頂部

????????scrollsToTop是UIScrollView的一個屬性,主要用于點擊設備的狀態欄時,是scrollsToTop == YES的控件滾動返回至頂部。

????????每一個默認的UIScrollView的實例,他的scrollsToTop屬性默認為YES,所以要實現某一UIScrollView的實例點擊設備狀態欄返回頂部,則需要關閉其他的UIScrollView的實例的scrollsToTop屬性為NO。很好理解:若多個scrollView響應返回頂部的事件,系統就不知道到底要將那個scrollView返回頂部了,因此也就不做任何操作了。


3 參考資料

Scroll View Programming Guide for iOS筆記

http://blog.sina.com.cn/s/blog_67419c420100phyf.html


第二、UIScrollView的使用大全

http://blog.csdn.net/ch_soft/article/details/6947695


[置頂] UIScrollView用法

http://blog.csdn.net/mengtnt/article/details/6723245


UIScrollView原理詳解

http://blog.csdn.net/likendsl/article/details/7592867


TwitterPaggingViewer——類似Twitter,將滑動視圖的UIPageControl(就是記錄當前頁面的一串小點)放到導航欄

http://code4app.com/ios/TwitterPaggingViewer/53a7ed4a933bf0794c8b48f9


UICollectionViewLayout

http://blog.csdn.net/majiakun1/article/details/17204921


ios開發——解決UICollectionView的cell間距與設置不符問題

http://www.bkjia.com/IOSjc/917782.html


IOS中scrollsToTop問題小結

http://blog.csdn.net/enuola/article/details/32331933


ios重寫Cell后tabelView不能響應點擊狀態欄回到到頂部

http://www.cocoachina.com/bbs/read.php?tid-248386.html


深入理解iOS開發中的UIScrollView

http://mobile.51cto.com/hot-443341.htm


IOS——iOS組件之UIScrollView詳解

https://segmentfault.com/a/1190000002412930


IOSUI—UIScrollView控件介

http://www.cnblogs.com/wendingding/p/3754210.html

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,468評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內容