Flutter滾動Widget

列表是移動端經(jīng)常使用的一種視圖展示方式蝶棋,在Flutter中提供了ListView和GridView。

一忽妒、ListView組件

移動端數(shù)據(jù)量比較大時玩裙,我們都是通過列表來進行展示的兼贸,比如商品數(shù)據(jù)、聊天列表吃溅、通信錄溶诞、朋友圈等。在iOS中决侈,我們可以通過UITableView來實現(xiàn)螺垢。
ListView可以沿一個方向(垂直或水平方向,默認(rèn)是垂直方向)來排列其所有子Widget赖歌。
一種最簡單的使用方式是直接將所有需要排列的子Widget放在ListView的children屬性中即可枉圃。

1、ListView的使用庐冯。

為了讓文字之間有一些間距孽亲,我使用了Padding Widget。

class MyHomeBody extends StatelessWidget {
  final TextStyle textStyle = TextStyle(fontSize: 20, color: Colors.redAccent);

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text("人的一切痛苦展父,本質(zhì)上都是對自己無能的憤怒返劲。", style: textStyle),
        ),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text("人活在世界上,不可以有偏差栖茉;而且多少要費點勁兒篮绿,才能把自己保持到理性的軌道上。", style: textStyle),
        ),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text("我活在世上吕漂,無非想要明白些道理搔耕,遇見些有趣的事。", style: textStyle),
        )
      ],
    );
  }
}

2痰娱、ListTile的使用

使用場景:在開發(fā)中弃榨,我們經(jīng)常見到一種列表,有一個圖標(biāo)或圖片(Icon)梨睁,有一個標(biāo)題(Title)鲸睛,有一個子標(biāo)題(Subtitle),還有尾部一個圖標(biāo)(Icon)坡贺。

class MyHomeBody extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        ListTile(
          leading: Icon(Icons.people, size: 36,),
          title: Text("聯(lián)系人"),
          subtitle: Text("聯(lián)系人信息"),
          trailing: Icon(Icons.arrow_forward_ios),
        ),
        ListTile(
          leading: Icon(Icons.email, size: 36,),
          title: Text("郵箱"),
          subtitle: Text("郵箱地址信息"),
          trailing: Icon(Icons.arrow_forward_ios),
        ),
        ListTile(
          leading: Icon(Icons.message, size: 36,),
          title: Text("消息"),
          subtitle: Text("消息詳情信息"),
          trailing: Icon(Icons.arrow_forward_ios),
        ),
        ListTile(
          leading: Icon(Icons.map, size: 36,),
          title: Text("地址"),
          subtitle: Text("地址詳情信息"),
          trailing: Icon(Icons.arrow_forward_ios),
        )
      ],
    );
  }
}

我們可以通過設(shè)置 scrollDirection 參數(shù)來控制視圖的滾動方向官辈。
這里需要注意,我們需要給Container設(shè)置width遍坟,否則它是沒有寬度的拳亿,就不能正常顯示。
或者我們也可以給ListView設(shè)置一個itemExtent愿伴,該屬性會設(shè)置滾動方向上每個item所占據(jù)的寬度肺魁。

class MyHomeBody extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return ListView(
      scrollDirection: Axis.horizontal,
      itemExtent: 200,
      children: <Widget>[
        Container(color: Colors.red, width: 200),
        Container(color: Colors.green, width: 200),
        Container(color: Colors.blue, width: 200),
        Container(color: Colors.purple, width: 200),
        Container(color: Colors.orange, width: 200),
      ],
    );
  }
}
3、ListView.build
3.1 ListView的問題:

通過構(gòu)造函數(shù)中的children傳入所有的子Widget有一個問題:默認(rèn)會創(chuàng)建出所有的子Widget隔节。
但是對于用戶來說鹅经,一次性構(gòu)建出所有的Widget并不會有什么差異寂呛,但是對于我們的程序來說會產(chǎn)生性能問題,而且會增加首屏的渲染時間瘾晃。
我們可以ListView.build來構(gòu)建子Widget贷痪,提供性能。

3.2 ListView.build使用場景:

ListView.build適用于子Widget比較多的場景蹦误,該構(gòu)造函數(shù)將創(chuàng)建子Widget交給了一個抽象的方法劫拢,交給ListView進行管理,ListView會在真正需要的時候去創(chuàng)建子Widget强胰,而不是一開始就全部初始化好舱沧。
該方法有兩個重要參數(shù):
a、itemBuilder:列表項創(chuàng)建的方法哪廓。當(dāng)列表滾動到對應(yīng)位置的時候狗唉,ListView會自動調(diào)用該方法來創(chuàng)建對應(yīng)的子Widget初烘。類型是IndexedWidgetBuilder涡真,是一個函數(shù)類型。
b肾筐、itemCount:表示列表項的數(shù)量哆料,如果為空,則表示ListView為無限列表吗铐。

class MyHomeBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: 100,
      itemExtent: 80,
      itemBuilder: (BuildContext context, int index) {
        return ListTile(title: Text("標(biāo)題$index"), subtitle: Text("詳情內(nèi)容$index"));
      }
    );
  }
}
3.3 ListView.build動態(tài)數(shù)據(jù)

思考:這個時候是否依然可以使用StatelessWidget:
答案:不可以东亦,因為當(dāng)前我們的數(shù)據(jù)是異步加載的,剛開始界面并不會展示數(shù)據(jù)(沒有數(shù)據(jù))唬渗,后面從JSON中加載出來數(shù)據(jù)(有數(shù)據(jù))后典阵,再次展示加載的數(shù)據(jù)。
這里是有狀態(tài)的變化的镊逝,從無數(shù)據(jù)壮啊,到有數(shù)據(jù)的變化。
這個時候撑蒜,我們需要使用StatefulWidget來管理組件歹啼。

3.4 ListView.separated

ListView.separated可以生成列表項之間的分割器,它除了比ListView.builder多了一個separatorBuilder參數(shù)座菠,該參數(shù)是一個分割器生成器狸眼。
實現(xiàn)奇偶行分割線不同的顏色:

class MySeparatedDemo extends StatelessWidget {
  Divider blueColor = Divider(color: Colors.blue);
  Divider redColor = Divider(color: Colors.red);

  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          leading: Icon(Icons.people),
          title: Text("聯(lián)系人${index+1}"),
          subtitle: Text("聯(lián)系人電話${index+1}"),
        );
      },
      separatorBuilder: (BuildContext context, int index) {
        return index % 2 == 0 ? redColor : blueColor;
      },
      itemCount: 100
    );
  }
}

二、GridView組件

GridView用于展示多列的展示浴滴,在開發(fā)中也非常常見拓萌,比如直播App中的主播列表、電商中的商品列表等等升略。iOS中類似的控件為UICollectionView司志。

1甜紫、GridView構(gòu)造函數(shù)

一種使用GridView的方式就是使用構(gòu)造函數(shù)來創(chuàng)建,和ListView對比有一個特殊的參數(shù):gridDelegate 骂远, 它用于控制交叉軸的item數(shù)量或者寬度囚霸,需要傳入的類型是SliverGridDelegate,但是它是一個抽象類激才,所以我們需要傳入它的子類:SliverGridDelegateWithFixedCrossAxisCount

SliverGridDelegateWithFixedCrossAxisCount({
  @required double crossAxisCount, // 交叉軸的item個數(shù)
  double mainAxisSpacing = 0.0, // 主軸的間距
  double crossAxisSpacing = 0.0, // 交叉軸的間距
  double childAspectRatio = 1.0, // 子Widget的寬高比
})

代碼:

class MyGridCountDemo extends StatelessWidget {

 List<Widget> getGridWidgets() {
   return List.generate(100, (index) {
     return Container(
       color: Colors.purple,
       alignment: Alignment(0, 0),
       child: Text("item$index", style: TextStyle(fontSize: 20, color: Colors.white)),
     );
   });
 }

 @override
 Widget build(BuildContext context) {
   return GridView(
     gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
       crossAxisCount: 3,
       mainAxisSpacing: 10,
       crossAxisSpacing: 10,
       childAspectRatio: 1.0
     ),
     children: getGridWidgets(),
   );
 }
}

SliverGridDelegateWithMaxCrossAxisExtent:

SliverGridDelegateWithMaxCrossAxisExtent({
  double maxCrossAxisExtent, // 交叉軸的item寬度
  double mainAxisSpacing = 0.0, // 主軸的間距
  double crossAxisSpacing = 0.0, // 交叉軸的間距
  double childAspectRatio = 1.0, // 子Widget的寬高比
})

代碼:

class MyGridExtentDemo extends StatelessWidget {

  List<Widget> getGridWidgets() {
    return List.generate(100, (index) {
      return Container(
        color: Colors.purple,
        alignment: Alignment(0, 0),
        child: Text("item$index", style: TextStyle(fontSize: 20, color: Colors.white)),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return GridView(
      gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 150,
        mainAxisSpacing: 10,
        crossAxisSpacing: 10,
        childAspectRatio: 1.0
      ),
      children: getGridWidgets(),
    );
  }
}

這兩種方式也可以不設(shè)置delegate拓型,可以分別使用:GridView.count構(gòu)造函數(shù)和GridView.extent構(gòu)造函數(shù)實現(xiàn)相同的效果。

2瘸恼、GridView.build

GridView.build和ListView一樣劣挫,使用構(gòu)造函數(shù)會一次性創(chuàng)建所有的子Widget,會帶來性能問題东帅,所以我們可以使用GridView.build來交給GridView自己管理需要創(chuàng)建的子Widget压固。

class _GridViewBuildDemoState extends State<GridViewBuildDemo> {
  List<Anchor> anchors = [];

  @override
  void initState() {
    getAnchors().then((anchors) {
      setState(() {
        this.anchors = anchors;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: GridView.builder(
        shrinkWrap: true,
        physics: ClampingScrollPhysics(),
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 2,
          mainAxisSpacing: 10,
          crossAxisSpacing: 10,
          childAspectRatio: 1.2
        ),
        itemCount: anchors.length,
        itemBuilder: (BuildContext context, int index) {
          return Container(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Image.network(anchors[index].imageUrl),
                SizedBox(height: 5),
                Text(anchors[index].nickname, style: TextStyle(fontSize: 16),),
                Text(anchors[index].roomName, maxLines: 1, overflow: TextOverflow.ellipsis,)
              ],
            ),
          );
        }
      ),
    );
  }
}

三、Sliver

場景:一個滑動的視圖中包括一個標(biāo)題視圖(HeaderView)靠闭,一個列表視圖(ListView)帐我,一個網(wǎng)格視圖(GridView)。我們怎么可以讓它們做到統(tǒng)一的滑動效果呢愧膀?
使用前面的滾動是很難做到的拦键。Flutter中有一個可以完成這樣滾動效果的Widget:CustomScrollView,可以統(tǒng)一管理多個滾動視圖檩淋。
在CustomScrollView中芬为,每一個獨立的,可滾動的Widget被稱之為Sliver蟀悦。
補充:Sliver可以翻譯成裂片媚朦、薄片,你可以將每一個獨立的滾動視圖當(dāng)做一個小裂片日戈。

3.1 Slivers的基本使用

因為我們需要把很多的Sliver放在一個CustomScrollView中询张,所以CustomScrollView有一個slivers屬性,里面讓我們放對應(yīng)的一些Sliver:

  • SliverList:類似于我們之前使用過的ListView涎拉;
  • SliverFixedExtentList:類似于SliverList只是可以設(shè)置滾動的高度瑞侮;
  • SliverGrid:類似于我們之前使用過的GridView;
  • SliverPadding:設(shè)置Sliver的內(nèi)邊距鼓拧,因為可能要單獨給Sliver設(shè)置內(nèi)邊距半火;
  • SliverAppBar:添加一個AppBar,通常用來作為CustomScrollView的HeaderView季俩;
  • SliverSafeArea:設(shè)置內(nèi)容顯示在安全區(qū)域(比如不讓齊劉海擋住我們的內(nèi)容
    SliverGrid+SliverPadding+SliverSafeArea的組合:
class HomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: <Widget>[
        SliverSafeArea(
          sliver: SliverPadding(
            padding: EdgeInsets.all(8),
            sliver: SliverGrid(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                crossAxisSpacing: 8,
                mainAxisSpacing: 8,
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    alignment: Alignment(0, 0),
                    color: Colors.orange,
                    child: Text("item$index"),
                  );
                },
                childCount: 20
              ),
            ),
          ),
        )
      ],
    );
  }
}
3.2 Slivers的組合使用

SliverAppBar+SliverGrid+SliverFixedExtentList做出如下界面:

class HomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return showCustomScrollView();
  }

  Widget showCustomScrollView() {
    return new CustomScrollView(
      slivers: <Widget>[
        const SliverAppBar(
          expandedHeight: 250.0,
          flexibleSpace: FlexibleSpaceBar(
            title: Text('Coderwhy Demo'),
            background: Image(
              image: NetworkImage(
                "https://tva1.sinaimg.cn/large/006y8mN6gy1g72j6nk1d4j30u00k0n0j.jpg",
              ),
              fit: BoxFit.cover,
            ),
          ),
        ),
        new SliverGrid(
          gridDelegate: new SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: 200.0,
            mainAxisSpacing: 10.0,
            crossAxisSpacing: 10.0,
            childAspectRatio: 4.0,
          ),
          delegate: new SliverChildBuilderDelegate(
                (BuildContext context, int index) {
              return new Container(
                alignment: Alignment.center,
                color: Colors.teal[100 * (index % 9)],
                child: new Text('grid item $index'),
              );
            },
            childCount: 10,
          ),
        ),
        SliverFixedExtentList(
          itemExtent: 50.0,
          delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
              return new Container(
                alignment: Alignment.center,
                color: Colors.lightBlue[100 * (index % 9)],
                child: new Text('list item $index'),
              );
            },
            childCount: 20
          ),
        ),
      ],
    );
  }
}

四钮糖、監(jiān)聽滾動視圖

對于滾動的視圖,我們經(jīng)常需要監(jiān)聽它的一些滾動事件,在監(jiān)聽到的時候去做對應(yīng)的一些事情店归。eg:
a阎抒、視圖滾動到底部時,我們可能希望做上拉加載更多消痛;
b且叁、滾動到一定位置時顯示一個回到頂部的按鈕,點擊回到頂部的按鈕秩伞,回到頂部逞带;
c、監(jiān)聽滾動什么時候開始纱新,什么時候結(jié)束展氓;
在Flutter中監(jiān)聽滾動相關(guān)的內(nèi)容由兩部分組成:ScrollController和ScrollNotification。

4.1 ScrollController

在Flutter中脸爱,Widget并不是最終渲染到屏幕上的元素(真正渲染的是RenderObject)遇汞,因此通常這種監(jiān)聽事件以及相關(guān)的信息并不能直接從Widget中獲取,而是必須通過對應(yīng)的Widget的Controller來實現(xiàn)簿废。
ListView空入、GridView的組件控制器是ScrollController,我們可以通過它來獲取視圖的滾動信息捏鱼,并且可以調(diào)用里面的方法來更新視圖的滾動位置执庐。
另外酪耕,通常情況下导梆,我們會根據(jù)滾動的位置來改變一些Widget的狀態(tài)信息,所以ScrollController通常會和StatefulWidget一起來使用迂烁,并且會在其中控制它的初始化看尼、監(jiān)聽、銷毀等事件盟步。
我們來做一個案例藏斩,當(dāng)滾動到1000位置的時候,顯示一個回到頂部的按鈕:
jumpTo(double offset)却盘、animateTo(double offset,...):這兩個方法用于跳轉(zhuǎn)到指定的位置狰域,它們不同之處在于,后者在跳轉(zhuǎn)時會執(zhí)行一個動畫黄橘,而前者不會兆览。
ScrollController間接繼承自Listenable,我們可以根據(jù)ScrollController來監(jiān)聽滾動事件塞关。

class MyHomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  ScrollController _controller;
  bool _isShowTop = false;
  
  @override
  void initState() {
    // 初始化ScrollController
    _controller = ScrollController();
    
    // 監(jiān)聽滾動
    _controller.addListener(() {
      var tempSsShowTop = _controller.offset >= 1000;
      if (tempSsShowTop != _isShowTop) {
        setState(() {
          _isShowTop = tempSsShowTop;
        });
      }
    });
    
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("ListView展示"),
      ),
      body: ListView.builder(
        itemCount: 100,
        itemExtent: 60,
        controller: _controller,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(title: Text("item$index"));
        }
      ),
      floatingActionButton: !_isShowTop ? null : FloatingActionButton(
        child: Icon(Icons.arrow_upward),
        onPressed: () {
          _controller.animateTo(0, duration: Duration(milliseconds: 1000), curve: Curves.ease);
        },
      ),
    );
  }
}
4.2 NotificationListener

場景:監(jiān)聽什么時候開始滾動抬探,什么時候結(jié)束滾動,這個時候我們可以通過NotificationListener帆赢。
NotificationListener是一個Widget小压,模板參數(shù) T 是想監(jiān)聽的通知類型线梗,如果省略,則所有類型通知都會被監(jiān)聽怠益,如果指定特定類型仪搔,則只有該類型的通知會被監(jiān)聽。
NotificationListener需要一個onNotification回調(diào)函數(shù)蜻牢,用于實現(xiàn)監(jiān)聽處理邏輯僻造。
該回調(diào)可以返回一個布爾值,代表是否阻止該事件繼續(xù)向上冒泡孩饼,如果為true時髓削,則冒泡終止,事件停止向上傳播镀娶,如果不返回或者返回值為false 時立膛,則冒泡繼續(xù)。

案例: 列表滾動, 并且在中間顯示滾動進度:

class MyHomeNotificationDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyHomeNotificationDemoState();
}

class MyHomeNotificationDemoState extends State<MyHomeNotificationDemo> {
  int _progress = 0;

  @override
  Widget build(BuildContext context) {
    return NotificationListener(
      onNotification: (ScrollNotification notification) {
        // 1.判斷監(jiān)聽事件的類型
        if (notification is ScrollStartNotification) {
          print("開始滾動.....");
        } else if (notification is ScrollUpdateNotification) {
          // 當(dāng)前滾動的位置和總長度
          final currentPixel = notification.metrics.pixels;
          final totalPixel = notification.metrics.maxScrollExtent;
          double progress = currentPixel / totalPixel;
          setState(() {
            _progress = (progress * 100).toInt();
          });
          print("正在滾動:${notification.metrics.pixels} - ${notification.metrics.maxScrollExtent}");
        } else if (notification is ScrollEndNotification) {
          print("結(jié)束滾動....");
        }
        return false;
      },
      child: Stack(
        alignment: Alignment(.9, .9),
        children: <Widget>[
          ListView.builder(
            itemCount: 100,
            itemExtent: 60,
            itemBuilder: (BuildContext context, int index) {
              return ListTile(title: Text("item$index"));
            }
          ),
          CircleAvatar(
            radius: 30,
            child: Text("$_progress%"),
            backgroundColor: Colors.black54,
          )
        ],
      ),
    );
  }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末梯码,一起剝皮案震驚了整個濱河市宝泵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轩娶,老刑警劉巖儿奶,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡厅目,警方通過查閱死者的電腦和手機虽风,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓤鼻,“玉大人,你說我怎么就攤上這事贤重〔绲唬” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵并蝗,是天一觀的道長祭犯。 經(jīng)常有香客問我,道長滚停,這世上最難降的妖魔是什么沃粗? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮铐刘,結(jié)果婚禮上陪每,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好檩禾,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布挂签。 她就那樣靜靜地躺著,像睡著了一般盼产。 火紅的嫁衣襯著肌膚如雪饵婆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天戏售,我揣著相機與錄音侨核,去河邊找鬼。 笑死灌灾,一個胖子當(dāng)著我的面吹牛搓译,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锋喜,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼些己,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嘿般?” 一聲冷哼從身側(cè)響起段标,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炉奴,沒想到半個月后逼庞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡瞻赶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年赛糟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片共耍。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡虑灰,死狀恐怖吨瞎,靈堂內(nèi)的尸體忽然破棺而出痹兜,到底是詐尸還是另有隱情,我是刑警寧澤颤诀,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布字旭,位于F島的核電站,受9級特大地震影響崖叫,放射性物質(zhì)發(fā)生泄漏遗淳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一心傀、第九天 我趴在偏房一處隱蔽的房頂上張望屈暗。 院中可真熱鬧,春花似錦、人聲如沸养叛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弃甥。三九已至爽室,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淆攻,已是汗流浹背阔墩。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瓶珊,地道東北人啸箫。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像伞芹,于是被迫代替她去往敵國和親筐高。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354