安全區(qū)適配

前言

隨著蘋果日趨追趕大屏風(fēng)潮的腳步凰棉,之前讓 Android 同學(xué)頭疼不已的屏幕適配問(wèn)題得哆,也逐漸開始困擾我們廣大 iOS 小伙伴們沥曹。該篇文章在 WWDC 關(guān)于 UIKit:Apps for Every Size and Shape 的基礎(chǔ)上進(jìn)行總結(jié)與實(shí)踐髓帽,希望能夠幫助大家快速準(zhǔn)確的處理布局與適配問(wèn)題奄薇。

文章結(jié)構(gòu)如下:

  1. Safe Area 的概念與特性
  • safeAreaInsets 與 safeAreaLayoutGuide 調(diào)用時(shí)機(jī)
  • 安全區(qū)域擴(kuò)展
  • 安全區(qū)域計(jì)算規(guī)則
  • 安全區(qū)域傳遞性
  1. UIView 的 Margins
  • layoutMargins
  • directionalLayoutMargins
  • systemMinimumLayoutMargins
  • preservesSuperviewLayoutMargins
  • insetsLayoutMarginsFromSafeArea
  1. UIScrollView 適配
  • adjustedContentInset
  • contentInsetAdjustmentBehavior
  1. UITableView & UICollectionVIew
  • UITableView 的 insetsContentViewsToSafeArea
  • UICollectionViewFlowLayout 的 sectionInsetReference

常見機(jī)型尺寸對(duì)照表:

機(jī)型 尺寸(英寸) 寬高 分辨率
5驳阎、SE 4 320x568 640x1136
6、7馁蒂、8 4.7 375x667 750x1334
6+呵晚、7+、8+ 5.5 414x736 1080x1920
X沫屡、XS 5.8 375x812 1125x2436
XR 6.1 414x896 828x1792
XS Max 6.5 414x896 1242x2688

Safe Area 的概念與特性

可被完全看見的饵隙,不影響用戶操作的矩形區(qū)域,稱為安全區(qū)沮脖,在 iOS 11 伴隨著全(劉)面(海)屏被提出金矛。它的出現(xiàn)取代了 iOS 7 以來(lái)的 topLayoutGuidebottomLayoutGuide,成為新的參照物來(lái)保證 view 能正常勺届、安全地顯示驶俊。

這個(gè)區(qū)域的大小是由系統(tǒng)來(lái)決定的。在某個(gè) view 上的布局只需要相對(duì)于其 safe area 就可以了免姿。每個(gè) view 的 safe area 都可以通過(guò) iOS 11 新增的 API safeAreaInsets 或者 safeAreaLayoutGuide 獲取饼酿。

image1.png

safeAreaInsets 與 safeAreaLayoutGuide 調(diào)用時(shí)機(jī)

在視圖顯示在屏幕上或者裝載到一個(gè)視圖層級(jí)中的時(shí)候,才能正確獲取到 safeAreaInsetssafeAreaLayoutGuide胚膊,否則返回0故俐。
所以與安全區(qū)相關(guān)的布局操作應(yīng)放在 layoutSubviewsviewDidLayoutSubviews 中進(jìn)行處理奈应。

image2.png

安全區(qū)域擴(kuò)展

UIViewController 支持使用 additionalSafeAreaInsets 屬性,自定義擴(kuò)展安全區(qū)域大小购披,以滿足一些應(yīng)用場(chǎng)景杖挣。這里蘋果官方給出了一個(gè)例子:

You might use this property to extend the safe area to include custom content in your interface. For example, a drawing app might use this property to avoid displaying content underneath tool palettes.

安全區(qū)域計(jì)算規(guī)則

對(duì)于 ViewController 的根視圖,會(huì)根據(jù)各種 bar 的高度刚陡,以及開發(fā)者自己設(shè)置的 additionalSafeAreaInsets 屬性來(lái)計(jì)算惩妇。

對(duì)于層級(jí)中的其他視圖,safeAreaInsets反映了 View 被覆蓋的區(qū)域筐乳。只有當(dāng)該視圖存在超出其父視圖安全區(qū)域的部分歌殃,safeAreaInsets 才會(huì)返回相應(yīng)的值。如果整個(gè)視圖已經(jīng)處于安全區(qū)域中蝙云,那么 safeAreaInsets 返回 0氓皱。

安全區(qū)域傳遞性

通過(guò) self.additionalSafeAreaInsets = UIEdgeInsetsMake(15, 15, 15, 15) 更改 ViewController 根視圖的 Safe Area(藍(lán)色部分),然后在其上添加一個(gè)超出安全區(qū)域的子視圖(黃色部分)勃刨,最后在子視圖上添加一個(gè)Label(綠色部分)并依據(jù)該子視圖的 safeAreaInsets 建立約束波材。從最終的呈現(xiàn)效果可以論證父視圖的安全區(qū)域會(huì)向上傳遞

image3.png

小結(jié)

這個(gè)由系統(tǒng)控制的區(qū)域身隐,是我們適配時(shí)候需要重點(diǎn)關(guān)注的對(duì)象廷区。尤其是要清楚地知道,安全區(qū)到屏幕邊距在橫屏或豎屏贾铝、NavigationBar 與 TabBar 存在或不存在等情況下的具體數(shù)值隙轻,這樣在對(duì)控件進(jìn)行布局時(shí),才能準(zhǔn)確把握其位置垢揩。

iOS 11 之后玖绿,我們可以通過(guò)下面的代碼來(lái)獲取這個(gè)具體數(shù)值:

    UIEdgeInsets insets = UIEdgeInsetsZero;
    if(@available(iOS 11.0, *)) {
        insets = view.safeAreaInsets;
    }

iOS 11 之前就需要我們通過(guò)宏定義去進(jìn)行相應(yīng)的處理。例如狀態(tài)欄叁巨、導(dǎo)航欄等的高度獲劝叻恕:

#define StatusBarHeight                     CGRectGetHeight([UIApplication sharedApplication].statusBarFrame)
#define TabBarHeight(tabBar)                CGRectGetHeight(tabBar.frame)
#define NavigationBarHeight(navigationBar)  CGRectGetHeight(navigationBar.frame)

常見系統(tǒng)控件高度表:

控件 豎屏 橫屏
StatusBar 20 0
StatusBar(X) 44 0
NavigationBar 44 32
NavigationBar(XR、Max) 44 44
TabBar 49 32
TabBar(X) 83 53
TabBar(XR俘种、Max) 83 70
HomeIndicator 34 21

注:iPhone X 橫屏下左右兩邊安全距離為44

UIView 的 Margins

就像我們用田字格寫漢字時(shí)上留天秤标,下留地,左右要留空一樣宙刘,界面的布局也應(yīng)該留有邊界苍姜。這個(gè)邊界就是 Margins

image4.png

layoutMargins

iOS 8 中提出了 layoutMargins 的概念悬包,其主要用于設(shè)置子視圖與父視圖之間的邊距衙猪。默認(rèn)情況下,layoutMargin 到各邊的距離為8。

typedef struct UIEdgeInsets {
    CGFloat top, left, bottom, right;
} UIEdgeInsets;

In iOS 11 and later, use the directionalLayoutMargins property to specify layout margins instead of this property.

directionalLayoutMargins

iOS 11 提出垫释,主要是為了Right To Left(RTL)語(yǔ)言下可以進(jìn)行自動(dòng)適配丝格。上面蘋果的官方文檔也有指出,用directionalLayoutMargins替換掉layoutMargin棵譬,這樣在做國(guó)際化的時(shí)候就無(wú)需針對(duì)語(yǔ)言專門進(jìn)行適配了显蝌。

typedef struct NSDirectionalEdgeInsets {
    CGFloat top, leading, bottom, trailing;
} NSDirectionalEdgeInsets API_AVAILABLE(ios(11.0),tvos(11.0),watchos(4.0));

systemMinimumLayoutMargins

UIViewController 存在屬性 systemMinimumLayoutMargins,當(dāng) viewRespectsSystemMinimumLayoutMargins 為 YES 時(shí)订咸,可以通過(guò)該屬性更改 layoutMargins 的默認(rèn)值曼尊。

preservesSuperviewLayoutMargins

iOS 8 開始引入,當(dāng)這個(gè)屬性的值為 YES 的時(shí)候脏嚷,一個(gè)視圖布局內(nèi)容時(shí)其父視圖的 margins 也會(huì)被考慮在內(nèi)骆撇,此時(shí)該視圖的實(shí)際 margins 為該視圖與父視圖 margins 中的最大值。默認(rèn)是 NO父叙。

insetsLayoutMarginsFromSafeArea

iOS 11 開始引入神郊,控制 safeAreaInsets 是否加到 layoutMargins 上。默認(rèn)為 YES趾唱。

//orangeView.insetsLayoutMarginsFromSafeArea = YES;
safeAreaInsets: {88, 0, 0, 0}
layoutMargins: {88, 50, 0, 0}

//orangeView.insetsLayoutMarginsFromSafeArea = NO;
safeAreaInsets: {88, 0, 0, 0}
layoutMargins: {0, 50, 0, 0}

獲取實(shí)際layoutMargins的偽代碼如下:

- (UIEdgeInsets)getRealLayoutMargins {
    UIEdgeInsets layoutMargins = self.layoutMargins;  //默認(rèn)是8
    if (self.preservesSuperviewLayoutMargins) {
        layoutMargins = Max(layoutMargins, self.superview.layoutMargins);
    }
    if (self.insetsLayoutMarginsFromSafeArea) {
        layoutMargins = Add(layoutMargins, self.safeAreaInsets);
    }
    return layoutMargins;
}

小結(jié)

日常布局的時(shí)候涌乳,往往都不會(huì)使用 layoutMargins,這是因?yàn)樘峁┑囊曈X標(biāo)注是不會(huì)考慮這個(gè)值的鲸匿,我們更希望能直接設(shè)置約束值為標(biāo)注值爷怀,而不是進(jìn)行轉(zhuǎn)換操作阻肩。目前看來(lái)只有在進(jìn)行語(yǔ)言適配的情況下才會(huì)以 view 的 directionalLayoutMargins 為基準(zhǔn)建立約束吧带欢。

UIScrollView 適配

adjustedContentInset

The insets derived from the content insets and the safe area of the scroll view.

這句話用代碼翻譯過(guò)來(lái)就是adjustedContentInset = safeAreaInset + contentInset,這里要不要加safeAreaInset則取決于contentInsetAdjustmentBehavior烤惊。下面將重點(diǎn)解釋下contentInsetAdjustmentBehavior這個(gè)屬性乔煞。

另外值得注意的一點(diǎn)是 iOS 10 中 contentInset 與 iOS 11 的 adjustedContentInset 表現(xiàn)是一致的,即 contentInset 的值在 iOS 10 中 與 iOS 11 中可能是不同的:

//iOS 10 automaticallyAdjustsScrollViewInsets = YES
contentInset = UIEdgeInsets(top: 74.0, left: 10.0, bottom: 59.0, right: 10.0)
//iOS 11 contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAlways
contentInset = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
adjustedContentInset = UIEdgeInsets(top: 74.0, left: 10.0, bottom: 59.0, right: 10.0)

contentInsetAdjustmentBehavior

iOS 7 中 UIViewController 的 automaticallyAdjustsScrollViewInsets 屬性在 iOS 11 中被廢棄掉了柒室。取而代之的是 UIScrollView 的 contentInsetAdjustmentBehavior渡贾。

typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
    UIScrollViewContentInsetAdjustmentAutomatic, // Similar to .scrollableAxes, but for backward compatibility will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller, regardless of whether the scroll view is scrollable
    UIScrollViewContentInsetAdjustmentScrollableAxes, // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)
    UIScrollViewContentInsetAdjustmentNever, // contentInset is not adjusted
    UIScrollViewContentInsetAdjustmentAlways, // contentInset is always adjusted by the scroll view's safeAreaInsets
} API_AVAILABLE(ios(11.0),tvos(11.0));
  • UIScrollViewContentInsetAdjustmentNever
    不依據(jù) scroll view 的safeAreaInsets進(jìn)行適配。
- (UIEdgeInsets)adjustedContentInset {
    return self.contentInset;
}
  • UIScrollViewContentInsetAdjustmentAlways
    總是依據(jù) scroll view 的safeAreaInsets進(jìn)行適配
- (UIEdgeInsets)adjustedContentInset {
    return UIEdgeInsetsMake(self.contentInset.top + self.safeAreaInsets.top,
    self.contentInset.left + self.safeAreaInsets.left,
    self.contentInset.bottom + self.safeAreaInsets.bottom,
    self.contentInset.right + self.safeAreaInsets.right);
}
  • UIScrollViewContentInsetAdjustmentScrollableAxes
    在可以滑動(dòng)的方向上(contentSize.width/height > frame.size.width/heightalwaysBounceHorizontal/Vertical = YES)依據(jù) scroll view 的safeAreaInsets進(jìn)行適配雄右。
    當(dāng)展示內(nèi)容太少空骚,contentSize.width/height < frame.size.width/height而導(dǎo)致 scroll view 不能滑動(dòng),則不會(huì)適配擂仍。
- (UIEdgeInsets)adjustedContentInset {
    UIEdgeInsets adjustedContentInset = self.contentInset;
    if (self.contentSize.width > self.frame.size.width || self.alwaysBounceHorizontal == YES) {
        adjustedContentInset.left += self.safeAreaInsets.left;
        adjustedContentInset.right += self.safeAreaInsets.right;
    }
    if (self.contentSize.height > self.frame.size.height || self.alwaysBounceVertical) {
        adjustedContentInset.top += self.safeAreaInsets.top;
        adjustedContentInset.bottom += self.safeAreaInsets.bottom;
    }
    return adjustedContentInset;
}
  • UIScrollViewContentInsetAdjustmentAutomatic
    處于導(dǎo)航層級(jí)且automaticallyAdjustsScrollViewInsets = YES的 view controller 中囤屹,作為第一個(gè)被添加子視圖的 scroll view, 無(wú)論能否滑動(dòng),頂部與底部都將依據(jù) scroll view 的safeAreaInsets進(jìn)行適配逢渔。其他情況下與ScrollableAxes表現(xiàn)相同肋坚。
- (UIEdgeInsets)adjustedContentInset {
    UIEdgeInsets adjustedContentInset = self.contentInset;
    if (viewController.automaticallyAdjustsScrollViewInsets == YES && viewController.navigationController && viewController.view.subviews.firstObject == self) {
        adjustedContentInset.top += self.safeAreaInsets.top;
        adjustedContentInset.bottom += self.safeAreaInsets.bottom;
    }
    else {
        if (self.contentSize.width > self.frame.size.width || self.alwaysBounceHorizontal == YES) {
            adjustedContentInset.left += self.safeAreaInsets.left;
            adjustedContentInset.right += self.safeAreaInsets.right;
        }
        if (self.contentSize.height > self.frame.size.height || self.alwaysBounceVertical) {
            adjustedContentInset.top += self.safeAreaInsets.top;
            adjustedContentInset.bottom += self.safeAreaInsets.bottom;
        }
    }
    return adjustedContentInset;
}

UITableView & UICollectionVIew

作為 UIScrollView 的子類,以上特性 UITableView 與 UICollectionVIew 也都具有。但是由于 UITableViewHeaderFooterView智厌、UITableViewCell诲泌、UICollectionReusableView、UICollectionViewCell 的存在铣鹏,適配安全區(qū)的時(shí)候也有一定的差異化敷扫。

UITableView 的 insetsContentViewsToSafeArea

該屬性能夠控制 UITableViewHeaderFooterView 與 UITableViewCell 的 contentView 是否被 safeAreaInsets 所影響,默認(rèn)值為 YES诚卸,具體的呈現(xiàn)效果如下:

image5.png

這就意味著在 iOS 11呻澜,我們?cè)跒閔eader、footer惨险、cell添加子控件時(shí)羹幸,不需要改變子控件的位置,UITableView自動(dòng)幫我們適配辫愉。

當(dāng)insetsContentViewsToSafeArea為 NO栅受,橫屏下 cell 部分區(qū)域會(huì)被齊劉海遮擋:

image6.png

UICollectionViewFlowLayout 的 sectionInsetReference

現(xiàn)在,我們使用 UICollectionView 實(shí)現(xiàn)一個(gè)一樣的列表界面:

image7.png

從截圖中可以看到恭朗,UICollectionView 在默認(rèn)情況下沒有像 UITableView 那樣去處理屏镊。這是由于 UICollectionReusableView 不存在 contentView,同時(shí)考慮到 UICollectionView 布局的復(fù)雜性痰腮,并不適合統(tǒng)一進(jìn)行適配而芥。

單列列表布局情況下想要正確布局內(nèi)容,唯一的方法是讓子視圖依據(jù)安全區(qū)建立約束膀值。

這里有一個(gè)需要注意的地方就是棍丐,
UICollectionViewCell 雖然存在contentView屬性,但是通過(guò) xib 拖拽的 cell 視圖層級(jí)中沒有contentView沧踏,添加在 cell 上的子視圖也不能夠直接以 cell 的 safe area 為基準(zhǔn)添加約束歌逢。可以通過(guò)手動(dòng)添加view作為內(nèi)容容器來(lái)解決翘狱。

[圖片上傳失敗...(image-c96b19-1542424776344)]


image11.png

接下來(lái)改變 UICollectionViewFlowLayout 的 itemSize秘案,使其呈現(xiàn)多列網(wǎng)格布局:

image8.png

可以看到在橫屏?xí)r cell 被齊劉海遮擋了一部分。當(dāng)然我們通過(guò)設(shè)置 UICollectionViewFlowLayout 的 sectionInset 能夠適配安全區(qū)潦匈。但是在 iOS 11 中阱高,蘋果為 UICollectionViewFlowLayout 添加了一個(gè)新屬性 sectionInsetReference 來(lái)處理它。

typedef NS_ENUM(NSInteger, UICollectionViewFlowLayoutSectionInsetReference) {
    UICollectionViewFlowLayoutSectionInsetFromContentInset,
    UICollectionViewFlowLayoutSectionInsetFromSafeArea,
    UICollectionViewFlowLayoutSectionInsetFromLayoutMargins
} API_AVAILABLE(ios(11.0), tvos(11.0)) API_UNAVAILABLE(watchos);

系統(tǒng)默認(rèn)值為 UICollectionViewFlowLayoutSectionInsetFromContentInset茬缩,那么我們將 sectionInsetReference 設(shè)置為 UICollectionViewFlowLayoutSectionInsetFromSafeArea

這種情況下 sectionInset 等于原來(lái)的大小加上 safeAreaInsets 的大小赤惊。

類似地,當(dāng)使用 UICollectionViewFlowLayoutSectionInsetFromLayoutMargins 時(shí)寒屯,collection view 的 layoutMargins 會(huì)被添加到 sectionInset荐捻。

image10.png

小結(jié)

對(duì)于 Scroll View黍少,我們通常會(huì)禁用掉系統(tǒng)自動(dòng)添加偏移量的行為,即設(shè)置 contentInsetAdjustmentBehaviorUIScrollViewContentInsetAdjustmentNever处面,然后通過(guò) frame 去控制展示厂置。其他三個(gè)枚舉值的具體使用場(chǎng)景目前還不是很常見,我覺得一些沉浸式的設(shè)計(jì)可能會(huì)有發(fā)揮的余地魂角。

Table View 不需要我們做額外的處理昵济,它的 insetsContentViewsToSafeArea 屬性默認(rèn)為 YES,會(huì)幫我們調(diào)整 header野揪、footer 以及 cell 的 contentView访忿。

Collection View 在 iOS 11 之前,單列情況可以設(shè)置 cell 子視圖與 cell 左右邊距的距離大于 44 來(lái)避免橫屏齊劉海的遮蓋問(wèn)題斯稳,多列則可以通過(guò)設(shè)置 sectionInset 進(jìn)行適配海铆。iOS 11 之后單列情況 cell 子視圖直接依據(jù)安全區(qū)進(jìn)行布局,多列可以使用 sectionInsetReference 防止齊劉海遮蓋挣惰。

尾聲

Safe Area 的出現(xiàn)卧斟,為我們提供了一個(gè)虛擬的布局區(qū)域,我們只需要專注于根據(jù)安全區(qū)建立約束即可憎茂,不用再去關(guān)心狀態(tài)欄珍语、導(dǎo)航欄等系統(tǒng)控件變化導(dǎo)致的適配∈#總的來(lái)說(shuō)是對(duì)界面布局效率的重大提升板乙,蘋果也通過(guò)使 xib 的安全區(qū)向下兼容到 iOS 9 等方式,鼓勵(lì)廣大開發(fā)者去使用這些新特性拳氢,做出更精美的應(yīng)用募逞。那就讓我們愉快的使用起來(lái)吧,Just Do IT饿幅!

參考文獻(xiàn):

iOS開發(fā)-LayoutGuide

最近很火的 Safe Area 到底是什么

隨手記在iPhone X上的適配實(shí)踐總結(jié)

UIView的Margins

iOS 11 安全區(qū)域適配總結(jié)

WWDC 2018:快速將開發(fā)項(xiàng)目適配所有的iOS設(shè)備

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凡辱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子栗恩,更是在濱河造成了極大的恐慌,老刑警劉巖洪燥,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件磕秤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡捧韵,警方通過(guò)查閱死者的電腦和手機(jī)市咆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)再来,“玉大人蒙兰,你說(shuō)我怎么就攤上這事磷瘤。” “怎么了搜变?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵采缚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我挠他,道長(zhǎng)扳抽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任殖侵,我火速辦了婚禮贸呢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拢军。我一直安慰自己楞陷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布茉唉。 她就那樣靜靜地躺著猜谚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赌渣。 梳的紋絲不亂的頭發(fā)上魏铅,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音坚芜,去河邊找鬼览芳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸿竖,可吹牛的內(nèi)容都是我干的沧竟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缚忧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悟泵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起闪水,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤糕非,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后球榆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朽肥,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年持钉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衡招。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡每强,死狀恐怖始腾,靈堂內(nèi)的尸體忽然破棺而出州刽,到底是詐尸還是另有隱情,我是刑警寧澤浪箭,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布穗椅,位于F島的核電站,受9級(jí)特大地震影響山林,放射性物質(zhì)發(fā)生泄漏房待。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一驼抹、第九天 我趴在偏房一處隱蔽的房頂上張望桑孩。 院中可真熱鬧,春花似錦框冀、人聲如沸流椒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宣虾。三九已至,卻和暖如春温数,著一層夾襖步出監(jiān)牢的瞬間绣硝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工撑刺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹉胖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓够傍,卻偏偏與公主長(zhǎng)得像甫菠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冕屯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

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