导航的相关问题

导航本质

导航条也是继承自UIViewController,它有自己的view,我们的view都是放在UIViewControllerWrapperView上面。所以如果我们要自定义一个导航条,可以继承自UIViewController,然后用一个数组管理我们的viewControllers,然后再把viewController的view加到我们定义的导航条的view上面。

导航分为三个区:导航区(nav.navigationBar),内容区(nav.viewControllers),工具区(nav.toolbar)
其中工具区默认被隐藏。

导航内容展示的几种区别

// 透明全局(默认)
- (void)translucentAndAll{
    self.navigationController.navigationBar.translucent = YES;
    self.edgesForExtendedLayout = UIRectEdgeAll;
//    self.automaticallyAdjustsScrollViewInsets = YES;
//    self.extendedLayoutIncludesOpaqueBars = NO;
}

// 透明64
- (void)translucentAnd64{
    self.navigationController.navigationBar.translucent = YES;
    self.edgesForExtendedLayout = UIRectEdgeNone;   // 不拓展它的区域,从导航栏下面开始
}

// 不透明64
- (void)noTranslucentAnd64{
    self.navigationController.navigationBar.translucent = NO;
   // self.edgesForExtendedLayout = UIRectEdgeNone;
}

// 不透明全局
- (void)noTranslucentAndAll{
    self.navigationController.navigationBar.translucent = NO;
    self.extendedLayoutIncludesOpaqueBars = YES; // 延伸区域包括不透明的bar
}

导航条返回按钮既有图片也有文字

可以创建一个view,在view上面添加图片和文字,再调用self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];这句代码,但是系统默认的会和最左边有20的像素


要解决这个20像素的问题,可以将view上添加的控件的x值设为负数,但是这样点击那小于20像素的部分就不会响应事件。如下:

    view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
    view.backgroundColor = [UIColor redColor];
    UIImageView *imageV = [[UIImageView alloc] initWithFrame:CGRectMake(-10, 0, 20, 20)];
    imageV.image = [UIImage imageNamed:@"arrow.png"];
    [view addSubview:imageV];
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];

注意这里只能是将view上添加的控件的x值设为负数,将view的x值设为负数,距离最左边还是20像素,没有意义。

所以最好的解决办法是将view直接添加到navigationBar上面[self.navigationController.navigationBar addSubview:view];。然后在viewWillDisappear的方法中从父控件中移除,才不会影响到下一个界面。

导航条返回按钮只有图片

这里需要将图片渲染,并且只有将navigationBar的backIndicatorImage和backIndicatorTransitionMaskImage两个图片属性都设置为它才会有效果,如下:

    UIImage *image = [UIImage imageNamed:@"arrow.png"];
    //一定要加这句代码,出来的才是图片的颜色,不然一直系统的蓝色
    image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    self.navigationController.navigationBar.backIndicatorImage = image;
    self.navigationController.navigationBar.backIndicatorTransitionMaskImage = image;

另外:self.navigationItem.backBarButtonItem设置的是当前界面用导航推过去的下一个界面的返回按钮。

设置导航栏为透明

self.navigationController.navigationBar.translucent属性必须为YES。
方法一:给navigationBar添加一个透明的背景图片,但是设置它的navigationBar.backgroundColor背景色无效

-(void)transluentStyle{
    [self.navigationController.navigationBar setBackgroundImage:self.image forBarMetrics:UIBarMetricsDefault];
    // 这个方法不行
//    self.navigationController.navigationBar.backgroundColor = [UIColor clearColor];
}
- (UIImage *)image{
    
    UIGraphicsBeginImageContext(CGSizeMake(100, 100));
    [[[UIColor whiteColor] colorWithAlphaComponent:0] setFill];
    UIRectFill(CGRectMake(0, 0, 100, 100));
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

方法二:遍历子控件,并将_UIBarBackground的控件背景设置为透明色

- (void)transluentTwoStyle{
    
    NSArray *ary  = [self.navigationController.navigationBar subviews];
    UIColor *alphaColor = [[UIColor whiteColor] colorWithAlphaComponent:0];
    for (int i = 0; i < ary.count; i++) {
        UIView *view = ary[i];
        view.backgroundColor = alphaColor;

        for (int j = 0; j < view.subviews.count; j++) {
            UIView *subView = view.subviews[j];
            subView.backgroundColor = alphaColor;
            for (int k = 0; k < subView.subviews.count; k++) {
                UIView *subsubView = subView.subviews[k];
                subsubView.backgroundColor = alphaColor;
            }
        }
        if([view isKindOfClass:NSClassFromString(@"_UIBarBackground")]){
            
            view.backgroundColor = alphaColor;

        }
    }
    
}

去掉导航下面的那条黑线

方法一:通过Debug View Hierarchy层级可以看到那根黑线的y坐标是64,在导航栏下面,所以我们只要如下就好
self.navigationController.navigationBar.clipsToBounds = YES;
方法二:老办法,递归遍历找到黑线并隐藏

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"黑线处理";
    // 导航条背景色
    self.navigationController.navigationBar.barTintColor = [UIColor yellowColor];
    UIImageView *iamgeV = [self findBackLineImageV:self.navigationController.navigationBar];
    iamgeV.hidden = YES;
}
- (UIImageView *)findBackLineImageV:(UIView*)view{
    
    // 递归写法
    // 找到了黑线就返回
    if([view isKindOfClass:[UIImageView class]] && view.frame.size.height <= 1){
        return (UIImageView*)view;
    }
    NSArray *viewAry = view.subviews;
    // 如果不是黑线,就遍历它的子view,再走本身这个方法,找出黑线
    for (int i = 0; i < viewAry.count; i++) {
        UIView *tmpV = [self findBackLineImageV:viewAry[i]];
        if (tmpV) {
            return (UIImageView*)tmpV;
        }
    }
    return nil;
}

导航上面Item按钮的距离设置

可以用系统的方法,在两个Item直接加一个空格Item(这种思维也可以用到其他不好控制的布局上面,当要改变两个直接的距离的时候,直接改变中间控件的宽高就可以了)

    NSMutableArray *barItems = [NSMutableArray array];
    UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithTitle:@"Nav" style:UIBarButtonItemStylePlain target:self action:@selector(showNav)];
    UIBarButtonItem *barItemSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
    barItemSpace.width = 60;
    UIBarButtonItem *barItemT = [[UIBarButtonItem alloc] initWithTitle:@"view" style:UIBarButtonItemStylePlain target:self action:@selector(showNavTwo)];
    
    [barItems addObject:barItem];
    [barItems addObject:barItemSpace];
    [barItems addObject:barItemT];
    
    self.navigationItem.rightBarButtonItems = barItems;

导航栏标题

我们也可以自己写一个view,赋给导航条的titleView,如下:

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 0, 50, 50)];
    view.backgroundColor = [UIColor redColor];
    self.navigationItem.titleView = view;

其中这里设置view的x值为20也是没有意义的和leftBarButtonItem一样,它一样还是会居中显示

重点:其实很多有些复杂,用系统不方便的一些设置,我们完全可以不用系统的,直接写一个控件添加到navigationBar上面,然后再在viewWillDisappear的方法中从父控件中移除,不影响到下一个界面就好。

navigationBarHidden和navigationBar.hidden

    self.navigationController.navigationBarHidden = YES;
    self.navigationController.navigationBar.hidden = YES;

第一个方法是navigationController的属性,第二个是navigationBar本身的属性。其中第一个可以看做是执行可以看作是remove操作navigationBar操作[self.navigationController.navigationBar removeFromSuperview];
注意:两个隐藏的方法要分别对应使用,navigationBarHidden设置的为YES,当要显示的时候,也必须是将这个属性设置为NO,不能套用,不然会显示不出来。

导航栏的隐藏还有一种方法,就是通过代理方法来实现,设置self为导航控制器的代理,实现代理方法,在将要显示控制器中设置导航栏隐藏和显示:

@interface WLHomePageController () <UINavigationControllerDelegate>
@end
@implementation WLHomePageController 
#pragma mark - lifeCycle
- (void)viewDidLoad {
    [super viewDidLoad];
    // 设置导航控制器的代理为self
    self.navigationController.delegate = self;
}
#pragma mark - UINavigationControllerDelegate
// 将要显示控制器
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    // 判断要显示的控制器是否是自己
    BOOL isShowHomePage = [viewController isKindOfClass:[self class]];
    [self.navigationController setNavigationBarHidden:isShowHomePage animated:YES];
}

自己实现一个导航返回的动画效果

分析:我们需要用到手势,获取手势的移动距离,从而来进行操作和判断。有点类似于只有两个页面的scrollview的滚动,其中转场的地方就是scrollview,前一个控制器的view和当前控制器的view就相当于scrollview的上面添加的两个view,只是还要包括导航条的操作,不过导航条不太好操作。具体的代码如下,里面有详细的注释:

#import "EOCEOCAnimaTheoryVC.h"
#import "UIView+EOCFrame.h"


@interface EOCEOCAnimaTheoryVC (){
    
    UIView *transferView;
    UIView *preView;
    UINavigationBar *preNavBar;
}

@end

@implementation EOCEOCAnimaTheoryVC

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"动画原理";
    UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleNavTransition:)];
    [self.view addGestureRecognizer:panGes];
    
}
- (void)viewDidAppear:(BOOL)animated{
    
    [super viewDidAppear:animated];
    
    transferView = [self.view superview];  // 它的父控件UIViewControllerWrapperView,就是导航条自己本身的view,其他的view变化都是通过添加在它本身上面的
    if (self.navigationController.viewControllers.count >= 2) {
        
        NSArray *viewCtrAry = self.navigationController.viewControllers;
        preView = ((UIViewController*)[viewCtrAry objectAtIndex:viewCtrAry.count -2]).view; //导航条中的上一个控制器的view
        
    }
}

- (void)handleNavTransition:(UIPanGestureRecognizer*)gesture{
    
    CGPoint gapPoint = [gesture translationInView:gesture.view]; // 获取手势的偏移量
    [gesture setTranslation:CGPointZero inView:gesture.view];  // 每次滑动完置为零,避免累加
    float width = gapPoint.x;
    //CGPoint posPoint = [gesture locationInView:gesture.view];
    
    if (gesture.state == UIGestureRecognizerStateBegan) { // 手势开始
        
        [preView setFrame:CGRectMake(-preView.eocW, preView.eocOrigin.y, preView.eocW, preView.eocH)]; // 将preView添加到self.view的紧挨着左边,但是这时是在屏幕外
        [transferView addSubview:preView];
        [transferView bringSubviewToFront:self.view];
        
//        preNavBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(-[UIScreen mainScreen].bounds.size.width, 0, [UIScreen mainScreen].bounds.size.width, 64)];  // 设置前一个导航栏
//        NSMutableArray *array = [NSMutableArray array];
//        [array addObjectsFromArray:self.navigationController.navigationBar.items];  //获取navigationBar上所有的items
//        [array removeLastObject];  // 移除掉当前navigationBar上的items,就是前一个navigationBar上面所有的items
//        preNavBar.items = array;  // 将items赋给前一个navigationBar
//        [transferView addSubview:preNavBar];  // 添加到转场view上面
        
    }else if(gesture.state == UIGestureRecognizerStateChanged) {  // 手势开始变化
        
        // 将preView和self.view在他们的父控件transferView上都向右移动手势移动的距离长度
        [preView setFrame:CGRectMake(preView.eocOrigin.x + width, preView.eocOrigin.y, preView.eocW, preView.eocH)];
        [self.view setFrame:CGRectMake(self.view.eocOrigin.x + width, self.view.eocOrigin.y, self.view.eocW, self.view.eocH)];
        
//        // 移动当前导航栏
//        self.navigationController.navigationBar.frame = ({
//            CGRect rect = self.navigationController.navigationBar.frame;
//            rect.origin.x = self.view.frame.origin.x + width;
//            rect;
//        });
//        // 移动前一个导航栏
//        preNavBar.frame = ({
//            CGRect rect = preNavBar.frame;
//            rect.origin.x = preNavBar.frame.origin.x + width;
//            rect;
//        });
    }else{
        
        if (self.view.eocOrigin.x > self.view.eocW/2) {  // 当向右滑动超过一半时,屏幕中间还是显示preView,滑过去了
            [UIView animateWithDuration:0.3 animations:^{
                [preView setFrame:CGRectMake(0, preView.eocOrigin.y, preView.eocW, preView.eocH)];  //将前一个控制器view移动到屏幕上
                [self.view setFrame:CGRectMake(self.view.eocW, self.view.eocOrigin.y, self.view.eocW, self.view.eocH)];  //将当前控制器view移动到屏幕外
                
            } completion:^(BOOL finished) {
                NSMutableArray *array = [NSMutableArray array];
                [array addObjectsFromArray:self.navigationController.viewControllers];
                [array removeLastObject];  //移除掉最后一个控制器,即当前控制器
                self.navigationController.viewControllers = array;
                [self.view removeFromSuperview];  //将最后一个控制器,即当前控制器的view从父控件中移除
            }];
        }else{  // 当向右滑动没有超过一半时,屏幕中间还是显示的self.view,没有滑过去
            [UIView animateWithDuration:0.3 animations:^{
                [preView setFrame:CGRectMake(-preView.eocW, preView.eocOrigin.y, preView.eocW, preView.eocH)];
                [self.view setFrame:CGRectMake(0, self.view.eocOrigin.y, self.view.eocW, self.view.eocH)];
            } completion:^(BOOL finished) {
                [preView removeFromSuperview];  //将preView从父控件中移除
            }];
        }
    }
}
@end

其中需要注意的是transferView转场的view就是导航条本身的view:


效果如图:


上面代码中注释的部分,是关于导航条的动画操作,但是会有许多问题,如果打开运行,会有下面的问题,还没深究。另外导航条也有自己的代理UINavigationBarDelegate和代理方法

另外导航条也有自己的代理UINavigationBarDelegate和代理方法

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item;    // called at end of animation of push or immediately if not animated
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;  // same as push methods
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;

替换系统转场动画手势

导航条有个手势属性,我们可以替换掉它


根据打印我们可以看到该手势的方法名为handleNavigationTransition:

    NSArray *targetsArr =  [self.navigationController.interactivePopGestureRecognizer valueForKey:@"targets"];
    id target = [[targetsArr lastObject] valueForKey:@"target"];
    SEL actionSEL = NSSelectorFromString(@"handleNavigationTransition:");
    
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:target action:actionSEL];
    
//    [self.navigationController.interactivePopGestureRecognizer.view addGestureRecognizer:panGesture]; // 导航栏侧滑手势都被替换掉
    [self.view addGestureRecognizer:panGesture];//只是当前页面被替换掉

通过系统的代理模式来写转场动画效果

导航条有自己的代理UINavigationControllerDelegate,我们可以重写它的代理方法来做操作,不然就是执行系统自己的动画效果


- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC  NS_AVAILABLE_IOS(7_0);

其中fromVC为当前控制器,toVC为目标控制器
我们重写这个方法时,由于返回的是一个支持UIViewControllerAnimatedTransitioning协议的对象,而系统没有,所以我们需要自己写一个继承自UIViewControllerAnimatedTransitioning协议的对象。这个协议还需要实现以下两个方法:

// This is used for percent driven interactive transitions, as well as for
// container controllers that have companion animations that might need to
// synchronize with the main animation.
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
// This method can only  be a nop if the transition is interactive and not a percentDriven interactive transition.
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

而最后一个方法里面又有一个协议UIViewControllerContextTransitioning,我们可以在协议中看到传到这个方法的对象transitionContext的一些属性和一些方法。
在最后一个方法打断点输出如图:


其中他的containerView属性对象其实就是导航条的view—— UIViewControllerWrapperView。并通过viewControllerForKey拿到当前控制器和目标控制器,然后我们用拿到的这些控制器在这个方法中实现自己的动画效果。
代码如下:
继承自UINavigationController的类

#import "EOCNavigationCtr.h"
#import "EOCNavAnimation.h"

@interface EOCNavigationCtr ()<UINavigationControllerDelegate, UIGestureRecognizerDelegate>{
    
    UIPercentDrivenInteractiveTransition *_eocAnimaTransProgress;
}

@end

@implementation EOCNavigationCtr

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.delegate = self;
    
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleNavTransition:)];
    panGesture.delegate = self;
    [self.view addGestureRecognizer:panGesture];
    
}

- (void)handleNavTransition:(UIPanGestureRecognizer*)gesture{
    
    CGPoint gapPoint = [gesture translationInView:gesture.view];
    //[gesture setTranslation:CGPointZero inView:gesture.view];
    float width = gapPoint.x;
    float percent = width/[UIScreen mainScreen].bounds.size.width; // 动画完成进度
    
    if (gesture.state == UIGestureRecognizerStateBegan) {
        
        _eocAnimaTransProgress  = [[UIPercentDrivenInteractiveTransition alloc] init];
        [self popViewControllerAnimated:YES];
        
    }else if(gesture.state == UIGestureRecognizerStateChanged) {
        [_eocAnimaTransProgress updateInteractiveTransition:percent];  // 更新进度
    }else{
        
        if (percent > 0.5) {
            [_eocAnimaTransProgress finishInteractiveTransition];  // 大于百分之五十就完成这个动画
        }else{
            [_eocAnimaTransProgress cancelInteractiveTransition];  // 小于百分之五十就不完成这个动画
        }
        _eocAnimaTransProgress = nil;  // 置空
    }
}

// 转场动画
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                            animationControllerForOperation:(UINavigationControllerOperation)operation
                                                         fromViewController:(UIViewController *)fromVC
                                                           toViewController:(UIViewController *)toVC{
    
    if (operation == UINavigationControllerOperationPop) {  // 操作为pop
        EOCNavAnimation *eocNav = [[EOCNavAnimation alloc] init];
        eocNav.nav = self;
        return eocNav;
    }
    return nil;
}

// 控制动画进度
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                                   interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController{
    
    if ([animationController isKindOfClass:[EOCNavAnimation class]]) {  //如果是这个动画就返回它的动画进度
        return _eocAnimaTransProgress;
    }
    return nil;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    /**
     *  这里有两个条件不允许手势执行,1、当前控制器为根控制器;2、如果这个push、pop动画正在执行(私有属性)
     */
    return self.viewControllers.count != 1 && ![[self valueForKey:@"_isTransitioning"] boolValue];
}
@end

继承自UIViewControllerAnimatedTransitioning协议的对象

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface EOCNavAnimation : NSObject<CAAnimationDelegate,UIViewControllerAnimatedTransitioning>{
    id <UIViewControllerContextTransitioning> _transitionContext;
}
@property (nonatomic, strong)UINavigationController *nav;
@end
#import "EOCNavAnimation.h"

@implementation EOCNavAnimation


- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{
    
    return 0.5;  // 返回动画时间
    
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
    
    _transitionContext = transitionContext;
    
    UIView *containView = transitionContext.containerView;
    
    UIViewController *fromViewCtr = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewCtr = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    [containView insertSubview:toViewCtr.view belowSubview:fromViewCtr.view];
    
    /*
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        fromViewCtr.view.transform = CGAffineTransformMakeTranslation([UIScreen mainScreen].bounds.size.width, 0);
    } completion:^(BOOL finished) {
         [_transitionContext completeTransition:![_transitionContext transitionWasCancelled]];
    }];
    */
    
    //复杂动画
    CATransition *st = [CATransition animation];
    st.type = @"cube";
    st.subtype = @"fromLeft";
    st.duration = 0.5;
    st.removedOnCompletion = NO;
    st.fillMode = kCAFillModeForwards;
    st.delegate = self;  // 设置代理,在代理方法中做完成标识,不然返回后不能做任何操作
    [containView.layer addAnimation:st forKey:nil];
    [containView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
}
//  [transitionContext completeTransition:YES]; 没有做completeTransition 完成标识,任何动作都认为在做转场
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    [_transitionContext completeTransition:![_transitionContext transitionWasCancelled]];
}
- (void)animationEnded:(BOOL) transitionCompleted{
    NSLog(@"animationEnded");
}
@end

参考文章
iOS导航栏的正确隐藏方式

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,048评论 25 707
  • 前言的前言 唐巧前辈在微信公众号「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各项指标...
    VincentHK阅读 5,308评论 4 44
  • 嗨,好久不见!除了这句话我不知道怎样才算是最好的问候方式。 那个我曾不屑一顾,不愿向人提起的你,那个我把人生中最美...
    玖月冬暖阅读 554评论 0 3
  • 感赏今天老猫带我去看猫!米国短毛而猫,长得跟大老虎似的! 感赏老猫带我吃寿司!真好吃! 感赏下午蛇蛇就来了~ 感...
    猫公主喵阅读 103评论 0 0
  • 文章原创作者:文茵紫 最近火遍四海八荒的《三生三世十里桃花》看的我难以自拔。目之所及之处,离不开各种关于三生三世的...
    米立丫丫阅读 341评论 0 0