第十三章——棧視圖【譯】

在這本書中,您一直在使用自動布局來創(chuàng)建靈活的界面,可以跨設(shè)備類型和大小進(jìn)行擴(kuò)展。 自動布局是一種非常強(qiáng)大的技術(shù),但是這種能力帶來了復(fù)雜性。 布置一個界面通常需要大量的約束,并且由于需要不斷地添加和移除約束,所以創(chuàng)建動態(tài)界面是很困難的。

通常,界面(或界面的子部分)可以以線性方式布局。 考慮一下您編寫的其他應(yīng)用程序:第1章的 Quiz 應(yīng)用程序由四個子視圖組成,它們是垂直布局的。 對于 WorldTrotter 應(yīng)用程序來說也是如此; ConversionViewController 有一個垂直界面,由一個文本字段和幾個標(biāo)簽組成。

具有線性布局的界面非常適合使用 棧視圖(stack view)。 棧視圖是 UIStackView 的一個實例,它允許您創(chuàng)建一個垂直的或水平的布局,它很容易布局,并且會自動管理您通常需要自己去管理的大部分約束。 也許最重要的是,您可以在其他棧視圖中嵌套棧視圖,這使您能夠在很短的時間內(nèi)創(chuàng)建真正令人驚嘆的界面。

在本章中,您將繼續(xù)使用 Homepwner 創(chuàng)建一個界面,以顯示特定 Item 的詳細(xì)信息。 您創(chuàng)建的界面將由多個嵌套的棧視圖組成,包括垂直和水平的視圖(圖13.1)。

圖13.1 Homepwner和堆棧視圖

使用UIStackView

您將創(chuàng)建一個用于編輯 Item 詳細(xì)信息的界面。 您將在本章中完成基本界面,然后您將在第14章中完成實施細(xì)節(jié)。

在頂層,您將擁有一個垂直的堆棧視圖,其中包含四個元素,顯示 item 的名稱(Name)、序列號(Serial)、值(Value)和創(chuàng)建日期(Date Created)(圖13.2)。

圖13.2 垂直棧視圖布局

打開您的 Homepwner 項目,然后打開 Main.storyboard。 將一個新的 View Controller 從對象庫拖到畫布上。 將 Vertical Stack View 從對象庫拖動到 View ControllerView 上。 向棧視圖添加約束上下左右固定為 8 點(diǎn)。

現(xiàn)在將 UILabel 的 4 個實例從對象庫拖放到棧視圖中。 從上到下,給這些標(biāo)簽添加文本 “Name”、“Serial”、“Value” 和 “Date Created”(圖13.3)。

圖13.3添加標(biāo)簽到棧視圖中

您可以馬上看到問題:標(biāo)簽都有一個紅色邊框(表示自動布局問題),并且有一個警告,一些視圖是垂直不明確的。 有兩種方法可以解決這個問題:使用自動布局或修改棧視圖的屬性。 我們首先使用自動布局解決方案,因為它突出顯示了自動布局的重要性。

隱式約束

你在第3章學(xué)到,每個視圖都有一個固有的內(nèi)容大小。 您還了解到,如果不指定明確確定寬度或高度的約束,則視圖將從其固有內(nèi)容大小中派生出其寬度或高度。 這是如何實現(xiàn)的呢?

它使用從視圖的 content hugging prioritiescontent compression resistance priorities 的隱式約束來完成這一任務(wù)。 每個視圖(View)的每個軸都有以下優(yōu)先級之一:

  • horizontal content hugging priority
  • vertical content hugging priority
  • horizontal content compression resistance priority
  • vertical content compression resistance priority

Content hugging priorities

Content hugging priorities 的內(nèi)容就像放置在視圖周圍的橡皮筋。 橡皮筋使得視圖不想大于其尺寸中的內(nèi)在內(nèi)容大小。 每個優(yōu)先級與0到1000之間的值相關(guān)聯(lián)。值為1000表示視圖不能比該維度上的內(nèi)在內(nèi)容大小更大。

讓我們來看一個只有水平維度的例子。 假設(shè)您有兩個標(biāo)簽彼此相鄰,兩個視圖之間以及每個視圖及其父級視圖之間的約束如圖13.4所示。

圖13.4 兩個標(biāo)簽并排

在父視圖變得越來越大之前這樣顯示看起來還很不錯。 但到了那時候哪個標(biāo)簽應(yīng)該變得更寬? 第一個標(biāo)簽,第二個標(biāo)簽,還是兩者? 如圖13.5所示,界面目前是模糊的。

圖13.5 模糊的布局

這就是 content hugging priority。 具有較高 content hugging priority 的視圖是不拉伸的視圖。 你可以把優(yōu)先值看作是橡皮筋的 “強(qiáng)度”。 優(yōu)先級越高,橡皮筋越堅固,它想要擠壓它的內(nèi)在內(nèi)容的尺寸就越大。
注:也就是優(yōu)該值越大,越難拉伸

Content compression resistance priorities

Content compression resistance priorities 決定了一個視圖拒絕小于其固有內(nèi)容大小的程度。 請考慮圖13.4中的相同的兩個標(biāo)簽。 如果父級視圖的寬度減小了會發(fā)生什么? 其中一個標(biāo)簽需要截斷它的文本(圖13.6)。 但是是哪一個呢?

圖13.6 被壓縮的模糊布局

具有較高 Content compression resistance priorities 的視圖是能夠抵抗壓縮的視圖,因此不會截斷其文本。

有了這些知識,您現(xiàn)在就可以用棧視圖來解決問題了。

選擇 Date Created 標(biāo)簽并打開其大小(Size)檢查器。 找到 Vertical Content Hugging Priority 并將其降低到249.現(xiàn)在其他三個標(biāo)簽擁有更高的 content hugging priority,所以他們將擠壓其內(nèi)在的內(nèi)容高度。 Date Created 標(biāo)簽將伸展以填充剩余空間。

棧視圖 distribution

我們來看看另一種解決問題的方法。 堆棧視圖具有可確定其內(nèi)容布局方式的多個屬性。

在畫布上或使用文檔大綱選擇棧視圖。 打開屬性檢查器,找到頂部標(biāo)記為 Stack View 的部分。 決定內(nèi)容如何布局的屬性之一是 Distribution 屬性。 目前它被設(shè)置為 Fill,它允許視圖根據(jù)其固有的內(nèi)容大小來排列其內(nèi)容。 將值更改為 Fill Equally。 這將調(diào)整標(biāo)簽的大小,使它們都具有相同的高度,忽略內(nèi)在的內(nèi)容大小(圖13.7)。 要想知道棧視圖可以具有的其他的 distribution 值,請閱讀文檔。

圖13.7堆棧視圖設(shè)置為fill equally

將堆棧視圖的 Distribution 更改為 Fill; 這是你在這一章中想要的。

嵌套堆棧視圖

棧視圖最強(qiáng)大的功能之一是它們可以彼此嵌套。 您將使用此方式在較大的垂直棧視圖中嵌套水平棧視圖。 前三個標(biāo)簽將在其旁邊顯示一個文本字段,顯示該 Item 的相應(yīng)值,并允許用戶編輯該值。

在畫布上選擇 Name 標(biāo)簽。 單擊自動布局約束菜單中左側(cè)的第二個圖標(biāo):


這將將所選視圖嵌入到棧視圖中。

選擇新的棧視圖并打開其屬性檢查器。 棧視圖當(dāng)前是一個垂直棧視圖,但您希望它是一個水平棧視圖。 將 Axis 更改為 Horizontal

現(xiàn)在將 Text Field 從對象庫拖到 Name 標(biāo)簽的右側(cè)。 因為默認(rèn)情況下,標(biāo)簽擁有比文本字段更大的 content hugging priority ,所以標(biāo)簽會擠壓內(nèi)在的內(nèi)容寬度并且文本字段會延伸。 標(biāo)簽和文本字段目前具有相同的內(nèi)容壓縮阻力優(yōu)先級,如果文本字段的文本太長,這將導(dǎo)致模糊的布局。 打開文本字段的大小檢查器,并將其 Horizontal Content Compression Resistance Priority 設(shè)置為 749。這將確保文本字段的文本將在必要時被截斷,而不是標(biāo)簽。

棧視圖間隔

標(biāo)簽和文本框看起來有點(diǎn)小,因為它們之間沒有間隔。 棧視圖允許您自定義 item 之間的間隔。

選擇水平棧視圖并打開它的屬性檢查器。 改變 Spacing8。 注意,文本字段收縮以適應(yīng)間隔,因為它對壓縮的抵抗力比標(biāo)簽要小。

SerialValue 標(biāo)簽重復(fù)以下步驟:

  1. 選擇標(biāo)簽,然后單擊

    圖標(biāo)。

  2. 將堆棧視圖更改為水平(horizontal)棧視圖。
  3. Text field 拖到水平棧視圖上,將其 horizontal content compression resistance priority 改為749
  4. 更新堆棧視圖,Spacing8 點(diǎn)。

你會想要對界面進(jìn)行另外的調(diào)整:垂直棧視圖需要一些間距。 Date Created 標(biāo)簽應(yīng)具有中心文本對齊方式。 NameSerialValue 標(biāo)簽的寬度應(yīng)該相同。

選擇垂直棧視圖,打開其屬性檢查器,并將 Spacing 更新為 8 點(diǎn)。 然后選擇 Date Created 的標(biāo)簽,打開其屬性檢查器,并將 Alignment 更改為居中。 這解決了前兩個問題。

雖然棧視圖大大減少了您需要添加到界面中的約束數(shù)量,但有一些約束仍然很重要。 在界面上,由于標(biāo)簽寬度的差異,文本字段的前部不對齊。 (英文中的區(qū)別不是非常明顯,但當(dāng)本地化為其他語言時,這種差異變得更加顯著)為了解決這個問題,您將在三個文本字段之間添加前部約束。

右鍵選中 Name 文本字段拖動到 Seria 文本字段,并選擇 Leading。 然后對 Serial 文本字段和 Value 文本字段執(zhí)行相同操作。 完成的界面如圖13.8所示。

圖13.8最終棧視圖界面

棧視圖會使你在短時間內(nèi)就能創(chuàng)建非常豐富的界面,比您在使用手動配置約束需要的時間要短。 約束仍然要被添加,但是它們是由堆棧視圖本身去管理,而不是你。 棧視圖允許您在運(yùn)行時具有非常動態(tài)的界面。 您可以通過使用 addArrangedSubview(_ :)insertArrangedSubview(_:at :)removeArrangedSubview(_ :) 來添加和刪除視圖。 您還可以在棧視圖中的視圖上切換 hidden 屬性。 堆棧視圖將通過該值自動布局其內(nèi)容。

Segues

大多數(shù)iOS應(yīng)用程序都有許多視圖控制器,用戶可以在其中進(jìn)行導(dǎo)航。故事板允許您將這些交互設(shè)置為 segues,而無需編寫代碼。

一個 segue 能將另一個視圖控制器的視圖移到屏幕上,并由 UIStoryboardSegue 的一個實例來表示。 每個 segue 都有一個 樣式(style)、一個 動作項(action item) 和一個 標(biāo)識符(identifier)。 segue 的樣式?jīng)Q定了視圖控制器的呈現(xiàn)方式。 動作項是在故事板文件中觸發(fā) segue 的視圖對象,如按鈕、表視圖單元或其他 UIControl。 標(biāo)識符用于以編程方式訪問 segue。 當(dāng)您想要觸發(fā)一個不是來自某個動作項的 segue 時,這是很有用的,比如抖動或其他無法在故事板文件中設(shè)置的界面元素。

讓我們從一個 show segue開始。 show segue 顯示一個視圖控制器,這取決于它顯示的上下文。 segue 將在表視圖控制器和新視圖控制器之間。 動作項將是表視圖的 cell; 點(diǎn)擊一個 cell 將會顯示視圖控制器。

Main.storyboard 中,在 Items View Controller 上選擇 ItemCell 的 prototype cell。 右鍵從 cell 拖動到上一節(jié)中新設(shè)置的視圖控制器。 (確保您是從 cell 拖動而不是表視圖!)接著將出現(xiàn)一個黑色面板,其中列出了可能的樣式。 從 Selection Segue 部分中選擇 Show(圖13.9)。

圖13.9 設(shè)置一個 show segue

注意從表視圖控制器到新視圖控制器的箭頭。 這是一個 segue。 圓圈中的圖標(biāo)告訴你這個 segue 是一個 show segue,每個 segue 都有一個唯一的圖標(biāo)。

構(gòu)建并運(yùn)行應(yīng)用程序。 點(diǎn)擊 cell,新的視圖控制器將從屏幕底部向上滑動。 (從底部滑出是以模態(tài)方式呈現(xiàn)視圖控制器時的默認(rèn)行為。)

到現(xiàn)在為止還挺好! 但目前有兩個問題:視圖控制器不顯示所選 Item 的信息,并且無法關(guān)閉視圖控制器以返回到 ItemsViewController。 您將在下一節(jié)中解決第一個問題,在第14章中解決第二個問題。

掛鉤內(nèi)容

要顯示所選 Item 的信息,您將需要創(chuàng)建一個新的 UIViewController 子類。

創(chuàng)建一個新的 Swift文件 并將其命名為 DetailViewController。 打開 DetailViewController.swift 并聲明一個名為 DetailViewController 的新 UIViewController 子類。

import Foundation
import UIKit

class DetailViewController: UIViewController {

}

因為您需要能夠訪問您在運(yùn)行時創(chuàng)建的子視圖,DetailViewController 需要它們的 outlet。 該計劃是向 DetailViewController 添加四個新 outlet,然后進(jìn)行連接。 在以前的練習(xí)中,您已經(jīng)做了兩個不同的步驟:首先,您在 Swift 文件中添加 outlet,然后在故事板文件中進(jìn)行了連接。 其實您可以使用助理編輯器一次完成。

打開 DetailViewController.swift,在項目導(dǎo)航器中選擇 Main.stroyboard。 這將打開在 DetailViewController.swift 旁邊的助理編輯器中的文件。 (您可以通過單擊工作區(qū)頂部的 Editor 控件中的中間按鈕來切換助理編輯器,顯示助理編輯器的快捷方式為 Command-Option-Return,返回標(biāo)準(zhǔn)編輯器的快捷方式為 Command-Return。)

你的窗口已經(jīng)變得有些凌亂。 讓我們做一些暫時的修改。 通過單擊工作區(qū)頂部的 View控件中的左側(cè)按鈕隱藏導(dǎo)航區(qū) (此快捷方式為 Command-0)。 然后,通過單擊編輯器左下角的切換按鈕(右上角左邊那三個按鈕的中間的那個顯示像兩個圓交叉的那個按鈕),在 Interface Builder 中隱藏文檔輪廓。 您的工作區(qū)現(xiàn)在應(yīng)如圖13.10所示。

圖13.10 布局工作區(qū)

在連接 outlet 之前,您需要告知詳細(xì)界面應(yīng)該與 DetailViewController 相關(guān)聯(lián)。 在畫布上選擇 View Controller 并打開其身份檢查器。 將 Class 更改為 DetailViewController(圖13.11)。

圖13.11 設(shè)置視圖控制器類

UITextField 的三個實例和 UILabel 的底部實例將在 DetailViewController 中顯示。 右鍵選中從 Name 標(biāo)簽旁邊的 UITextField 拖動到 DetailViewController.swift的頂部,如圖13.12所示。

圖13.12 從故事板拖動到源文件

放手后會出現(xiàn)彈出窗口。 在 Name 字段中輸入 nameField,確保 Storage 設(shè)置為 Strong,然后單擊 Connect(圖13.13)。

圖13.13 自動生成outlet并進(jìn)行連接

這將在 DetailViewController 中創(chuàng)建一個名為 nameField 的類型為 UITextField@IBOutlet 屬性。

此外,這個 UITextField 已經(jīng)連接到 DetailViewControllernameField outlet。 您可以通過單擊 Detail View Controller 查看連接來驗證這一點(diǎn)。 還要注意,將鼠標(biāo)懸停在面板上的 nameField 連接之上,將會顯示您連接的 UITextField

以相同的方式創(chuàng)建其他三個 outlet,并將其命名,如圖13.14所示。

圖13.14連接圖

進(jìn)行連接后,DetailViewController.swift 應(yīng)該如下所示:

import UIKit

class DetailViewController: UIViewController {

??@IBOutlet var nameField: UITextField!
??@IBOutlet var serialNumberField: UITextField!
??@IBOutlet var valueField: UITextField!
??@IBOutlet var dateLabel: UILabel!

}

如果您的文件看起來不一樣,那表明您的 outlet 連接不正確。 解決您的文件與上述代碼之間的任何差異的三個步驟:首先,通過 右鍵——拖動 流程并再次進(jìn)行連接,直到您在 DetailViewController.swift 中顯示上述四行。 第二,刪除創(chuàng)建的任何錯誤代碼(如非屬性方法聲明或?qū)傩裕?最后,檢查故事板文件中的任何不良連接——在 Main.storyboard 中,右擊 Detail View Controller*。 如果任何連接旁邊都有黃色警告標(biāo)志,請點(diǎn)擊這些連接旁邊的x` 圖標(biāo)以將其斷開連接。

確保界面文件中沒有錯誤的連接很重要。 當(dāng)更改屬性名稱但不更新界面文件中的連接或完全刪除屬性但不從界面文件中刪除時,通常會發(fā)生連接錯誤。 無論哪種方式,連接錯誤都會導(dǎo)致應(yīng)用程序在加載界面文件時崩潰。

連接完成后,您可以關(guān)閉助理編輯器,并返回到僅查看 DetailViewController.swift

DetailViewController 將持有對正在顯示的 Item 的引用。 加載視圖后,您將會將每個文本字段上的文本從 Item 實例中設(shè)置為適當(dāng)?shù)闹怠?/p>

DetailViewController.swift 中,為 Item 實例添加一個屬性,并重寫 viewWillAppear(_ :) 來設(shè)置界面。

class DetailViewController: UIViewController {

??@IBOutlet var nameField: UITextField!
??@IBOutlet var serialNumberField: UITextField!
??@IBOutlet var valueField: UITextField!
??@IBOutlet var dateLabel: UILabel!

??var item: Item!

??override func viewWillAppear(_ animated: Bool) {
????super.viewWillAppear(animated)

????nameField.text = item.name
????serialNumberField.text = item.serialNumber
????valueField.text = "\(item.valueInDollars)"
????dateLabel.text = "\(item.dateCreated)"
??}
}

這是有用的,我們最好使用格式化器而不是使用字符串插值來打印出 valueInDollarsdateCreated。 您在第 4 章中使用了 NumberFormatter 的實例。您將在此使用另一個實例,以及 DateFormatter 的實例來格式化 dateCreated

NumberFormatterDateFormatter 的實例添加到 DetailViewController。 在 viewWillAppear(_ :) 中使用這些格式化器來格式化 valueInDollarsdateCreated

var item: Item!

let numberFormatter: NumberFormatter = {
??let formatter = NumberFormatter()formatter.numberStyle = .decimal
??formatter.minimumFractionDigits = 2
??formatter.maximumFractionDigits = 2
??return formatter
}()

let dateFormatter: DateFormatter = {
??let formatter = DateFormatter()
??formatter.dateStyle = .medium
??formatter.timeStyle = .none
??return formatter
}()

override func viewWillAppear(_ animated: Bool) {
??super.viewWillAppear(animated)

??nameField.text = item.name
??serialNumberField.text = item.serialNumber
??valueField.text = "\(item.valueInDollars)"
??dateLabel.text = "\(item.dateCreated)"
??valueField.text = numberFormatter.string(from: NSNumber(value: item.valueInDollars))
??dateLabel.text = dateFormatter.string(from: item.dateCreated)
}

傳遞數(shù)據(jù)

當(dāng)表視圖中的一行被點(diǎn)擊時,您需要一個告訴 DetailViewController 當(dāng)前選擇了哪個 Item 的方法。 每當(dāng)觸發(fā) segue 時,都會在啟動 segue 的視圖控制器上調(diào)用 prepare(for:sender :) 方法。 該方法有兩個參數(shù):UIStoryboardSegue——它提供有關(guān)哪個 segue 正在發(fā)生的信息,以及 發(fā)送者(sender)——它是觸發(fā) segue 的對象(例如 UITableViewCellUIButton)。

UIStoryboardSegue 為您提供了三條信息:源視圖控制器(segue 起始位置),目標(biāo)視圖控制器(segue 結(jié)束位置)以及 segue 的標(biāo)識符。 標(biāo)識符可以區(qū)分分隔符。 讓我們給 segue 一個有用的標(biāo)識符。

再次打開 Main.storyboard。 通過單擊兩個視圖控制器之間的箭頭并打開屬性檢查器來選擇 show segue。 對于 identifier,輸入 showItem(圖13.15)。

圖13.15 Segue 標(biāo)識符

隨著學(xué)習(xí)的深入,你現(xiàn)在可以傳遞你的 Item 實例。 打開 ItemsViewController.swift并實現(xiàn) prepare(for:sender :)

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
??// If the triggered segue is the "showItem" segue
??switch segue.identifier {
??case "showItem"?:
????// Figure out which row was just tapped
????if let row = tableView.indexPathForSelectedRow?.row {

??????// Get the item associated with this row and pass it along
??????let item = itemStore.allItems[row]
??????let detailViewController = segue.destination as! DetailViewController
??????detailViewController.item = item
????}
??default:
????preconditionFailure("Unexpected segue identifier.")
??}
}

您在第2章中了解了 switch 語句。這里,您正在使用它來切換可能的 segue 標(biāo)識符。 因為 segue 的 identifier 是一個可選的String, 因為其后面加上了?。 默認(rèn)塊使用 preconditionFailure(_ :) 函數(shù)捕獲任何意外的 segue 標(biāo)識符并使應(yīng)用程序崩潰。 如果程序員忘記給出一個標(biāo)識符,或者如果在某個地方出現(xiàn)了一個帶有 segue 標(biāo)識符的錯字,那就會出現(xiàn)這種情況。 任何一種情況都是程序員的錯誤,使用 preconditionFailure(_ :) 可以幫助您更快地識別這些問題。

構(gòu)建并運(yùn)行應(yīng)用程序。 點(diǎn)擊一行,DetailViewController 將在屏幕上滑動,顯示該 item 的詳細(xì)信息。 (您將在第14章中修復(fù)無法返回 ItemsViewController 的問題)

許多新加入iOS的程序員都在與視圖控制器之間如何傳遞數(shù)據(jù)進(jìn)行斗爭。 將根視圖控制器中的所有數(shù)據(jù)并將數(shù)據(jù)的子集傳遞給下一個 UIViewController (就像本章所做的那樣) 是一種簡潔高效的方法。

青銅挑戰(zhàn):更多棧視圖

棧視圖對 QuizWorldTrotter 也很好用。 使用 UIStackView 更新這兩個應(yīng)用程序。

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

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