UIView(2)

UIView(控件)

UIView的创建

  1. alloc init方法创建
  • 通过UIStoryboard加载控件详见UIStoryboard
  • 通过xib加载控件详见XIB

UIView的常用属性

// superview:获得自己的父控件对象,每个子控件的superview只有一个,该属性只读
// 一般用于判断是否已经加入到视图中,避免重复添加
if (view.superview) return;

// subviews:获得自己的所有子控件对象,只读
NSLog(@"%@",view.subviews);

// 是否可与用户交互
view.userInteractionEnabled = YES;

// 裁剪超出范围的控件
view.clipsToBounds = YES;

// 设置透明度
view.alpha = 1;

// 设置背景颜色,默认是clearColor
view.backgroundColor = [UIColor colorWithRed:1 green:1 blue:0 alpha:0.3];//颜色由三原色组成

UIView的常用方法

// 添加一个子控件view
// 底层实现:
    // 1.判断传入view之前有没有父控件
    // 2.如果有,先移除之前父控件
    // 3.再重新添加view
[self.view addSubview:view];

// 从父控件中移除
// 多用于动画控件完成动画后移除
[self.view removeFromSuperview];

UIView获取子控件或其标识

  • 开发中,经常需要使用到标识来获取控件或其标识,用于控件间的联动,这时的可选方案如下:
    • 方案一:通过tag值(不推荐使用)

      1. tag:控件的ID(标识),父控件可以通过tag来找到对应的子控件;
      2. tag默认值是0
      3. tag值是随意设置,很容易混乱,能不用就不用,开发时间越长,tag值管理会越来越困难
        // 设置tag值
        view.tag = 10;
        
        // 根据tag获取view,没找到返回nil
        UIView *view = [self.view viewWithTag:10];
        
        // viewWithTag:内部的大致实现思路
        - (UIView *)viewWithTag:(NSInteger)tag
        {
            if (self.tag == tag) return self;
        
            for (UIView *subview in self.subviews) {
            // 返回tag标识找出对应的控件(一般都是子控件)
                return [subview viewWithTag:tag];
            }
        }
        
    • 方案二:通过subviews数组获取(不推荐)

      • 不足:一般都是通过控制器的view的subviews获取子控件或其标识,但该view不仅有我们自己创建的控件,也有系统创建的控件,不好把握,容易出错;另外子元素种类一般不相同,不方便管理
        // 获取某个子控件
        UIView *view = self.view.subviews[0];
        
        // 获取控件标识
        NSInteger index = [self.views indexOfObject:view]
        
    • 方案三:新建数组,获取角标获取控件(推荐方案)

      // 新建控件数组并作为成员属性
      NSMutableArray *views = [NSMutableArray array];
      self.views = views;
      
      // 将控件添加到控件数组中
      [self.views addObject:view];
      [self.views addObject:view1];
      [self.views addObject:view2];
      
      // 获取控件标识
      NSInteger index = [self.views indexOfObject:view]
      
      // 获取控件
      UIView *view = self.views[index];
      

UIViewContentMode属性(只对UIImageView控件中图片有效)

  • 带有scale单词的:图片有可能会拉伸(常用)
scale的属性 拉伸方式(不旋转图片 保持原宽高比? 备注
UIViewContentModeScaleToFill 不按比例拉伸拉伸图片至填充整个控件 图片跟控件同宽同高默认属性
UIViewContentModeScaleAspectFill 按比例拉伸图片,直至图片拉伸至填充整个控件 图片一边与控件相等,另一边于控件
UIViewContentModeScaleAspectFit 按比例拉伸图片,直至图片任一边与控件对应边一样大 图片一边与控件相等,另一边于控件
  • 没有scale单词的:图片绝对不会被拉伸
不含scale的属性 是否拉伸 在控件中的显示位置
UIViewContentModeCenter 保持图片的原尺寸 居中
UIViewContentModeTop 同上 上面
UIViewContentModeBottom 同上 下面
UIViewContentModeLeft 同上 左面
UIViewContentModeRight 同上 右面
UIViewContentModeTopLeft 同上 左上
UIViewContentModeTopRight 同上 右上
UIViewContentModeBottomLeft 同上 左下
UIViewContentModeBottomRight 同上 右下

UIView的封装(自定义控件)

  1. 自定义控件基础:父子控件
    1. 每个控件都是个容器,能容纳其他控件
    1. 内部小控件是大控件的子控件
    2. 大控件是内部小控件的父控件
  • 自定义控件的意义
    1. 如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部子控件的创建屏蔽起来,不暴露给外界

      2. 外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据
    
  • 步骤:

    1. 新建一个继承UIView的类
    • 创建并布局子控件(纯代码或者xib方式)
      1. 纯代码方式
        1. 提供类方法及对象方法
        1. 可以重写init或initWithFrame方法
        2. 重写init创建时,底层也会调用initWithFrame方法,先调用父类的,再调用子类自身;
        2. 在initWithFrame:方法中添加并初始化子控件
        3. 在layoutSubviews方法中布局子控件,布局前必须调用[super layoutSubviews];

      2. xib方式
        1. 新建一个xib文件(xib的文件名最好跟控件类名一样)
        1. 添加子控件、设置子控件属性
        2. 修改最大的父控件的class为控件类名
        3. 将子控件进行连线
        2. 提供一个类方法及对象方法用于加载xib
        1. 初始化时底层不调用initWithFrame:方法,而是调用`initWithCoder:方法。加载时:
        2. initWithCoder是第一个执行的方法
        3. awakeAfterUsingCoder:是第二个执行的方法
        3. awakeFromNib是最后执行的方法,可在这里初始化控件

    • 提供模型属性,重写模型属性的set方法
      • 在set方法中给子控件设置数据

渐变式动画

  1. 头尾式
    // 开始动画
    [UIView beginAnimations:nil context:nil];
    
    // 设置动画属性
    // 设置动画时间
    [UIView setAnimationDuration:2.0];
    
    /* 需要执行动画的代码 */
    
    // 提交动画
    [UIView commitAnimations];
    
  • block式(实质是苹果对头尾式动画的封装)
    // 在1秒内执行动画
    [UIView animateWithDuration:1.0 animations:^{
        // 显示指示版
        self.hudLbl.alpha = 1;//不透明
    
    } completion:^(BOOL finished) {
    
        // 上一个动画完毕后延迟3秒后,在1秒内执行下列动画
        [UIView animateWithDuration:1.0 delay:3.0 options:kNilOptions animations:^{
    
            // 隐藏指示版
            self.hudLbl.alpha = 0;//完全透明
        } completion:nil];
    }];
    

UIView界面跳转

  1. 如果2个控件如果有重叠部分,那么处于上面的那个控件会盖住下面的。上面的控件不是透明或颜色为clearColor,会挡住下面控件的显示

  2. 开发中需要在某些时刻将指定的控件显示出来,即放在最上面;这时需要界面跳转。

  • 界面跳转主要的方法有3种:
    1. 用 UINavigationController 把 View B push 进来。
      [self.navigationController pushViewController:nextView animated:YES];
      
    • 用Modal的 presentModalViewController 方法把 View B 盖在上面。
      [self presentModalViewController:nextView animated:YES];
      
    • 调整窗口subView中元素的顺序,也可应用于当前显示的父控件中,让其某个子控件显示出来;
      // AppDelegate.m 类
      // 添加到窗口上
      [self.window addSubview:viewB];
      [self.window addSubview:viewA];
      
      // 调整控件位置顺序,让其显示出来
      [self.window bringSubviewToFront:viewB];
      
  • 界面跳转的本质重新调整窗口subViews中元素的顺序,让最后一个元素显示

UIView圆角裁剪和加边框方式

方案一 :最简单的

// 最简单的方式就是设置每个 View 自带的 layer 的属性即可
view.layer.cornerRadius = 8.0f;

// 如果该 View 有子 View,会是这种状况
view中有view
// 如果需要切掉除了保留部分以外的子 View,那么需要加上
view.clipsToBounds = YES;
InMrEb2.jpg-web.jpg
// 如果需要边框,也简单,加上 layer 的边框设置就可以。
view.layer.borderWidth=10.0f;
view.layer.borderColor= [UIColor yellowColor].CGColor;

// 但是如果细看,会发现边框有严重的黑边,特别是当 View 背景色比较深的时候
简单增加边框的效果图

方案一总结:
1.1 好处:简单,哪里需要圆角就在哪里设置就可以了。
1.2 缺点:这种方式处理的圆角很模糊,特别是在视图比较小的时候,质量不高,当背景色比较深的时候有边框有黑边现象,而且如果使用了 clipToBounds ,则会触发离屏渲染(这个一个很大的坑,有兴趣的话可以详细了解下),造成很严重的卡顿问题,特别是在 UITableViewCell 的子 View 中这样使用,掉帧会很严重。


简单裁剪的bug

方案二 :设置 mask layer

// 使用贝赛尔曲线,并根据其路径,得到一个「遮罩 layer」,将其设置为 View 自带 layer 的 mask,盖掉其他部分,剩余中间的部分。也可以达到圆角效果。

- (void)setRoundedCorners {
   UIBezierPath* maskPath = [UIBezierPathbezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:size];

   CAShapeLayer* maskLayer = [CAShapeLayerlayer];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;

   self.layer.mask = maskLayer;
}
   // 将这个 masklayer 加到自带 layer 上而不是设置为其 mask,代码如下:
   /*
   UIBezierPath* maskPath = [UIBezierPath bezierPathWithRoundedRect:v.boundsbyRoundingCorners:UIRectCornerAllCornerscornerRadii:CGSizeMake(halfW, halfW)];

   CAShapeLayer* maskLayer = [CAShapeLayer layer];
   maskLayer.frame = view.bounds;
   maskLayer.fillColor = [UIColor whiteColor].CGColor;
   maskLayer.path = maskPath.CGPath;
   maskLayer.backgroundColor= [UIColor greenColor].CGColor;

   [view.layer addSublayer:maskLayer];
   */
   
   // 效果图:
   // 一个只有四个角的 layer 盖到原来的 layer 上,达到圆角效果。
   // 因为是盖住四角达到的效果,所以不用设置 maskToBounds 也可以去掉子 View 超出中心圆的部分,但是同样会触发离屏渲染。用的时候应当小心。
```![z26jAbI.jpg-web.jpg](http://upload-images.jianshu.io/upload_images/1566132-4b043dfcc9ad6d73.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![设置mask layer圆角效果图](http://upload-images.jianshu.io/upload_images/1566132-3da6e98933c5125d.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


```objc
   // 如果要加上边框,可以在 self.layer 上加一个圆环 layer 达到边框效果,代码如下:

- (void)setRoundedCorners:(UIRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(UIColor*)borderColor cornerSize:(CGSize)size {
   UIBezierPath* maskPath = [UIBezierPathbezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:size];

   CAShapeLayer* maskLayer = [CAShapeLayerlayer];
   maskLayer.fillColor = [UIColorblueColor].CGColor;
   maskLayer.frame = self.bounds;
   maskLayer.path = maskPath.CGPath;

   self.layer.mask = maskLayer;

   if(borderWidth >0) {
       CAShapeLayer*borderLayer = [CAShapeLayerlayer];

       // 用贝赛尔曲线画线,path 其实是在线的中间,这样会被      layer.mask(遮罩层)遮住一半,故在 halfWidth 处新建 path,刚好产生一个内描边
       CGFloathalfWidth = borderWidth /2.0f;
       CGRectf =CGRectMake(halfWidth,  halfWidth,CGRectGetWidth(self.bounds) - borderWidth,CGRectGetHeight(self.bounds) - borderWidth);

       borderLayer.path = [UIBezierPathbezierPathWithRoundedRect:f byRoundingCorners:corners cornerRadii:size].CGPath;
       borderLayer.fillColor = [UIColorclearColor].CGColor;
       borderLayer.strokeColor = borderColor.CGColor;
       borderLayer.lineWidth = borderWidth;
       borderLayer.frame =         CGRectMake(0,0,CGRectGetWidth(f),CGRectGetHeight(f));
       [self.layer addSublayer:borderLayer];
}
    // 我们会看到这里 borderLayer 的坐标很奇怪,这里解释一下,如果我们这样设置坐标,用以下方式添加 borderLayer,会是什么效果呢?

    UIBezierPath* borderPath= [UIBezierPathbezierPathWithRect:v.bounds];

    CAShapeLayer* borderLayer= [CAShapeLayer layer];
    borderLayer.path =borderPath.CGPath;
    borderLayer.fillColor = [UIColor clearColor].CGColor;
    borderLayer.strokeColor =   [[UIColorblackColor]colorWithAlphaComponent:0.5].CGColor;
    borderLayer.lineWidth =10;
    borderLayer.frame = v.bounds;
    [v.layer addSublayer:borderLayer];
    
    // 效果图:
    // 效果分析:
    // 边框刚好骑在了边界上,如果这时候我们在使用 maskLayer 做圆角,那骑在边界上的边框有外面一半将被吃掉,只剩下一半,所以要把 borderLayer 往里挪一半的边框的距离,避免让 maskLayer 吃掉外面那部分边框。
设置mask layer增加边框效果图1
放大后的效果图:
设置mask layer增加边框效果图2
方案二总结:
1.1 好处:简单,并且可以使用贝赛尔曲线达到任意形状的「剪切」,也可以根据情况选择要「切」的角,比如如果只需要切右上和右下两个角,那么只需要改一下贝赛尔曲线
   UIBezierPath* maskPath = [UIBezierPathbezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerTopRight|UIRectCornerBottomRightcornerRadii:CGSizeMake(halfW, halfW)];
1.2 缺点:上一种方式的缺点,这个方式也都有

方案三 :生成圆角背景图片方式

   CGFloat w = 200; 
   UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0,0, w, w)]; 
   v.backgroundColor= [UIColor redColor];
   [self.view addSubview:v];
   v.center = self.view.center; 
   
   UIImage *img = [UIImage imageWithColor:v.backgroundColorandSize:v.bounds.size]; 
   img = [img roundedWithBorderWidth:10borderColor:[UIColorgreenColor]]; 
   
   UIImageView *imageView = [[UIImageView alloc] initWithImage:img];
   [v insertSubview:imageViewatIndex:0]; 
   v.backgroundColor= [UIColor clearColor];
   
   // 根据 View 的大小和背景色,生成一张图片,生成图片的方法如下:
   @implementationUIImage(ZQExtension) 
   + (UIImage*)imageWithColor:(UIColor*)color andSize:(CGSize)size { 
   CGRectrect =CGRectMake(0.0f,0.0f, size.width, size.height); 
   
   UIGraphicsBeginImageContextWithOptions(rect.size,NO, [UIScreenmainScreen].scale); 
   
   CGContextRefcontext =UIGraphicsGetCurrentContext();
   
   CGContextSetFillColorWithColor(context, [colorCGColor]);
   
   CGContextFillRect(context, rect); 
   
   UIImage*image =UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); returnimage; 
   } 
   @end
   
   // 再将这张图片圆角处理,并加上边框,最后创建一个 UIImageView,设置该 imageView 的 image 为圆角处理后的图片,并插入 View 的最底层,造成一种圆角处理的假象。

   // 圆角处理的代码如下:

@implementationUIImage(ZQExtension)

- (UIImage*)roundedWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor*)borderColor {

   CGFloatinset =1;
   CGFloatwidth =self.size.width;
   CGFloatheight =self.size.height;
   CGFloatcornerRadius;
   UIBezierPath*maskShape;
   
   if(width > height) {
        cornerRadius = height / 2.0- inset;
       maskShape = [UIBezierPathbezierPathWithRoundedRect:CGRectMake((width-height)/2.0+ inset,0+ inset, height-2*inset, height-2*inset) cornerRadius:cornerRadius];
       
   }else{
       cornerRadius = width / 2.0- inset;
       maskShape = [UIBezierPathbezierPathWithRoundedRect:CGRectMake(0+inset, (height-width)/2.0+inset, width-2*inset, width-2*inset) cornerRadius:cornerRadius];
}

   UIGraphicsBeginImageContextWithOptions(self.size,NO, [UIScreenmainScreen].scale); 
   
   CGContextRefctx =UIGraphicsGetCurrentContext(); 
   
   CGContextSaveGState(ctx); 
   
   CGContextAddPath(ctx, maskShape.CGPath);
   
   CGContextClip(ctx); CGContextTranslateCTM(ctx,0, height); 
   
   CGContextScaleCTM(ctx,1.0,-1.0); 
   
   CGContextDrawImage(ctx,CGRectMake(0,0, width, height),self.CGImage); 
   
   CGContextRestoreGState(ctx);
   
   if(borderWidth >0) { 
       [borderColor setStroke]; 
       
       CGFloathalfWidth = borderWidth /2.0; 
       
       UIBezierPath*border = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(halfWidth, halfWidth,self.size.width - borderWidth ,self.size.width - borderWidth)];
       
       CGContextSetShouldAntialias(ctx,YES);
       
       CGContextSetAllowsAntialiasing(ctx,YES);
       
       CGContextSetLineWidth(ctx, borderWidth);
       
       CGContextAddPath(ctx, border.CGPath);
       
       CGContextStrokePath(ctx); 
   } 
       UIImage*resultingImage =UIGraphicsGetImageFromCurrentImageContext();
       
       UIGraphicsEndImageContext(); 
       
       returnresultingImage; 
       
   } @end
   
   // 效果如下:
   // 这里使用贝赛尔曲线加边框的坐标和第二种方式的类似。
生成圆角背景图片方式效果图
方案三 :生成圆角背景图片方式总结
3.1 好处:是不会触发离屏渲染,生成图片和圆角都由 CPU 处理,且边框清晰,没有黑边,
3.2 缺点:不能处理子 View,在四角处的子 View 不会被「切」掉,毕竟是一个圆角背景造成的圆角假象,对子 View 没有什么影响力。

方案四 :使用遮罩层(推荐)

    // 这个遮罩层不是上面提遮罩 layer,是一张你想要保留的形状的一张图片,比如想要圆角图片,可以让设计师做一张这样图片:

    // 中间透明,周围是想要盖住的形状,最中看到的是中间留下来的形状,这种做法没有什么性能损耗,就是需要麻烦设计师做一张图。
    
    // 具体的做法见,也可以跑一下这个 demo 看看怎么对 UITableView 优化的。 https://github.com/johnil/VVeboTableViewDemo/blob/master/VVeboTableViewDemo/view/VVeboTableViewCell.m#L46
    
    // 设计师需要做的图:
遮罩层图片

五、总结:UIView圆角裁剪和加边框方式汇总

5.1 在[离屏渲染优化][http://www.jianshu.com/p/ca51c9d3575b] (建议好好看看篇文章)中,seedante 对各种圆角方案也有总结对比,最终得到这样一个结果:

5.2 任何时候优先考虑避免触发离屏渲染,无法避免时优化方案有两种:

5.3 Rasterization:适用于静态内容的视图,也就是内部结构和内容不发生变化的视图,对上面的所有效果而言,在实现成本以及性能上最均衡的。即使是动态变化的视图,开启 Rasterization 后能够有效降低 GPU 的负荷,不过在动态视图里是否启用还是看 Instruments 的数据。

5.4 规避离屏渲染,用其他手法来模拟效果,混合图层是个性能最好、耗能最少的通用优化方案,尤其对于 rounded corer 和 mask。

5.5 总的来说,圆角方案需要根据情况具体选择用哪种方式。

UIView的layout机制解释

// ios layout机制相关方法

- (CGSize)sizeThatFits:(CGSize)size
- (void)sizeToFit
——————-

- (void)layoutSubviews
- (void)layoutIfNeeded
- (void)setNeedsLayout
——————–

- (void)setNeedsDisplay
- (void)drawRect

/*
layoutSubviews在以下情况下会被调用:

1、init初始化不会触发layoutSubviews

   但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发

2、addSubview会触发layoutSubviews

3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化

4、滚动一个UIScrollView会触发layoutSubviews

5、旋转Screen会触发父UIView上的layoutSubviews事件

6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件

在苹果的官方文档中强调:

      You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want.

layoutSubviews, 当我们在某个类的内部调整子视图位置时,需要调用。

反过来的意思就是说:如果你想要在外部设置subviews的位置,就不要重写。

刷新子对象布局

-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)

如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局

在视图第一次显示之前,标记总是“需要刷新”的,可以直接调用[view layoutIfNeeded]

重绘

-drawRect:(CGRect)rect方法:重写此方法,执行重绘任务
-setNeedsDisplay方法:标记为需要重绘,异步调用drawRect
-setNeedsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘

sizeToFit会自动调用sizeThatFits方法;

sizeToFit不应该在子类中被重写,应该重写sizeThatFits

sizeThatFits传入的参数是receiver当前的size,返回一个适合的size

sizeToFit可以被手动直接调用

sizeToFit和sizeThatFits方法都没有递归,对subviews也不负责,只负责自己

———————————-

layoutSubviews对subviews重新布局

layoutSubviews方法调用先于drawRect

setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews

layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout.根据Apple官方文档,layoutIfNeeded方法应该是这样的

layoutIfNeeded遍历的不是superview链,应该是subviews链

drawRect是对receiver的重绘,能获得context

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

推荐阅读更多精彩内容