Flutter跨平台移动端开发丨Column、Row、Flex、Wrap、Flow、Stack

目录

  1. Column Widget(垂直布局)
  2. Row Widget(水平布局)
  3. Flex Widget and Expanded(弹性布局及扩展)
  4. Wrap Widget(流式布局)
  5. Flow Widget(自定义流式布局)
  6. Stack Widget and Positioned(层叠布局及定位)

Column Widget(垂直布局)

子 widget 按照垂直方向排列,继承自 flex

  Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  }) : super(
    children: children,
    key: key,
    direction: Axis.vertical,
    mainAxisAlignment: mainAxisAlignment,
    mainAxisSize: mainAxisSize,
    crossAxisAlignment: crossAxisAlignment,
    textDirection: textDirection,
    verticalDirection: verticalDirection,
    textBaseline: textBaseline,
  );
  • key:当前元素的唯一标识符(类似于 Android 中的 id)
  • mainAxisAlignment :表示子 widget 在 Column 空间内的对齐方式。当值为 mainAxisSize = min 时无意义,因为此时 Column 的宽度 = 所有子 widget 的宽度之和。当 mainAxisSize = max 时有意义,MainAxisAlignment.start表示沿textDirection的初始方向对齐,如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。而MainAxisAlignment.end和MainAxisAlignment.start正好相反;MainAxisAlignment.center表示居中对齐。textDirection是mainAxisAlignment的参考系
  • mainAxisSize :表示 Column 在水平方向占用的空间。max 表示最大宽度,min 表示最小宽度,也就是所有子 widget 的宽度之和
  • crossAxisAlignment:表示子 widgets 在纵轴方向的对齐方式,Column 的高度等于子 widgets 中高度最高子元素的高度。它的取值和MainAxisAlignment一样(包含start、end、 center三个值),verticalDirection 是 crossAxisAlignment 的参考系
  • textDirection:表示水平方向子 widget 的布局顺序,默认为由左向右
  • verticalDirection:表示 Column 的纵轴对齐方式,默认为 VerticalDirection.down 从上到下
  • textBaseline:文本绘制基线(alphabetic/ideographic)
  • children:子 widget 集合
/**
 * @des Column Widget
 * @author liyongli 20190422
 * */
class ColumnWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _ColumnState();

}

/**
 * @des Column Widget State
 * @author liyongli 20190422
 * */
class _ColumnState extends State<ColumnWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Row Widget"),
        ),

        body: new Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          verticalDirection: VerticalDirection.up,

          children: <Widget>[
            new Text("我是一只小小鸟 ",
            style: new TextStyle(
              color: Color(0xff2196F3),
              height: 3.0
            )),

            new Text("飞着飞着",
                style: new TextStyle(
                    color: Color(0xff2196F3),
                    height: 2.0
            )),

            new Text("我更有劲了",
                style: new TextStyle(
                    color: Color(0xff2196F3),
                    height: 4.0
            ))
          ],
        ),
      ),
    );
  }
}

Row Widget(水平布局)

子 widget 按照水平方向排列,继承自 flex

  Row({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  }) : super(
    children: children,
    key: key,
    direction: Axis.horizontal,
    mainAxisAlignment: mainAxisAlignment,
    mainAxisSize: mainAxisSize,
    crossAxisAlignment: crossAxisAlignment,
    textDirection: textDirection,
    verticalDirection: verticalDirection,
    textBaseline: textBaseline,
  );
  • key:当前元素的唯一标识符(类似于 Android 中的 id)
  • mainAxisAlignment :表示子 widget 在 row 空间内的对齐方式。当值为 mainAxisSize = min 时无意义,因为此时 row 的宽度 = 所有子 widget 的宽度之和。当 mainAxisSize = max 时有意义,MainAxisAlignment.start表示沿textDirection的初始方向对齐,如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。而MainAxisAlignment.end和MainAxisAlignment.start正好相反;MainAxisAlignment.center表示居中对齐。textDirection是mainAxisAlignment的参考系
  • mainAxisSize :表示 row 在水平方向占用的空间。max 表示最大宽度,min 表示最小宽度,也就是所有子 widget 的宽度之和
  • crossAxisAlignment:表示子 widgets 在纵轴方向的对齐方式,row 的高度等于子 widgets 中高度最高子元素的高度。它的取值和MainAxisAlignment一样(包含start、end、 center三个值),verticalDirection 是 crossAxisAlignment 的参考系
  • textDirection:表示水平方向子 widget 的布局顺序,默认为由左向右
  • verticalDirection:表示 row 的纵轴对齐方式,默认为 VerticalDirection.down 从上到下
  • textBaseline:文本绘制基线(alphabetic/ideographic)
  • children:子 widget 集合
import 'package:flutter/material.dart';

/**
 * @des Row Widget
 * @author liyongli 20190422
 * */
class RowWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _RowState();

}

/**
 * @des Row Widget State
 * @author liyongli 20190422
 * */
class _RowState extends State<RowWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Row Widget"),
        ),

        body: new Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.end,
          verticalDirection: VerticalDirection.up,

          children: <Widget>[
            new Text("我是一只小小鸟 ",
            style: new TextStyle(
              color: Color(0xff2196F3),
              height: 3.0
            )),

            new Text(" 翅膀硬了",
                style: new TextStyle(
                    color: Color(0xff2196F3),
                    height: 2.0
            )),

            new Text(" 不停的飞",
                style: new TextStyle(
                    color: Color(0xff2196F3),
                    height: 4.0
            ))
          ],
        ),
      ),
    );
  }
}

Flex Widget and Expanded(弹性布局及扩展)

Flex Widget(弹性布局)

flex 可以按水平或垂直方向排列子 widget,并且允许子 widget 按照比例分配父 widget 的空间,row 和 column 均继承自 flex

  Flex({
    Key key,
    @required this.direction,
    this.mainAxisAlignment = MainAxisAlignment.start,
    this.mainAxisSize = MainAxisSize.max,
    this.crossAxisAlignment = CrossAxisAlignment.center,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    this.textBaseline,
    List<Widget> children = const <Widget>[],
  })
  • key:当前元素的唯一标识符(类似于 Android 中的 id)
  • direction:弹性布局的方向, Row默认为水平方向,Column默认为垂直方向
  • mainAxisAlignment :表示子 widget 在 flex 空间内的对齐方式。当值为 mainAxisSize = min 时无意义,因为此时 row 的宽度 = 所有子 widget 的宽度之和。当 mainAxisSize = max 时有意义,MainAxisAlignment.start表示沿textDirection的初始方向对齐,如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。而MainAxisAlignment.end和MainAxisAlignment.start正好相反;MainAxisAlignment.center表示居中对齐。textDirection是mainAxisAlignment的参考系
  • mainAxisSize :表示 flex 在水平方向占用的空间。max 表示最大宽度,min 表示最小宽度,也就是所有子 widget 的宽度之和
  • crossAxisAlignment:表示子 widgets 在纵轴方向的对齐方式,flex 的高度等于子 widgets 中高度最高子元素的高度。它的取值和MainAxisAlignment一样(包含start、end、 center三个值),verticalDirection 是 crossAxisAlignment 的参考系
  • textDirection:表示水平方向子 widget 的布局顺序,默认为由左向右
  • verticalDirection:表示 flex 的纵轴对齐方式,默认为 VerticalDirection.down 从上到下
  • textBaseline:文本绘制基线(alphabetic/ideographic)
  • children:子 widget 集合
Expanded(扩展)

可以按照设定的比例值扩展/扩大在 row、column、flex 布局中 widget 的所用空间

Expanded({
  flex:1, // 当 flex = 0 时为占用空间不扩展
  child: Container(
    height: 30.0
   ),
})
水平方向扩展
/**
 * @des Flex Widget
 * @author liyongli 20190422
 * */
class FlexWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _FlexState();

}

/**
 * @des Flex Widget State
 * @author liyongli 20190422
 * */
class _FlexState extends State<FlexWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Row Widget"),
        ),

        body: new Column(
          children: <Widget>[

            new Flex(
              direction: Axis.horizontal,
              children: <Widget>[

                Expanded(
                  flex: 1,
                  child: Container(
                    color: Color(0xff333333),
                    height: 20.0,
                  ),
                ),

                Expanded(
                  flex: 2,
                  child: Container(
                    color: Color(0xff999999),
                    height: 20.0,
                  ),
                ),

                Expanded(
                  flex: 2,
                  child: Container(
                    color: Color(0xff666666),
                    height: 20.0,
                  ),
                )

              ],
            )
          ],
        ),
      ),
    );
  }
}
垂直方向扩展
/**
 * @des Flex Widget
 * @author liyongli 20190422
 * */
class FlexWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _FlexState();

}

/**
 * @des Flex Widget State
 * @author liyongli 20190422
 * */
class _FlexState extends State<FlexWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Flex Widget"),
        ),

        body: new Center(
          child: new SizedBox(
            width: 20,
            child: new Flex(
              direction: Axis.vertical,
              children: <Widget>[
                
                // 第一部分占五分之一
                Expanded(
                  flex: 1,
                  child: Container(
                    color: Color(0xff333333),
                    height: 20,
                  ),
                ),

                // 第二部分占五分之二
                Expanded(
                  flex: 2,
                  child: Container(
                    color: Color(0xff999999),
                    height: 20,
                  ),
                ),

                // 第三部分占五分之二
                Expanded(
                  flex: 2,
                  child: Container(
                    color: Color(0xff666666),
                    height: 20,
                  ),
                ),
              ],
            ),
          )
        )
      ),
    );
  }
}

Wrap Widget(流式布局)

若布局中包含的 widget 超出屏幕范围,且需要自动折行展示,那么你需要使用流式布局 wrap 来实现,wrap 的构成与 flex + row + column 相似

  Wrap({
    Key key,
    this.direction = Axis.horizontal,
    this.alignment = WrapAlignment.start,
    this.spacing = 0.0,
    this.runAlignment = WrapAlignment.start,
    this.runSpacing = 0.0,
    this.crossAxisAlignment = WrapCrossAlignment.start,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    List<Widget> children = const <Widget>[],
  }) : super(key: key, children: children);

(key,alignment,crossAxisAlignment,textDirection,verticalDirection,children 参数意义与 flex / row / column 相同)

  • spacing:行间距
  • runAlignment:列间距
  • runSpacing:纵轴方向上对齐方式
/**
 * @des Wrap Widget
 * @author liyongli 20190423
 * */
class WrapWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _WrapState();

}

/**
 * @des Wrap Widget State
 * @author liyongli 20190423
 * */
class _WrapState extends State<WrapWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Wrap Widget"),
        ),

        body: new Center(
            child: new Wrap(
              spacing: 20.0, // 主轴(水平)方向间距
              runSpacing: 5.0, // 纵轴(垂直)方向间距
              alignment: WrapAlignment.center, //沿主轴方向居中
              children: <Widget>[
                new RaisedButton(
                  child: new Text("A"),
                  color: Colors.blue ,
                  textColor: Colors.white,
                  onPressed: _BtnClick,
                ),

                new RaisedButton(
                  child: new Text("B"),
                  color: Colors.blue ,
                  textColor: Colors.white,
                  onPressed: _BtnClick,
                ),

                new RaisedButton(
                  child: new Text("C"),
                  color: Colors.blue ,
                  textColor: Colors.white,
                  onPressed: _BtnClick,
                ),

                new RaisedButton(
                  child: new Text("D"),
                  color: Colors.blue ,
                  textColor: Colors.white,
                  onPressed: _BtnClick,
                ),

                new RaisedButton(
                  child: new Text("E"),
                  color: Colors.blue ,
                  textColor: Colors.white,
                  onPressed: _BtnClick,
                ),

              ],
            )
        )
      ),
    );
  }

  // 按钮点击监听
  void _BtnClick(){
    print("不设置点击事件按钮会是灰色的!");
  }

}

Flow Widget(自定义流式布局)

可灵活实现自定义需求布局,且性能较好,但是使用方式复杂

flow 官方介绍是一个对 child 尺寸以及位置调整非常高效的控件,主要是得益于其FlowDelegate。另外 flow 在用转换矩阵(transformation matrices)对child进行位置调整的时候进行了优化

Flow之所以高效,是因为其在定位过后,如果使用FlowDelegate中的paintChildren改变child的尺寸或者位置,只是重绘,并没有实际调整其位置

  Flow({
    Key key,
    @required this.delegate,
    List<Widget> children = const <Widget>[],
  }) : assert(delegate != null),
       super(key: key, children: RepaintBoundary.wrapAll(children));
  • key:当前元素的唯一标识符(类似于 Android 中的 id)
  • delegate:影响 flow 具体布局的 flowDelegate
  • children:子 widget 集合
/**
 * @des Flow Widget
 * @author liyongli 20190423
 * */
class FlowWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _FlowState();

}

/**
 * @des Flow Widget State
 * @author liyongli 20190423
 * */
class _FlowState extends State<FlowWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Flow Widget"),
        ),

        body: new Flow(
          delegate: TestFlowDelegate(margin: EdgeInsets.all(10.0)),
          children: <Widget>[
            new Container(width: 80.0, height:80.0, color: Colors.blue,),
            new Container(width: 80.0, height:80.0, color: Colors.black,),
            new Container(width: 80.0, height:80.0, color: Colors.amber,),
            new Container(width: 80.0, height:80.0,  color: Colors.brown,),
            new Container(width: 80.0, height:80.0, color: Colors.cyanAccent,),
            new Container(width: 80.0, height:80.0,  color: Colors.deepOrange,),
          ],
        ),
      ),
    );
  }
}

/**
 * @des Flow Widget Delegate
 * @author liyongli 20190423
 * */
class TestFlowDelegate extends FlowDelegate {
  EdgeInsets margin = EdgeInsets.zero;
  TestFlowDelegate({this.margin});
  @override
  void paintChildren(FlowPaintingContext context) {
    var x = margin.left;
    var y = margin.top;
    //计算所有子 widget 位置
    for (int i = 0; i < context.childCount; i++) {
      var w = context.getChildSize(i).width + x + margin.right;
      if (w < context.size.width) {
        context.paintChild(i, transform: new Matrix4.translationValues(x, y, 0.0));
        x = w + margin.left;
      } else {
        x = margin.left;
        y += context.getChildSize(i).height + margin.top + margin.bottom;
        context.paintChild(i, transform: new Matrix4.translationValues( x, y, 0.0));
        x += context.getChildSize(i).width + margin.left + margin.right;
      }
    }
  }

  getSize(BoxConstraints constraints){
    return Size(double.infinity,200.0);
  }

  @override
  bool shouldRepaint(FlowDelegate oldDelegate) {
    return oldDelegate != this;
  }
}

Stack Widget and Positioned(层叠布局及定位)

stack 与 Android 中 Frame、Web 中绝对定位类似,子 widget 根据父 widget 的四个顶点确定位置。stack 布局允许子 widget 堆叠绘制

  Stack({
    Key key,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    this.overflow = Overflow.clip,
    List<Widget> children = const <Widget>[],
  }) : super(key: key, children: children);
  • key:当前元素的唯一标识符(类似于 Android 中的 id)
  • alignment:如果子 widget 没有设置定位(无 positioned)或只指定了部分定位,则此参数为子 widget 的定位标准。
  • textDirection:用于决定 alignment 的参考标准,与 row 布局中参数功能一致
  • fit:如果子 widget 没有定位,则此参数将指定子 widget 以怎样的方式适应 statck 的大小。StackFit.loose = 使用子 widget 的大小,StackFit.expand = 扩展至 stack 大小
  • overflow:如果子 widget 超出了 stack 的空间,则此参数将指定如何显示。Overflow.clip = 超出部分隐藏 / 裁剪,Overflow.visible = 产出部分不会隐藏 / 裁剪
  • children:子 widget 集合
Positioned(定位)
  const Positioned({
    Key key,
    this.left,
    this.top,
    this.right,
    this.bottom,
    this.width,
    this.height,
    @required Widget child,
  }) : assert(left == null || right == null || width == null),
       assert(top == null || bottom == null || height == null),
       super(key: key, child: child);
  • left、top 、right、 bottom:代表子 widget 距 statck 左、上、右、下四边的距离
  • width、height:设置定位元素的宽、高(width、height 需配合 left、top 、right、 bottom 并结合实际情况使用,如水平方向时,只可以设置 left、right、width 三个参数中的二个,若同时设置三个参数会产生错误)
/**
 * @des Stack Widget
 * @author liyongli 20190423
 * */
class StackWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _StackState();

}

/**
 * @des Stack Widget State
 * @author liyongli 20190423
 * */
class _StackState extends State<StackWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(

        appBar: new AppBar(
          title: new Text("Stack Widget"),
        ),

        body: ConstrainedBox(
          constraints: BoxConstraints.expand(),
          child: Stack(
            alignment:Alignment.center , //指定无定位或部分定位的子 widget 的对齐方式
            children: <Widget>[

              Container(
                child: Text("我是一只小小鸟", style: new TextStyle(color: Colors.white),),
                color: Colors.blue,
              ),

              Positioned(
                left: 18.0,
                child: Text("想飞飞飞"),
              ),

              Positioned(
                top: 18.0,
                child: Text("飞的挺高"),
              )

            ],
          ),
        ),
      ),
    );
  }
}
  • 我是一只小小鸟:没有指定定位(无 positioned),alignment = Alignment.center,所以居中显示
  • 想飞飞飞:指定了 left ,属于部分定位,只指定了水平定位,无垂直定位,所以垂直对齐的方式会按 alignment 的赋值参数,也就是垂直居中显示
  • 飞的挺高:指定了 top,属于部分定位,只制定了垂直定位,无水平定位,所以水平方向会按照 alignment 的赋值参数,也就是水平居中显示

此时,在原基础上给 stack 设置 fit = StackFit.expand (子 widget 没有指定定位时,此参数将指定子 widget 以怎样的方式适应 stack)

/**
 * @des Stack Widget
 * @author liyongli 20190423
 * */
class StackWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new _StackState();

}

/**
 * @des Stack Widget State
 * @author liyongli 20190423
 * */
class _StackState extends State<StackWidget>{

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(

        appBar: new AppBar(
          title: new Text("Stack Widget"),
        ),

        body: ConstrainedBox(
          constraints: BoxConstraints.expand(),
          child: Stack(
            alignment:Alignment.center , //指定未定位或部分定位widget的对齐方式
            fit: StackFit.expand, // expand = 未定位的子 widget 占满 stack 的可用空间
            children: <Widget>[

              Positioned(
                left: 18.0,
                child: Text("想飞飞飞"),
              ),

              Container(
                child: Text("我是一只小小鸟", style: new TextStyle(color: Colors.white),),
                color: Colors.blue,
              ),

              Positioned(
                top: 18.0,
                child: Text("飞的挺高"),
              )

            ],
          ),
        ),
      ),
    );
  }
}
  • 我是一只小小鸟:由于它无定位,所以它的绘制方式遵循 fit 指定的值,也就是占满 stack
  • 想飞飞飞:被遮盖 / 隐藏,由于 stack 布局可堆叠的特性,它已被第二个子 widget 遮盖
  • 飞的挺高:正常显示,因为它最后绘制,所以不会被第二个子 widget 遮盖

本篇到此完结,更多 Flutter 跨平台移动端开发 原创内容持续更新中~

期待您 关注 / 点赞 / 收藏 向着 大前端工程师 晋级!

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

推荐阅读更多精彩内容