IOS SizeClass 和 Autolayout 适配各种设备

SizeClass Autolayout 在Storyboard或XB上的适配

现在苹果生态圈中的设备尺寸也已经变得种类繁多了,设备种类如下:
iPad:iPad1,iPad2,newPad,iPad4,iPad air,iPad air2,iPad mini1,iPad mini2,iPad mini3,iPad pro;
iPhone:iPhone3Gs,iPhone4,iPhone4S,iPhone5,iPhone5S,iPhone5C iPhone6,iPhone6 Plus,iPhone6S,ipad iPhone6S Plus;
iWatch

屏幕大小

  1. iPhone:3.5,4.0,4.7,5.5
  2. iPad: 7.9,9.7,12.9
  3. iWatch:1.6,1.8

想必苹果也意识到这一点。都知道苹果是以化繁为简的设计哲学深入人心的,这次再一次证明了。SizeClass是对设备尺寸的一个抽象概念,现在任何设备的 长、宽 被简洁地分为三种情况:普通 (Regular)紧密 (Compact)任意(Any) ,这样,根据长和宽不同的搭配就能产生 3 * 3 = 9 种不同尺寸。下图展示个每种情况对应的设备。

autolayout.png

以前为不同的iOS设备尺寸或者同尺寸横竖屏不同适配UI,都要根据实际情况而去计算frame。使用Size Classes是根据当前的屏幕size类型而使用Auto Layout方式进行布局了,要摒弃之前计算frame的思路,而改用相对布局的思维去思考(实际上还是要计算frame).

而且Xcode6最大的突破也是这里,不在需要建立不同尺寸的storyboard了,只要建立一个,然后修改其view的size就可以做各种屏幕尺寸的适配,如下:

例如我要做iPad页面设计,就设置成w (Regular)/h(Regular)

然后同样的工程,又要兼容横屏的iPhone6 plus,就可以把view的size class设置成:w (Regular)/h(Compact),然后继续适配


然后当程序跑在不同的设备上,或者设备横屏和竖屏切换,就能显示相应的UI了。

示例:

适配iPhone6,在RootViewController的view上添加一个新的view,让这个新的view无论屏幕横屏还是竖屏时候都距离其superview的边缘50点宽,并且横屏时候为绿颜色,竖屏时候为红颜色。

操作如下:

  1. 切换size class为wCompact/hRegular模式


并且添加一个view,不用管其frame,并设置其背景色为红色

接下来选中红色的view,然后点击Xcode顶部工具栏的Editor-Pin,然后分别添加红色view相对superview边框的约束(上下左右

添加约束的过程中会看到约束的线是黄颜色,表明当前的约束还不能确定view的frame,需要继续添加,当添加完4个约束后,约束线的颜色是蓝色的,表明当前约束是正确的。

然后选中约束,设定约束的值(我们不是想让新的view距离其superview边界50点宽吗!),4个约束都要设置。

设置完后点击下view会自动更新frame,应该是这样的:


2.切换size class为wRegular/hCompact模式,然后重复第一步中的设置,区别是新添加的view背景颜色设置为绿色。


示例2:

基于iPhone适配界面,添加三个view到rootView上,然后无论横屏还是竖屏,新添加的三个view之间及与屏幕边框的距离都保持不变的间距20点宽,效果如图:

因为要适配iPhone横竖屏,所以修改size class为wCompact/hRegular来适配竖屏:拖拽3个view到rootView上,并设置其背景颜色


为了满足设计要求,要添加如下constraint:

  1. 设定绿色view距离superview左边距和上边距;
  2. 设定黄色view距离superview右边距和上边距,相对绿色view的的左边距;
  3. 设定蓝色view的左边距和右边距和下边距,上边距离绿色view下边的距离;
  4. 设定绿色view与黄色view等宽高
  5. 设定蓝色view与绿色view等高

操作如下:

选中绿色view,Eidtor->Pin->Leading Space to Superview给绿色view添加相对其superview的左边距,然后选中constraint,修改约束的值为20,其他constraint以此类推



添加完如图:



其中红色框部分清晰的表达了所添加的constraint;蓝色框部分时添加的constraint,目前为黄色线,表明当前的constraint还不能定位view,当一个view的constraint正确的时候,constraint的颜色会变为蓝色。绿色线框的部分表达了constraint的数值,我们想让边距为20,所以设置数值为20 。wC hR Installed表明当前constraint适用于wC hR这种size class,不适合any any的size class。

添加绿色view与黄色view之前的距离时候,由于是设定两个子view的constraint,所以要选中两个view,然后Editor->Pin ->Horizontal,设定值为20:


同样方法Editor->Pin ->Width Equally,设定绿色view与黄色view等宽度,蓝色view与绿色view等高,结果如图:



但发现constraint颜色仍然后黄色,原因是当前view的位置和constraint希望的不一致,更新下frame(要选中3个view,因为constraint关联3个view)或者点击Document Outline中的黄色小箭头,然后会看到具体的constraint信息来一步步调试,这个也是Xcode6最有突破的地方:


然后效果如图:


然后运行下项目吧,发现确实和预期的一样。然后旋转屏幕,是不是发现横屏时候白了,屏幕什么都没有了?原因是我们仅仅适配的竖屏,横屏还没有适配啊!

修改size class,iPhone4s横屏的size class为wCompact/hCompact,而iPhone6 plus为wReguage/hCompact,那我们不如设置为wAny/hCompact吧!然后安装上边适配竖屏的方式适配横屏。适配好后再次运行,横竖屏都应该是我们想要的了。

小小技巧:
查看不同设备适配情况

Autolayout 纯代码的适配

在 ios6 之前没有AutoLayout布局UI,我们布局UI是基于固定的frame,bound对控件的布局,设置控件的 位置(x,y), 尺寸(width,height)就可以把控件放在相应的位置。

出现Autolayout后,我们用AutoLayout布局控件就要把之前固定设置frame、bound忘记;要想布局显示一个控件,Autolayout以两个词:约束参照 动态设置一个控件两个东西,位置尺寸;

小结:
1. 添加约束不宜过多,当添加的约束足以表达该控件的位置与尺寸,就足够了
2. 约束就是对控件的大小或者位置进行约束,参照就是以某个控件的位置进行约束,其实这两者没有明确的分别,它们都可以对控件的位置与尺寸起到作用。

两种语法

1)手动添加约束(苹果官方API)

/**
 *  这个是系统默认添加约束的方法,它是NSLayoutConstraint的类方法
 *
 *  @param view1      传入想要添加约束的控件
 *  @param attr1      传入想要添加约束的方向,这个枚举值有很多,可以自己看看
 *  @param relation   传入与约束值的关系,大于,等于还是小于
 *  @param view2      传入被参照对象
 *  @param attr2      传入被参照对象所被参照的方向,如顶部,左边,右边等等
 *  @param multiplier 传入想要的间距倍数关系
 *  @param c          传入最终的差值
 *
 *  @return NSLayoutConstraint对象
 */
+(instancetype)constraintWithItem:(id)view1 
                        attribute:(NSLayoutAttribute)attr1 
                        relatedBy:(NSLayoutRelation)relation 
                           toItem:(id)view2 
                        attribute:(NSLayoutAttribute)attr2 
                       multiplier:(CGFloat)multiplier 
                         constant:(CGFloat)c

//一部分NSLayoutAttribute枚举值
    NSLayoutAttributeLeft = 1,//控件左边
    NSLayoutAttributeRight,//控件右边
    NSLayoutAttributeTop,
    NSLayoutAttributeBottom,
    NSLayoutAttributeLeading,//控件左边
    NSLayoutAttributeTrailing,//控件右边
    NSLayoutAttributeWidth,//控件的宽
    NSLayoutAttributeHeight,//控件的高
    NSLayoutAttributeCenterX,//竖直方向中点
    NSLayoutAttributeCenterY,//水平方向中点

这个方法的参数我很想用形象的语言描述出来,但是还是想不出,更多需要大家从下面的代码中传入的参数去体会

    //创建redView
    UIView *redView = [[UIView alloc]init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];
    
    //创建redView第一个约束,相对self.view的左边缘间距20
    NSLayoutConstraint * redLeftLc = [NSLayoutConstraint constraintWithItem:redView
                                                                  attribute:NSLayoutAttributeLeftMargin
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:self.view
                                                                  attribute:NSLayoutAttributeLeft
                                                                 multiplier:1.0f
                                                                   constant:20.0];
    
    //只有在没有参照控件的情况下,约束才加到自身,不然加到父控件上
    [self.view addConstraint:redLeftLc];
    
    //创建redView第二个约束,相对self。view的底边缘间距20
    NSLayoutConstraint *redBottomLc = [NSLayoutConstraint constraintWithItem:redView
                                                                   attribute:NSLayoutAttributeBottom
                                                                   relatedBy:NSLayoutRelationEqual
                                                                      toItem:self.view
                                                                   attribute:NSLayoutAttributeBottomMargin
                                                                  multiplier:1.0f
                                                                    constant:-20];//由于是redview相对self.view往上减20,所以是-20
    //添加约束
    [self.view addConstraint:redBottomLc];
    
    //这里直接设置自身宽为50
    NSLayoutConstraint * redWLc = [NSLayoutConstraint constraintWithItem:redView
                                                               attribute:NSLayoutAttributeWidth
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50.0f];
    //由于没有参照物,所以约束添加于自身身上
    [redView addConstraint:redWLc];
    
    //创建最后一个约束,自身的高
    NSLayoutConstraint * redHLc = [NSLayoutConstraint constraintWithItem:redView
                                                               attribute:NSLayoutAttributeHeight
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50];
    //由于没有参照物,所以约束添加于自身身上
    [redView addConstraint:redHLc];     

运行的效果图


接下来我们继续增加需求,在红色方块的右边放一个离它20间距,离self.view底部也间距20,宽高相等的蓝色方块

    //先创建一个一个蓝色的view添加到视图上,剩下的就是用autolayout来设置它的“frame”了
    UIView *blueView = [[UIView alloc]init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];
    self.blueView = blueView;
    
    //创建第一个约束,左边间距,由于是想要与红色有20的间距,那么参照参数“toItem”就应该填redView
    NSLayoutConstraint *blueLeft = [NSLayoutConstraint constraintWithItem:blueView
                                                                attribute:NSLayoutAttributeLeft
                                                                relatedBy:NSLayoutRelationEqual
                                                                   toItem:redView
                                                                attribute:NSLayoutAttributeRight
                                                               multiplier:1.0f
                                                                 constant:20.0f];
    //与其他控件发生约束,所以约束添加到父控件上
    [self.view addConstraint:blueLeft];
    
    //现在我们已经可以确定自己水平方向的位置了,还差垂直方向的位置,现在我们来创建第二个约束,参照物依然是红色方块,需求是要离self.view底部20间距,这不是正好和红色一样么,那么我们可以直接与红色方块底部对齐就行了
    NSLayoutConstraint *blueBottom = [NSLayoutConstraint constraintWithItem:blueView
                                                                  attribute:NSLayoutAttributeBottom
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:redView
                                                                  attribute:NSLayoutAttributeBottom
                                                                 multiplier:1.0f
                                                                   constant:0.0f];//与红色方块底部对齐,倍数1.0f.差值0.0f
    //与其他控件发生约束,所以约束添加到父控件上
    [self.view addConstraint:blueBottom];
    
    //剩下两个约束差不多,我就一并描述了,它们都以redView为参照,与其等宽等高
    NSLayoutConstraint *blueW = [NSLayoutConstraint constraintWithItem:blueView
                                                             attribute:NSLayoutAttributeWidth
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:redView
                                                             attribute:NSLayoutAttributeWidth
                                                            multiplier:1.0f
                                                              constant:0.0f];
    [self.view addConstraint:blueW];
    
    
    NSLayoutConstraint *blueH = [NSLayoutConstraint constraintWithItem:blueView
                                                             attribute:NSLayoutAttributeHeight
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:redView
                                                             attribute:NSLayoutAttributeHeight
                                                            multiplier:1.0f
                                                              constant:0.0f];
    [self.view addConstraint:blueH];

接下来看看效果图


小结:
1.其实Autolayout的思想非常简单,刚开始使用的时候不要想着马上一气呵成,最好一个控件一个控件的实现依赖,分别满足其位置与尺寸的需求,如果一下子几个控件一起弄的话,往往大家犯错是犯在约束添多了,而不是添少了。
2.就如上面的例子,很多人会在设置了与红色等高等宽后,还同时去添加顶部对齐与底部对齐,这样高度就重复设置了,他会忽略了,上下同时对齐不仅给予了垂直位置,也给予了高度,所以思路必须清晰!

Autolayout 下添加动画

我将在蓝色方块的右边再加个同样大小的黄色方块,然后,要求点击屏幕,然后蓝色方块被移除,黄色方块替代蓝色方块的位置

还有一个autolayout的知识点:优先级(priority)

    //一如往常,先创建黄色View
    UIView *yellowV = [[UIView alloc]init];
    yellowV.backgroundColor = [UIColor yellowColor];
    yellowV.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:yellowV];
    
    //开始创建约束,第一个约束是什么呢?一看就知道是左间距约束啦
    NSLayoutConstraint *yellowLeft = [NSLayoutConstraint constraintWithItem:yellowV
                                                                  attribute:NSLayoutAttributeLeft
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:blueView attribute:NSLayoutAttributeRight
                                                                 multiplier:1.0f
                                                                   constant:20];
    //与其他控件发生约束,所以约束添加到父控件上
    [self.view addConstraint:yellowLeft];
    
    //添加底部约束
    NSLayoutConstraint *yellowBottom = [NSLayoutConstraint constraintWithItem:yellowV
                                                                    attribute:NSLayoutAttributeBottom
                                                                    relatedBy:NSLayoutRelationEqual
                                                                       toItem:self.view
                                                                    attribute:NSLayoutAttributeBottom
                                                                   multiplier:1.0f
                                                                     constant:-20];
    //与其他控件发生约束,所以约束添加到父控件上
    [self.view addConstraint:yellowBottom];
    
    //这里我直接设置宽高约束了,就省事不加参照控件了
    NSLayoutConstraint *yellowW = [NSLayoutConstraint constraintWithItem:yellowV
                                                               attribute:NSLayoutAttributeWidth
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50.0f];
    [yellowV addConstraint:yellowW];
    
    
    NSLayoutConstraint *yellowH = [NSLayoutConstraint constraintWithItem:yellowV
                                                               attribute:NSLayoutAttributeHeight
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:kNilOptions
                                                              multiplier:1.0f
                                                                constant:50.0f];
    [yellowV addConstraint:yellowH];

运行效果


接下来我再给黄色View添加一个约束,这个约束涉及到优先级,大家注意看代码了哈

//对黄色View添加约束,约束黄色view与红色View的间距为20
NSLayoutConstraint *yellowAnotherLeft = [NSLayoutConstraint constraintWithItem:yellowV
                                                                     attribute:NSLayoutAttributeLeft
                                                                     relatedBy:NSLayoutRelationEqual
                                                                        toItem:redView
                                                                     attribute:NSLayoutAttributeRight
                                                                    multiplier:1.0f
                                                                      constant:20];
UILayoutPriority priority = 250;//设置优先级
yellowAnotherLeft.priority = priority;

//与其他控件发生约束,所以约束添加到父控件上
[self.view addConstraint:yellowAnotherLeft];        

想必大家应该看出些端倪了,我在前面已经给黄色View添加了对蓝色View间距位20的view,现在又给黄色view对红色View添加一个间距20的约束,这很明显是不可能出现的情况,黄色View怎么可能同时做到这两个约束呢,用术语来说就是约束冲突,但是大家注意看这段代码

UILayoutPriority priority = 250;//设置优先级
  1. 我给yellowAnotherLeft这个约束添加了优先级,优先级的范围是0~1000,数字越大,优先级越高,在不设置的情况下默认为1000

  2. 这说明了,我最后添加的这个约束的优先级是低的,这个约束只有在它的冲突约束被抹掉后,它才能实现

  3. 也就是说,我把蓝色view移除后,黄色View相对于蓝色View左间距20这个约束就不成立了,那么黄色view会自动的变为与红色View间距20

让我们最后加几行代码,来实现这个动画吧!

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //先把蓝色方块从父视图上移除
    [self.blueView removeFromSuperview];
    //动画更新界面
    [UIView animateWithDuration:1.0f animations:^{
        [self.view layoutIfNeeded];
    }];
}   

autolayout的动画就是这样实现的,将操作代码走完后,再让动画块去更新界面,动画就出来了,效果如下:


2)VFL(visual format language)

需求:适配iPhone6,在RootViewController的view上添加一个新的view,让这个新的view无论屏幕横屏还是竖屏时候都距离其superview的边缘20

H:|-20-[newView]-20-|

V:|-20-[newView]-20-|

每一个 [] 中表示一个视图或一个控件;V 表示垂直约束,H 表示水平约束,然后两个视图之间的 -0- 的意思就很简单了,意思就是这两个视图之间间隔为0

比如:
V:[view0(67)]-0-[view1(67)]-0-[view2(67)]-0-[view3(67)]-0-[view4(67)]-0-|

self.view.translatesAutoresizingMaskIntoConstraints = NO;
 
UIView *newView = [UIView new];
newView.backgroundColor = [UIColor greenColor];
[self.view addSubview:newView];
newView.translatesAutoresizingMaskIntoConstraints = NO;

NSMutableArray *constraintArray = [NSMutableArray array];
    
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:NSDictionaryOfVariableBindings(newView,self.view)]];
    
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[newView]-20-|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:NSDictionaryOfVariableBindings(newView,self.view)]];
[self.view addConstraints:constraintArray];

运行效果

第三方库 Masonry

  1. VFL的约束创建非常宏观,如果既要照顾语法讲解,又要照顾约束理解.
  2. Masonry的约束添加思维其实与苹果原API的添加思维是相同的,只是Masonry语法更简洁,代码更优美

示例

需求:如下所示


实现如下:

UIView *redView = [[UIView alloc]init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
    
UIView *blueView = [[UIView alloc]init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
    
UIView *yellow = [[UIView alloc]init];
yellow.backgroundColor = [UIColor yellowColor];
[self.view addSubview:yellow];
    
UIView *green = [[UIView alloc]init];
green.backgroundColor = [UIColor greenColor];
[self.view addSubview:green];
    
[redView mas_makeConstraints:^(MASConstraintMaker *make) {

   make.left.equalTo(self.view.mas_left).offset(0);// 使左边等于self.view的控件,间隔为0;
   make.top.equalTo(self.view.mas_top).offset(0); // 使顶部与self.view的控件的间隔为0;
   make.width.equalTo(self.view.mas_width).multipliedBy(0.5); // 设置宽度为self.view的一半,multipliedBy是倍数的意思,也就是,使宽度等于self.view宽度的0.5倍
   make.height.equalTo(self.view.mas_height).multipliedBy(0.5);// 设置高度为self.view的一半。

}];


[blueView mas_makeConstraints:^(MASConstraintMaker *make) {

   make.width.and.height.equalTo(redView); // 跟redview等宽高
   make.top.equalTo(redView.mas_top); // 与redview顶部对齐
   make.leading.equalTo(redView.mas_right); // 与 redview的间隔为0

}];

[yellow mas_makeConstraints:^(MASConstraintMaker *make) {

   make.width.and.height.equalTo(redView); // 跟redview等宽高
   make.top.equalTo(redView.mas_bottom); // 与 redview的间隔为0
   make.leading.equalTo(redView); // 与redvie左对齐

}];

[green mas_makeConstraints:^(MASConstraintMaker *make) {

   make.width.and.height.equalTo(redView); // 跟redview等宽高
   make.top.equalTo(yellow.mas_top); // 与yellow顶部对齐
   make.leading.equalTo(yellow.mas_right); // 与 yellow的间隔为0

}];

PS:需要下载第三库 Masonry ,并导入 #import "Masonry.h"

Masonry 下的 Autolayout Animation

UIView *redView = [[UIView alloc]init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
    
UIView *greenView = [[UIView alloc]init];
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
self.greenView = greenView;
    
UIView *blueView = [[UIView alloc]init];
blueView.backgroundColor  = [UIColor blueColor];
[self.view addSubview:blueView];
    
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
   make.left.equalTo(self.view.mas_left).offset(20);
   make.bottom.equalTo(self.view.mas_bottom).offset(-20);
   make.width.equalTo(self.view.mas_width).multipliedBy(0.2);
   make.height.equalTo(self.view.mas_height).multipliedBy(0.2);
}];
    
[greenView mas_makeConstraints:^(MASConstraintMaker *make) {
   make.left.equalTo(redView.mas_right).offset(20);
   make.bottom.equalTo(self.view.mas_bottom).offset(-20);
   make.width.equalTo(self.view.mas_width).multipliedBy(0.2);
   make.height.equalTo(self.view.mas_height).multipliedBy(0.2);
}];
    
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
   make.left.equalTo(greenView.mas_right).offset(20);
   make.bottom.equalTo(self.view.mas_bottom).offset(-20);
   make.width.equalTo(self.view.mas_width).multipliedBy(0.2);
   make.height.equalTo(self.view.mas_height).multipliedBy(0.2);
   make.left.equalTo(redView.mas_right).offset(20).priority(250);
}]; 

让我们最后加几行代码,来实现这个动画吧!

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //先把绿色方块从父视图上移除
    [self.greenView removeFromSuperview];
    //动画更新界面
    [UIView animateWithDuration:1.0f animations:^{
        [self.view layoutIfNeeded];
    }];
}

运行效果


总结 Autolayout 使用

  1. 以后一律使用autolayout吗?除了在storyboard中使用autolayout,代码方式autolayout如何使用?

    • 当需要展示的内容很多并且尺寸不固定;
    • 程序需支持屏幕旋转(主要是iPad程序,iPhone程序横屏的场景有点非主流);
    • 程序通用于iPhone和iPad;
  2. 使用autolayout 利弊

    • 好处:可视化,实现简单功能很节省时间
    • 坏处:storyboard 使用 autolayout,移动一个控件就会让弄乱那些约束;
  3. autolayout有没有局限性和解决不了的问题?兼容性怎么样?效率怎么样

    • autolayout对view transforms支持的不好,这里有帖子详细描述了这个问题
    • 至于兼容性,只从iOS6就已经提出了autolayout的概念,大部分用户应该是使用iOS7和iOS8系统,所以兼容性问题不会太大,但size class是iOS8才有的概念,所以还有有一定的适配工作量

参考的帖子

iOS Autolayout解读

iOS Autolayout之Masonry解读

storyboard中autolayout和size class的使用详解

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

推荐阅读更多精彩内容