iOS 循環(huán)滾動(dòng)視圖垦巴,包含文字滾動(dòng)媳搪,banner 滾動(dòng)

iOS 循環(huán)滾動(dòng)視圖,包含文字滾動(dòng)骤宣,banner 滾動(dòng)

效果圖:

Demo.gif

demo 地址:
https://github.com/karosLi/KLRecycleScrollView

功能:

  • 支持上下滾動(dòng)和左右滾動(dòng)
  • 支持自定義子視圖
  • 支持分頁和不分頁
  • 支持自動(dòng)滾動(dòng)

實(shí)現(xiàn)代碼:

//
//  KLRecycleScrollView.m
//  KLRecycleScrollView
//
//  Created by karos li on 2017/12/25.
//  Copyright ? 2017年 karos. All rights reserved.
//

#import "KLRecycleScrollView.h"

@class KLInfiniteScrollView;
@protocol KLInfiniteScrollViewDelegate <NSObject>

- (UIView *)infiniteScrollView:(KLInfiniteScrollView *)infiniteScrollView viewForItemAtIndex:(NSInteger)index;
- (void)infiniteScrollView:(KLInfiniteScrollView *)infiniteScrollView didSelectView:(UIView *)view forItemAtIndex:(NSInteger)index;

@end

@interface KLInfiniteScrollView : UIScrollView

@property (nonatomic, strong, readonly) NSMutableArray *visibleViews;
@property (nonatomic, weak) id<KLInfiniteScrollViewDelegate> infiniteDelegate;

// 是否是水平布局
@property (nonatomic, assign) BOOL isHorLayout;

- (void)reloadData:(NSInteger)numberOfItems;

// 獲取子視圖距離最左邊的距離
- (CGFloat)getDistanceToLeftEdge:(UIView *)view;

// 獲取子視圖距離最上邊的距離
- (CGFloat)getDistanceToTopEdge:(UIView *)view;

@end

@interface KLInfiniteScrollView ()

@property (nonatomic, strong) NSMutableArray *visibleViews;
@property (nonatomic, strong) UIView *containerView;

@property (nonatomic, assign) NSInteger numberOfItems;
@property (nonatomic, assign) NSInteger rightMostVisibleViewIndex;
@property (nonatomic, assign) NSInteger leftMostVisibleViewIndex;
@property (nonatomic, assign) NSInteger topMostVisibleViewIndex;
@property (nonatomic, assign) NSInteger bottomMostVisibleViewIndex;

@end

@implementation KLInfiniteScrollView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    self.isHorLayout = YES;
    self.contentSize = CGSizeMake(5000, self.frame.size.height);
    self.visibleViews = [[NSMutableArray alloc] init];
    
    self.containerView = [[UIView alloc] init];
    self.containerView.frame = CGRectMake(0, 0, self.contentSize.width, self.contentSize.height);
    [self addSubview:self.containerView];
    
    self.bounces = NO;
    self.showsHorizontalScrollIndicator = NO;
    self.showsVerticalScrollIndicator = NO;
    
    return self;
}

#pragma mark - public
- (void)reloadData:(NSInteger)numberOfItems {
    self.numberOfItems = numberOfItems;
    [self setNeedsLayout];
}

- (void)setIsHorLayout:(BOOL)isHorLayout {
    _isHorLayout = isHorLayout;
    [self.visibleViews removeAllObjects];
    if (isHorLayout) {
        self.contentSize = CGSizeMake(5000, self.frame.size.height);
        self.containerView.frame = CGRectMake(0, 0, self.contentSize.width, self.contentSize.height);
    } else {
        self.contentSize = CGSizeMake(self.frame.size.width, 5000);
        self.containerView.frame = CGRectMake(0, 0, self.contentSize.width, self.contentSize.height);
    }
}

- (CGFloat)getDistanceToLeftEdge:(UIView *)view {
    CGRect visibleBounds = [self convertRect:[self bounds] toView:self.containerView];
    return CGRectGetMinX(view.frame) - CGRectGetMinX(visibleBounds);
}

- (CGFloat)getDistanceToTopEdge:(UIView *)view {
    CGRect visibleBounds = [self convertRect:[self bounds] toView:self.containerView];
    return CGRectGetMinY(view.frame) - CGRectGetMinY(visibleBounds);
}

#pragma mark - gesture
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UIView *hitView;
    for (UIView *view in self.containerView.subviews) {
        CGPoint point = [touches.anyObject locationInView:view];
        BOOL hasHit = [view pointInside:point withEvent:event];
        if (hasHit) {
            hitView = view;
            break;
        }
    }
    
    if (hitView.tag >= 20000) {
        NSInteger index = hitView.tag - 20000;
        if ([self.infiniteDelegate respondsToSelector:@selector(infiniteScrollView:didSelectView:forItemAtIndex:)]) {
            [self.infiniteDelegate infiniteScrollView:self didSelectView:hitView forItemAtIndex:index];
        }
    }
}

#pragma mark - Layout

// recenter content periodically to achieve impression of infinite scrolling
- (void)recenterInHorIfNecessary {
    CGPoint currentOffset = [self contentOffset];
    CGFloat contentWidth = [self contentSize].width;
    CGFloat centerOffsetX = (contentWidth - [self bounds].size.width) / 2.0;
    CGFloat distanceFromCenter = fabs(currentOffset.x - centerOffsetX);
    
    if (distanceFromCenter > (contentWidth / 4.0)) {
        self.contentOffset = CGPointMake(centerOffsetX, currentOffset.y);
        
        // move content by the same amount so it appears to stay still
        for (UIView *label in self.visibleViews) {
            CGPoint center = [self.containerView convertPoint:label.center toView:self];
            center.x += (centerOffsetX - currentOffset.x);
            label.center = [self convertPoint:center toView:self.containerView];
        }
    }
}

- (void)recenterInVerIfNecessary {
    CGPoint currentOffset = [self contentOffset];
    CGFloat contentHeight = [self contentSize].height;
    CGFloat centerOffsetY = (contentHeight - [self bounds].size.height) / 2.0;
    CGFloat distanceFromCenter = fabs(currentOffset.y - centerOffsetY);
    
    if (distanceFromCenter > (contentHeight / 4.0)) {
        self.contentOffset = CGPointMake(currentOffset.x, centerOffsetY);
        
        // move content by the same amount so it appears to stay still
        for (UIView *label in self.visibleViews) {
            CGPoint center = [self.containerView convertPoint:label.center toView:self];
            center.y += (centerOffsetY - currentOffset.y);
            label.center = [self convertPoint:center toView:self.containerView];
        }
    }
}


- (void)layoutSubviews {
    if (self.numberOfItems > 0) {
        if (self.isHorLayout) {
            [self recenterInHorIfNecessary];
            
            // tile content in visible bounds
            CGRect visibleBounds = [self convertRect:[self bounds] toView:self.containerView];
            CGFloat minimumVisibleX = CGRectGetMinX(visibleBounds);
            CGFloat maximumVisibleX = CGRectGetMaxX(visibleBounds);
            
            [self tileViewsFromMinX:minimumVisibleX toMaxX:maximumVisibleX];
        } else {
            [self recenterInVerIfNecessary];
            
            // tile content in visible bounds
            CGRect visibleBounds = [self convertRect:[self bounds] toView:self.containerView];
            CGFloat minimumVisibleY = CGRectGetMinY(visibleBounds);
            CGFloat maximumVisibleY = CGRectGetMaxY(visibleBounds);
            
            [self tileViewsFromMinY:minimumVisibleY toMaxY:maximumVisibleY];
        }
    }
    
    [super layoutSubviews];
}

#pragma mark - hor View Tiling

- (CGFloat)placeNewViewOnRight:(CGFloat)rightEdge {
    _rightMostVisibleViewIndex++;
    if (_rightMostVisibleViewIndex == self.numberOfItems) {
        _rightMostVisibleViewIndex = 0;
    }
    
    UIView *view;
    if ([self.infiniteDelegate respondsToSelector:@selector(infiniteScrollView:viewForItemAtIndex:)]) {
        view = [self.infiniteDelegate infiniteScrollView:self viewForItemAtIndex:_rightMostVisibleViewIndex];
    }
    
    if (!view) {
        view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)];
    }
    
    view.tag = 20000 + _rightMostVisibleViewIndex;
    [_containerView addSubview:view];
    [_visibleViews addObject:view]; // add rightmost label at the end of the array
    
    CGRect frame = [view frame];
    frame.origin.x = rightEdge;
    frame.origin.y = 0;
    [view setFrame:frame];
    return CGRectGetMaxX(frame);
}

- (CGFloat)placeNewViewOnLeft:(CGFloat)leftEdge {
    _leftMostVisibleViewIndex--;
    if (_leftMostVisibleViewIndex < 0) {
        _leftMostVisibleViewIndex = self.numberOfItems - 1;
    }

    UIView *view;
    if ([self.infiniteDelegate respondsToSelector:@selector(infiniteScrollView:viewForItemAtIndex:)]) {
        view = [self.infiniteDelegate infiniteScrollView:self viewForItemAtIndex:_leftMostVisibleViewIndex];
    }
    
    if (!view) {
        view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)];
    }
    
    view.tag = 20000 + _leftMostVisibleViewIndex;
    [_containerView addSubview:view];
    [_visibleViews insertObject:view atIndex:0]; // add leftmost label at the beginning of the array
    
    CGRect frame = [view frame];
    frame.origin.x = leftEdge - frame.size.width;
    frame.origin.y = 0;
    [view setFrame:frame];
    
    return CGRectGetMinX(frame);
}

- (void)tileViewsFromMinX:(CGFloat)minimumVisibleX toMaxX:(CGFloat)maximumVisibleX {
    // the upcoming tiling logic depends on there already being at least one label in the visibleLabels array, so
    // to kick off the tiling we need to make sure there's at least one label
    if ([_visibleViews count] == 0) {
        _rightMostVisibleViewIndex = -1;
        _leftMostVisibleViewIndex = 0;
        [self placeNewViewOnRight:minimumVisibleX];
    }
    
    // add labels that are missing on right side
    UIView *lastView = [_visibleViews lastObject];
    CGFloat rightEdge = CGRectGetMaxX([lastView frame]);
    
    while (rightEdge < maximumVisibleX) {
        rightEdge = [self placeNewViewOnRight:rightEdge];
    }
    
    // add labels that are missing on left side
    UIView *firstView = _visibleViews[0];
    CGFloat leftEdge = CGRectGetMinX([firstView frame]);
    while (leftEdge > minimumVisibleX) {
        leftEdge = [self placeNewViewOnLeft:leftEdge];
    }
    
    // remove labels that have fallen off right edge
    lastView = [_visibleViews lastObject];
    while ([lastView frame].origin.x > maximumVisibleX) {
        [lastView removeFromSuperview];
        [_visibleViews removeLastObject];
        lastView = [_visibleViews lastObject];
        
        _rightMostVisibleViewIndex--;
        if (_rightMostVisibleViewIndex < 0) {
            _rightMostVisibleViewIndex = self.numberOfItems - 1;
        }
    }
    
    // remove labels that have fallen off left edge
    firstView = _visibleViews[0];
    while (CGRectGetMaxX([firstView frame]) < minimumVisibleX) {
        [firstView removeFromSuperview];
        [_visibleViews removeObjectAtIndex:0];
        firstView = _visibleViews[0];
        
        _leftMostVisibleViewIndex++;
        if (_leftMostVisibleViewIndex == self.numberOfItems) {
            _leftMostVisibleViewIndex = 0;
        }
    }
}

#pragma mark - ver View Tiling

- (CGFloat)placeNewViewOnBottom:(CGFloat)bottomEdge {
    _bottomMostVisibleViewIndex++;
    if (_bottomMostVisibleViewIndex == self.numberOfItems) {
        _bottomMostVisibleViewIndex = 0;
    }
    
    UIView *view;
    if ([self.infiniteDelegate respondsToSelector:@selector(infiniteScrollView:viewForItemAtIndex:)]) {
        view = [self.infiniteDelegate infiniteScrollView:self viewForItemAtIndex:_bottomMostVisibleViewIndex];
    }
    
    if (!view) {
        view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)];
    }
    
    view.tag = 20000 + _bottomMostVisibleViewIndex;
    [_containerView addSubview:view];
    [_visibleViews addObject:view]; // add rightmost label at the end of the array
    
    CGRect frame = [view frame];
    frame.origin.x = 0;
    frame.origin.y = bottomEdge;
    [view setFrame:frame];
    return CGRectGetMaxY(frame);
}

- (CGFloat)placeNewViewOnTop:(CGFloat)topEdge {
    _topMostVisibleViewIndex--;
    if (_topMostVisibleViewIndex < 0) {
        _topMostVisibleViewIndex = self.numberOfItems - 1;
    }
    
    UIView *view;
    if ([self.infiniteDelegate respondsToSelector:@selector(infiniteScrollView:viewForItemAtIndex:)]) {
        view = [self.infiniteDelegate infiniteScrollView:self viewForItemAtIndex:_topMostVisibleViewIndex];
    }
    
    if (!view) {
        view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)];
    }
    
    view.tag = 20000 + _topMostVisibleViewIndex;
    [_containerView addSubview:view];
    [_visibleViews insertObject:view atIndex:0]; // add leftmost label at the beginning of the array
    
    CGRect frame = [view frame];
    frame.origin.x = 0;
    frame.origin.y = topEdge - frame.size.height;
    [view setFrame:frame];
    
    return CGRectGetMinY(frame);
}

- (void)tileViewsFromMinY:(CGFloat)minimumVisibleY toMaxY:(CGFloat)maximumVisibleY {
    // the upcoming tiling logic depends on there already being at least one label in the visibleLabels array, so
    // to kick off the tiling we need to make sure there's at least one label
    if ([_visibleViews count] == 0) {
        _bottomMostVisibleViewIndex = -1;
        _topMostVisibleViewIndex = 0;
        [self placeNewViewOnBottom:minimumVisibleY];
    }
    
    // add labels that are missing on right side
    UIView *lastView = [_visibleViews lastObject];
    CGFloat bottomEdge = CGRectGetMaxY([lastView frame]);
    
    while (bottomEdge < maximumVisibleY) {
        bottomEdge = [self placeNewViewOnBottom:bottomEdge];
    }
    
    // add labels that are missing on left side
    UIView *firstView = _visibleViews[0];
    CGFloat topEdge = CGRectGetMinY([firstView frame]);
    while (topEdge > minimumVisibleY) {
        topEdge = [self placeNewViewOnTop:topEdge];
    }
    
    // remove labels that have fallen off right edge
    lastView = [_visibleViews lastObject];
    while ([lastView frame].origin.y > maximumVisibleY) {
        [lastView removeFromSuperview];
        [_visibleViews removeLastObject];
        lastView = [_visibleViews lastObject];
        
        _bottomMostVisibleViewIndex--;
        if (_bottomMostVisibleViewIndex < 0) {
            _bottomMostVisibleViewIndex = self.numberOfItems - 1;
        }
    }
    
    // remove labels that have fallen off left edge
    firstView = _visibleViews[0];
    while (CGRectGetMaxY([firstView frame]) < minimumVisibleY) {
        [firstView removeFromSuperview];
        [_visibleViews removeObjectAtIndex:0];
        firstView = _visibleViews[0];
        
        _topMostVisibleViewIndex++;
        if (_topMostVisibleViewIndex == self.numberOfItems) {
            _topMostVisibleViewIndex = 0;
        }
    }
}

@end

@interface KLRecycleScrollView() <UIScrollViewDelegate, KLInfiniteScrollViewDelegate>

@property (strong, nonatomic) KLInfiniteScrollView *scrollView;
@property (strong, nonatomic) NSMutableArray *containerViews;

@property (assign, nonatomic) NSInteger totalItemsCount;
@property (strong, nonatomic) NSTimer *timer;

@end

@implementation KLRecycleScrollView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    self.scrollInterval = 3.5;
    [self setupView];
    
    return self;
}

- (void)setupView {
    self.scrollView = [[KLInfiniteScrollView alloc] initWithFrame:self.bounds];
    self.scrollView.delegate = self;
    self.scrollView.infiniteDelegate = self;
    [self addSubview:self.scrollView];
}

#pragma mark - public methods
- (void)reloadData:(NSInteger)totalItemsCount {
    self.totalItemsCount = totalItemsCount;
    [self.scrollView reloadData:totalItemsCount];
    
    [self startTimer];
}

- (void)setPagingEnabled:(BOOL)pagingEnabled {
    _pagingEnabled = pagingEnabled;
    self.scrollView.decelerationRate = pagingEnabled ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
}

- (void)setDirection:(KLRecycleScrollViewDirection)direction {
    _direction = direction;
    
    if (self.direction == KLRecycleScrollViewDirectionLeft || self.direction == KLRecycleScrollViewDirectionRight) {
        self.scrollView.isHorLayout = YES;
    } else if (self.direction == KLRecycleScrollViewDirectionTop || self.direction == KLRecycleScrollViewDirectionBottom) {
        self.scrollView.isHorLayout = NO;
    }
}

#pragma mark - timer
- (void)fireTimer {
    [UIView animateWithDuration:0.75 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        if (self.direction == KLRecycleScrollViewDirectionLeft) {
            CGPoint contentOffset = self.scrollView.contentOffset;
            [self.scrollView setContentOffset:CGPointMake(contentOffset.x + self.bounds.size.width, 0) animated:NO];
        } else if (self.direction == KLRecycleScrollViewDirectionRight) {
            CGPoint contentOffset = self.scrollView.contentOffset;
            [self.scrollView setContentOffset:CGPointMake(contentOffset.x - self.bounds.size.width, 0) animated:NO];
        } else if (self.direction == KLRecycleScrollViewDirectionTop) {
            CGPoint contentOffset = self.scrollView.contentOffset;
            [self.scrollView setContentOffset:CGPointMake(0, contentOffset.y + self.bounds.size.height) animated:NO];
        } else if (self.direction == KLRecycleScrollViewDirectionBottom) {
            CGPoint contentOffset = self.scrollView.contentOffset;
            [self.scrollView setContentOffset:CGPointMake(0, contentOffset.y - self.bounds.size.height) animated:NO];
        }
    } completion:^(BOOL finished) {
    }];
}

- (void)configTimer {
    self.timer = [NSTimer timerWithTimeInterval:self.scrollInterval target:self selector:@selector(fireTimer) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)startTimer {
    if (self.timerEnabled && !self.timer) {
        [self configTimer];
    }
}

- (void)stopTimer {
    if (self.timerEnabled) {
        [self.timer invalidate];
        self.timer = nil;
    }
}

#pragma mark - KLInfiniteScrollViewDelegate
- (UIView *)infiniteScrollView:(KLInfiniteScrollView *)infiniteScrollView viewForItemAtIndex:(NSInteger)index {
    UIView *subview;
    if ([self.delegate respondsToSelector:@selector(recycleScrollView:viewForItemAtIndex:)]) {
        subview = [self.delegate recycleScrollView:self viewForItemAtIndex:index];
    }
    
    subview.frame = self.bounds;
    return subview;
}

- (void)infiniteScrollView:(KLInfiniteScrollView *)infiniteScrollView didSelectView:(UIView *)view forItemAtIndex:(NSInteger)index {
    if ([self.delegate respondsToSelector:@selector(recycleScrollView:didSelectView:forItemAtIndex:)]) {
        [self.delegate recycleScrollView:self didSelectView:view forItemAtIndex:index];
    }
}

#pragma mark - override
- (void)setClipsToBounds:(BOOL)clipsToBounds {
    [super setClipsToBounds:clipsToBounds];
    self.scrollView.clipsToBounds = clipsToBounds;
}

#pragma mark - scroll view deleaget
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
    if (self.pagingEnabled) {
        if (self.direction == KLRecycleScrollViewDirectionLeft || self.direction == KLRecycleScrollViewDirectionRight) {
            NSInteger width = self.bounds.size.width;
            NSInteger extra = 0;
            if (velocity.x != 0) {
                extra = velocity.x > 0 ? width : -width;
            }
            
            CGPoint targetOffset = [self getLeftestViewToLeftEdge];
            targetContentOffset->x = targetOffset.x + extra;
            targetContentOffset->y = targetOffset.y;
        } else if (self.direction == KLRecycleScrollViewDirectionTop || self.direction == KLRecycleScrollViewDirectionBottom) {
            NSInteger height = self.bounds.size.height;
            NSInteger extra = 0;
            if (velocity.y != 0) {
                extra = velocity.y > 0 ? height : -height;
            }
            
            CGPoint targetOffset = [self getTopestViewToTopEdge];
            targetContentOffset->x = targetOffset.x;
            targetContentOffset->y = targetOffset.y + extra;
        }
    }
}

- (CGPoint)getLeftestViewToLeftEdge {
    CGPoint offset = self.scrollView.contentOffset;

    __block CGFloat minDistanceFromLeftEdge = MAXFLOAT;
    __block UIView *minDistanceFromLeftEdgeView;

    __weak typeof(self) weakSelf = self;
    [self.scrollView.visibleViews enumerateObjectsUsingBlock:^(id  _Nonnull view, NSUInteger idx, BOOL * _Nonnull stop) {
        CGFloat distanceToLeftEdge = [weakSelf.scrollView getDistanceToLeftEdge:view];
        if (distanceToLeftEdge < fabs(minDistanceFromLeftEdge)) {
            minDistanceFromLeftEdge = distanceToLeftEdge;
            minDistanceFromLeftEdgeView = view;
        }
    }];

    CGFloat targetX = offset.x + minDistanceFromLeftEdge;
    CGPoint targetOffset = CGPointMake(targetX, offset.y);

    return targetOffset;
}

- (CGPoint)getTopestViewToTopEdge {
    CGPoint offset = self.scrollView.contentOffset;
    
    __block CGFloat minDistanceFromTopEdge = MAXFLOAT;
    __block UIView *minDistanceFromTopEdgeView;
    
    __weak typeof(self) weakSelf = self;
    [self.scrollView.visibleViews enumerateObjectsUsingBlock:^(id  _Nonnull view, NSUInteger idx, BOOL * _Nonnull stop) {
        CGFloat distanceToTopEdge = [weakSelf.scrollView getDistanceToTopEdge:view];
        if (distanceToTopEdge < fabs(minDistanceFromTopEdge)) {
            minDistanceFromTopEdge = distanceToTopEdge;
            minDistanceFromTopEdgeView = view;
        }
    }];
    
    CGFloat targetY = offset.y + minDistanceFromTopEdge;
    CGPoint targetOffset = CGPointMake(offset.x, targetY);
    
    return targetOffset;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    [self stopTimer];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (scrollView == self.scrollView) {
        if (!decelerate) {
            [self startTimer];
        }
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (scrollView == self.scrollView) {
        [self startTimer];
    }
}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秦爆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子憔披,更是在濱河造成了極大的恐慌等限,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芬膝,死亡現(xiàn)場離奇詭異望门,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)锰霜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進(jìn)店門筹误,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人癣缅,你說我怎么就攤上這事纫事。” “怎么了所灸?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵丽惶,是天一觀的道長。 經(jīng)常有香客問我爬立,道長钾唬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮抡秆,結(jié)果婚禮上奕巍,老公的妹妹穿的比我還像新娘。我一直安慰自己儒士,他們只是感情好的止,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著着撩,像睡著了一般诅福。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拖叙,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天氓润,我揣著相機(jī)與錄音,去河邊找鬼薯鳍。 笑死咖气,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挖滤。 我是一名探鬼主播崩溪,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼斩松!你這毒婦竟也來了悯舟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤砸民,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后奋救,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體岭参,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年尝艘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了演侯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,989評論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡背亥,死狀恐怖秒际,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狡汉,我是刑警寧澤娄徊,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站盾戴,受9級特大地震影響寄锐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一橄仆、第九天 我趴在偏房一處隱蔽的房頂上張望剩膘。 院中可真熱鬧,春花似錦盆顾、人聲如沸怠褐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奈懒。三九已至,卻和暖如春蚕涤,著一層夾襖步出監(jiān)牢的瞬間筐赔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工揖铜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茴丰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓天吓,卻偏偏與公主長得像贿肩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子龄寞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 深度分銷的本質(zhì)依然是大量生產(chǎn)汰规,經(jīng)銷商不關(guān)心賣什么,只關(guān)心賣什么賺錢物邑,沒有人站在消費(fèi)者的角度思考問題溜哮。一旦市場壓力過...
    殷春燕閱讀 384評論 0 0
  • 晚上下班之后一個(gè)人去看房,過了年后的房價(jià)都漲了幾番色解,貴的嚇人茂嗓,出了地鐵站走了很久的路程,才到一個(gè)出租房科阎,兩室的老房...
    汐漫閱讀 654評論 2 1
  • 今天去玩啦述吸! 發(fā)現(xiàn)自己還是很不懂事的不喜歡開車… 額 說到這里感覺故事要說完了 為什么堅(jiān)持一周了還是不會(huì)講故事呢 ...
    兔子與鹿還有秋天閱讀 146評論 0 0
  • 飛鳥掠過高高的鐘塔 白色的塔尖上 鐘鳴陣陣 我的耳邊 人來人往 綠草的芳香 那是你的方向 略顯灰暗的天空下 你掠過...
    孫滸胡閱讀 242評論 0 2