Flutter-flutter基础之组件基础(八)

一、Stack Widget

Stack Widget 可以用来设置多个子 Widget ,这些子 Widget 以堆叠的方式进行排列。Stack 的子 Widget 可以分为已定位和未定位,定位使用 Positioned Widget 配合 Stack 一起使用。Stack 本身的大小将包含所有未定位的子 Widget ,这些子 Widget 根据对齐方式定位(在从左到右的环境中,默认为左上角,在从右到左的环境中,默认为右上角)。然后根据已定位的子 Widget 的上、右、下、左的属性相对于 Stack 放置它们。

Stack 的构造方法如下:

Stack({
  Key key,
  //AlignmentGeometry类型可选命名参数,如何对齐Stack中未定位和部分定位的子Widget
  //使用AlignmentDirectional
  this.alignment = AlignmentDirectional.topStart,
  //TextDirection类型可选命名参数,文本对齐方向设置
  this.textDirection,
  //StackFit类型可选命名参数,如何调整Stack中未定位的子Widget
  this.fit = StackFit.loose,
  //Overflow类型可选命名参数,设置溢出部分如何剪裁
  this.overflow = Overflow.clip,
  //List<Widget>类型可选命名参数,要显示的Widget
  List<Widget> children = const <Widget>[],
})

AlignmentDirectional 用于设置如何对齐 Stack 中未定位和部分定位的子 Widget 。对于未定位的子 Widget 项彼此相对放置,以使通过对齐确定的点位于同一位置。部分定位的子 Widget 指的是未在特定轴上指定对齐方式的子 Widget ,使用对齐方式来确定应如何在未指定的轴上定位它们。AlignmentDirectional 的构造方法如下:

//两个参数均为double类型
const AlignmentDirectional(this.start, this.y)

可以使用构造方法设置,也可以直接使用提供好的位置静态属性,如下:

/// The top corner on the "start" side.
static const AlignmentDirectional topStart = AlignmentDirectional(-1.0, -1.0);
/// The center point along the top edge.
///
/// Consider using [Alignment.topCenter] instead, as it does not need
/// to be [resolve]d to be used.
static const AlignmentDirectional topCenter = AlignmentDirectional(0.0, -1.0);
/// The top corner on the "end" side.
static const AlignmentDirectional topEnd = AlignmentDirectional(1.0, -1.0);
/// The center point along the "start" edge.
static const AlignmentDirectional centerStart = AlignmentDirectional(-1.0, 0.0);
/// The center point, both horizontally and vertically.
///
/// Consider using [Alignment.center] instead, as it does not need to
/// be [resolve]d to be used.
static const AlignmentDirectional center = AlignmentDirectional(0.0, 0.0);
/// The center point along the "end" edge.
static const AlignmentDirectional centerEnd = AlignmentDirectional(1.0, 0.0);
/// The bottom corner on the "start" side.
static const AlignmentDirectional bottomStart = AlignmentDirectional(-1.0, 1.0);
/// The center point along the bottom edge.
///
/// Consider using [Alignment.bottomCenter] instead, as it does not
/// need to be [resolve]d to be used.
static const AlignmentDirectional bottomCenter = AlignmentDirectional(0.0, 1.0);
/// The bottom corner on the "end" side.
static const AlignmentDirectional bottomEnd = AlignmentDirectional(1.0, 1.0);

位置属性简单易懂,不做中文说明了。AlignmentDirectional 的设置与 TextDirection 是关系的,对于不同的环境方向,AlignmentDirectional 的起始位置也不同。

StackFit 用于设置如何调整Stack中未定位的子 Widget ,其是一个枚举类型值,如下:

enum StackFit {
  //从其父级传递到Stack的约束被放宽了
  //例如:如果Stack具有强制其为350x600的约束,那么这将允许Stack的未定位子Widget
  //具有从0到350的任何宽度和从0到600的任何高度
  loose,

  //从其父级传递到Stack的约束被收紧到允许的最大大小。
  //例如:如果Stack具有宽度在10到100范围内、高度在0到600范围内的松散约束,则Stack中未
  //定位的子级的大小都将为100像素宽、600像素高
  expand,

  //从其父级传递到Stack的约束未修改地传递到未定位的子级
  //例如:如果Stack是行的扩展子级,则水平约束将是紧的,而垂直约束将是松的
  passthrough,
}

Stack 的使用方式如下:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Container(
        width: 500,
        height: 200,
        color: Colors.yellow,
        child:Stack(              //Stack
          alignment: AlignmentDirectional.topStart,
          textDirection: TextDirection.ltr,
          fit: StackFit.loose,
          overflow: Overflow.clip,
          children: <Widget>[
            Image.network("http://www.mwpush.com/uploads/avatar.png"),
            Text("Stack1", style: TextStyle(color: Colors.blue, fontSize: 30),),
            Text("Stack2",style: TextStyle(color: Colors.red, fontSize: 20),),
          ],
        ),
      ),
    );
  }
}

效果如下:


2020324102.jpg

定位 Widget 使用 Positioned ,用于控制 Stack 的子 Widget 的位置。如果一个 Widget 包装在 Positioned 中,那么这个 Widget 就是 Stack 中的一个定位 Widget 。如果单独设置 top 则表示该子 Widget 距离 Stack 顶部的距离,同时设定 topbottom 则子 Widget 会根据设置调整子 Widget 的高度以使其满足顶部和底部的距离,左右也是一样。其中 topbottomheight 只能同时设置其中的两项,另外一项必须为空,如果都为空,则使用 Stackalignment 在垂直方向进行定位。 leftrightwidth 也只能设置其中两项,另外一项必须为空,如果所有都为空,则使用 Stackalignment 在水平方向进行定位。

Positioned 的构造方法如下:

const Positioned({
  Key key,
  //double类型可选命名参数,子Widget底部距离Stack左边的距离
  this.left,
  //double类型可选命名参数,子Widget底部距离Stack顶部的距离
  this.top,
  //double类型可选命名参数,子Widget底部距离Stack右边的距离
  this.right,
  //double类型可选命名参数,子Widget底部距离Stack底部的距离
  this.bottom,
  //double类型可选命名参数,子Widget的宽度
  this.width,
  //double类型可选命名参数,子Widget的高度
  this.height,
  //Widget类型必传参数,要显示的Widget
  @required Widget child,
})

使用方法如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Container(
        width: 500,
        height: 200,
        color: Colors.yellow,
        child:Stack(              //Stack
          alignment: AlignmentDirectional.topStart,
          textDirection: TextDirection.ltr,
          fit: StackFit.loose,
          overflow: Overflow.clip,
          children: <Widget>[
            Image.network("http://www.mwpush.com/uploads/avatar.png"),
            Positioned(             //Positioned
              bottom: 10,
              top: 20,
              left: 120,
              width: 100,
              child: Container(child: Text("Stack1", style: TextStyle(color: Colors.blue, fontSize: 30,), ), color: Colors.red,),
            ),
            Text("Stack2",style: TextStyle(color: Colors.red, fontSize: 20),),
          ],
        ),
      ),
    );
  }
}

效果如下:


2020324208.jpg

二、IndexedStack Widget

Stack 可以显示一组 Widget ,IndexedStack 继承自 Stack ,用于选择性的只显示一组 Widget 中的一个。要显示的 Widget 通过 index 索引设置,编号从 0 开始。IndexedStack 的大小总是和一组 Widget 中的最大的 Widget 一样大。构造方法如下:

IndexedStack({
  Key key,
  //AlignmentGeometry类型可选命名参数,如何对齐Stack中未定位和部分定位的子Widget
  //使用AlignmentDirectional
  AlignmentGeometry alignment = AlignmentDirectional.topStart,
  //TextDirection类型可选命名参数,文本对齐方向设置
  TextDirection textDirection,
  //StackFit类型可选命名参数,如何调整Stack中未定位的子Widget
  StackFit sizing = StackFit.loose,
  //int类型可选参数,要显示的Widget
  this.index = 0,
  //List<Widget>类型可选命名参数,要显示的Widget
  List<Widget> children = const <Widget>[],
}) 

IndexedStack 只比 Stack 多了一个 index 属性,其他属性相同,默认显示 Widget 列中的第一个 Widget ,下标为 0 。IndexedStack 使用如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Container(
        width: 500,
        height: 200,
        color: Colors.yellow,
        child:IndexedStack(              //IndexedStack
          alignment: AlignmentDirectional.topStart,
          textDirection: TextDirection.ltr,
          sizing: StackFit.loose,
          index: 2,       //要显示的Widget的下标
          children: <Widget>[
            Image.network("http://www.mwpush.com/uploads/avatar.png"),
            Positioned(
              bottom: 10,
              top: 20,
              left: 120,
              width: 100,
              child: Container(child: Text("Stack1", style: TextStyle(color: Colors.blue, fontSize: 30,), ), color: Colors.red,),
            ),
            Text("Stack2",style: TextStyle(color: Colors.red, fontSize: 20),),
          ],
        ),
      ),
    );
  }
}

三、SizedBox Widget

SizedBox 是设置固定尺寸的 Widget ,如果设置了宽高,则子 Widget 会被强制为 SizedBox 的尺寸,如果不设置宽高,则 SizedBox 的尺寸将与子 Widget 相同。 如果没有给定子 Widget ,SizedBox 将尝试在给定父对象约束的情况下,将自身的大小调整到尽可能接近指定的高度和宽度。如果高度或宽度为空或未指定,将被视为零。

有以下几个构造方法:

//创建固定尺寸的SizedBox,宽高可以为空,此时表示大小不受限制
const SizedBox({
  Key key, 
  //double类型可选命名参数,设置SizedBox的宽度,子Widget也会具有此宽度
  this.width, 
  //double类型可选命名参数,设置SizedBox的高度,子Widget也会具有此高度
  this.height, 
  //Widget类型可选命名参数,要显示的Widget
  Widget child
})
  
//创建一个将变得与其父级允许一样大的SizedBox,等效于将width和height设置为double.infinity
const SizedBox.expand({
  Key key, 
  //Widget类型可选命名参数,要显示的Widget
  Widget child 
})
 
//创建一个将变得尽可能小的SizeBox
const SizedBox.shrink({ 
  Key key, 
  //Widget类型可选命名参数,要显示的Widget
  Widget child 
})

//创建一个指定尺寸的SizeBox
SizedBox.fromSize({ 
  Key key, 
  //Widget类型可选命名参数,要显示的Widget
  Widget child, 
  //Size类型可选命名参数,设置SizedBox的尺寸,子Widget也具有此尺寸
  Size size
})

使用如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: SizedBox(
          height: 100,
          width: 300,
          child: Container(
            color: Colors.red,
            width: 10,
            height: 20,
          ),
      ),
    );
  }
}

这里的子 Widget 是 Container ,虽然 Container 也设置了宽高,但是没有生效,其宽高与 SizedBox 相同。但是如果子 Widget 不能设置宽高属性,则子 Widget 的大小不会与 SizedBox 设置的相同,但是会受其最大尺寸约束。上述代码效果如下:

2020324330.jpg

四、Flex Widget

Flex 使用一维数组来设置一组子 Widget ,其可以通过设置主轴的方向来控制水平或垂直显示 Widget ,它是上篇文章中介绍过的 RowColumn 的父类。如果在使用前已知要显示的 Widget 的方向,应考虑使用 RowColumn

Flex 是一个不可以滚动的 Widget ,当要显示的 Widget 超过可用范围则会抛出异常。其构造方法如下:

Flex({
  Key key,
  //Axis类型必传参数,设置主轴的方向(垂直或者水平),不设置会抛出异常
  @required this.direction,
  //MainAxisAlignment类型可选命名参数,如何沿着主轴放置子Widget
  this.mainAxisAlignment = MainAxisAlignment.start,
  //MainAxisSize类型可选命名参数,主轴上应占用多少空间,该值传入最大化还是最小化可用空间
  this.mainAxisSize = MainAxisSize.max,
  //CrossAxisAlignment类型可选命名参数,如何沿着次轴放置子Widget
  this.crossAxisAlignment = CrossAxisAlignment.center,
  //TextDirection类型可选命名参数,设置子Widget横向的排列方向,默认为环境方向
  this.textDirection,
  //VerticalDirection类型可选命名参数,设置子Widget纵向的排列顺序以及如何解释垂直方向的开始和结束
  this.verticalDirection = VerticalDirection.down,
  //TextBaseline类型可选命名参数,果根据基线对齐项目,使用哪个基线
  this.textBaseline,
  //List<Widget>类型可选命名参数,要显示的Widgets
  List<Widget> children = const <Widget>[],
})

Axis 用于设置主轴的方向,即要显示的 Widgets 的排列方向,是一个枚举类型值,如下:

enum Axis {
  //水平排列
  horizontal,
  //垂直排列
  vertical,
}

其他属性在上一篇文章做过说明,可查看上篇文章的 Row 部分。 Flex 的使用方式如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Flex(
        direction: Axis.horizontal,
        children: <Widget>[
          Text("Text1"),
          Text("Text2"),
          Text("Text3"),
          Text("Text4"),
          Text("Text5"),
        ],
      ),
    );
  }
}

五、Expanded Widget

Expanded 是用来扩展 RowColumnFlex 的子 Widget ,其作用是按一定比例填充子 Widgets 间的可用空间。如果要扩展多个 Widget ,可以通过设置扩展因子在可用空间进行空间分配。其构造方法如下:

const Expanded({
  Key key,
  //int类型可选命名参数,扩展因子  
  int flex = 1,
  //Widget类型必传参数,要显示的Widget 
  @required Widget child,  
})

使用如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Flex(
        direction: Axis.horizontal,
        children: <Widget>[
          Expanded(
            child: Container(child: Text("Text1"), color: Colors.red, height: 50,),
            flex: 1,
          ),
          Expanded(
            child: Container(child: Text("Text2"), color: Colors.blue, height: 50,),
            flex: 2,
          ),
          Expanded(
            child: Container(child: Text("Text3"), color: Colors.yellow, height: 50,),
            flex: 3,
          ),
        ],
      ),
    );
  }
}

效果如下:


2020324508.jpg

上面的代码中设置了扩展因子,是倍数关系,所以显示的结果宽度也是倍数关系,如果是垂直排列 Widget ,则高度是倍数关系。不设置扩展因子则子 Widget 会平均分配可用空间。也可以单独设置某个子 Widget 的扩展因子。

六、Wrap Widget

Wrap 也可以显示多个子 Widget ,其可以设置排列方向(水平或者垂直)显示 Widgets ,与 RowColumn 的不同之处在于,RowColumn 在可用空间无法显示全部 Widget 时会抛出异常,而 Warp 显示不下时会自动换行。

构造方法如下:

Wrap({
  Key key,
  //Axis类型可选命名参数,设置主轴的方向(垂直或者水平)
  this.direction = Axis.horizontal,
  //WrapAlignment类型可选命名参数,在主轴上如何排列子Widgets
  this.alignment = WrapAlignment.start,
  //double类型可选命名参数,主轴上排列的每个Widget之间的间隙
  this.spacing = 0.0,
  //WrapAlignment类型可选命名参数,!!!没有整明白此参数的作用,使用也没有看到效果
  this.runAlignment = WrapAlignment.start,
  //double类型可选命名参数,如果是横向排列则是每行之间的间距,纵向排列则是每列之间的间距
  this.runSpacing = 0.0,
  //WrapCrossAlignment类型可选命名参数,如何沿着次轴放置子Widget
  this.crossAxisAlignment = WrapCrossAlignment.start,
  //TextDirection类型可选命名参数,设置子Widget横向的排列方向,默认为环境方向
  this.textDirection,
  //VerticalDirection类型可选命名参数,设置子Widget纵向的排列顺序以及如何解释垂直方向的开始和结束
  this.verticalDirection = VerticalDirection.down,
  //List<Widget>类型可选命名参数,要显示的Widgets
  List<Widget> children = const <Widget>[],
})

使用如下

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Container(
        color: Colors.amber,
        child: Wrap(                        //Wrap
          direction: Axis.horizontal,
          textDirection: TextDirection.ltr,
          alignment: WrapAlignment.center,
          crossAxisAlignment: WrapCrossAlignment.end,
          spacing: 10,
          runSpacing: 20,
          runAlignment: WrapAlignment.center,

          children: <Widget>[
            Container(child: Text("Text1"), color: Colors.red, height: 100, width: 50,),
            Container(child: Text("Text2"), color: Colors.red, height: 50, width: 100,),
            Container(child: Text("Text3"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text4"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text5"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text6"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text7"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text8"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text9"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text10"), color: Colors.red, height: 50, width: 50,),
            Container(child: Text("Text11"), color: Colors.red, height: 30, width: 120,),
          ],
        ),
      )
    );
  }
}

效果如下:


2020325953.jpg

七、FittedBox Widget

FittedBox 用于管理子 Widget 在其父级 Widget 如何对齐和缩放。构造方法如下:

const FittedBox({
  Key key,
  //BoxFit类型可选命名参数,如何适配子Widget
  this.fit = BoxFit.contain,
  //AlignmentGeometry类型可选命名参数,如何在父级范围内对齐子Widget,使用Alignment
  this.alignment = Alignment.center,
  //Widget类型可选命名参数,要显示的Widget
  Widget child,
})

使用如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Container(
        color: Colors.yellow,
        height: 200,
        width: 400,
        child: FittedBox(
          fit: BoxFit.fitHeight,
          alignment: Alignment.topLeft,
          child: Container(
            height: 100,
            width: 100,
            color: Colors.red,
            child: Image.network("http://www.mwpush.com/uploads/avatar.png"),
          ),
        ),
      )
    );
  }
}

BoxFit 的设置和样式可以查看官网,地址为:https://api.flutter.dev/flutter/painting/BoxFit-class.html

上述代码效果如下:


20203241037.jpg

八、OverflowBox Widget

通常,当一个子 Widget 在 父 Widget 中时,子 Widget 是受父 Widget 的约束限制的,超出父 Widget 的部分一般会被截掉。如果想子 Widget 不受父 Widget 的限制,可以使用 OverflowBox ,它是一个溢出 Widget ,可以使用与父 Widget 不同的约束。其构造方法如下:

const OverflowBox({
  Key key,
  //AlignmentGeometry类型可选命名参数,如何在父级范围内对齐子Widget,使用Alignment
  this.alignment = Alignment.center,
  //double类型可选命名参数,最小宽度,不设置(默认值),使用父级约束
  this.minWidth,
  //double类型可选命名参数,最大宽度,不设置(默认值),使用父级约束
  this.maxWidth,
  //double类型可选命名参数,最小高度,不设置(默认值),使用父级约束
  this.minHeight,
  //double类型可选命名参数,最大高度,不设置(默认值),使用父级约束
  this.maxHeight,
  //Widget类型可选命名参数,要显示的Widget
  Widget child,
})

使用如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Container(
        color: Colors.yellow,
        height: 200,
        width: 400,
        child: OverflowBox(             //OverflowBox
          minHeight: 100,   
          maxHeight: 300,
          minWidth: 100,
          maxWidth: 300,
          alignment: Alignment.topRight,
          child: Container(
            color: Colors.red,
          ),
        ),
      )
    );
  }
}

效果如下:


2020325929.jpg

九、Offstage Widget

在开发中,有时候需要根据需要来对某个 Widget 进行显示或隐藏,就可以使用 Offstage 。当 Offstage 设置为隐藏时,其不接收任何事件,也不占用父级的任何空间。但如果在 Offstage 中有动画执行,即便其为隐藏状态,动画都会在后台继续执行,会消耗电量和 CPU 。其构造方法如下:

const Offstage({
  Key key, 
  //bool类型可选命名参数,是否隐藏子Widget
  this.offstage = true, 
  //Widget类型可选命名参数,要显示或隐藏的Widget
  Widget child 
})

使用如下:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("HomePage"),
      ),
      body: Container(
        color: Colors.yellow,
        height: 200,
        width: 400,
        child:  Offstage(                   //Offstage
          offstage: false,       //当设置为true时,在界面上不会显示Text
          child: Text("Offstage"),
        )
      )
    );
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342