iOS開發(fā)-自定制banner輪播圖

banner.png

前言:對(duì)于banner輪播圖摔笤,相信大家都會(huì)經(jīng)常用到蹭劈。昨天下午看到自己之前用UIScrollView定制的banner輪播圖寫的有點(diǎn)亂,就想著再封裝一個(gè)整齊一點(diǎn)能夠大眾化使用的banner輪播圖名党,于是昨晚用UICollectionView又重新封裝了一個(gè)帝际,感覺用著還不錯(cuò),今天給大家簡(jiǎn)單介紹一下涮拗,希望能夠幫到有需要的朋友乾戏。

原理:使用UICollectionView通過定時(shí)器不斷改變UICollectionView的偏移量來達(dá)到輪播滾動(dòng)的效果,通過UIScrollView的代理方法計(jì)算UICollectionView偏移量并關(guān)聯(lián)到UIPageControlcurrentPage屬性實(shí)現(xiàn)滾動(dòng)的同時(shí)下方UIPageControlcurrentPage跟著做出相應(yīng)的改變三热。

下面給大家正式講解如何來封裝:
首先創(chuàng)建一個(gè)繼承于UIView的類RHBannerView鼓择,在RHBannerView.h中定義外漏的屬性和方法以及用于傳值的代理方法,如下:

#import <UIKit/UIKit.h>
#import "RHBannerModel.h"

// pageControl 所在位置
typedef NS_ENUM (NSInteger, RHBannerViewPageStyle) {
    
    RHBannerViewPageStyleLeft = 0,  // 左邊
    RHBannerViewPageStyleMiddle,    // 中間
    RHBannerViewPageStyleRight      // 右邊
};

@protocol RHBannerViewDelegate;
@interface RHBannerView : UIView
// 代理
@property (nonatomic, weak) id<RHBannerViewDelegate> delegate;
// PageControl所在位置樣式  默認(rèn)靠右
@property (nonatomic, assign) RHBannerViewPageStyle pageStyle;
// PageControl未選中圓點(diǎn)顏色 默認(rèn)灰色
@property (nonatomic, strong) UIColor * pageTintColor;
// PageControl選中圓點(diǎn)顏色  默認(rèn)白色
@property (nonatomic, strong) UIColor * currentPageTintColor;
// 輪播間隔時(shí)間  默認(rèn)3秒
@property (nonatomic, assign) NSTimeInterval intervalTime;

// 定義構(gòu)造方法快速創(chuàng)建對(duì)象
- (instancetype)initWithModels:(NSArray<RHBannerModel *> *)models;
// 定義構(gòu)造方法快速創(chuàng)建對(duì)象
- (instancetype)initWithFrame:(CGRect)frame models:(NSArray<RHBannerModel *> *)models;

/**
 根據(jù)model配置bannerView

 @param models 存儲(chǔ)RHBannerModel對(duì)象的數(shù)組
 */
- (void)configBannerWithModels:(NSArray<RHBannerModel *> *)models;

@end
@protocol RHBannerViewDelegate <NSObject>

@optional
// 點(diǎn)擊圖片
- (void)bannerView:(RHBannerView *)bannerView didSelectAtIndex:(NSInteger)index;

@end

這里定義了一個(gè)枚舉用來設(shè)置下方UIPageControl所在的位置就漾,定義了一個(gè)代理方法用來傳遞當(dāng)前點(diǎn)擊的banner圖是哪一個(gè)呐能,還定制了一個(gè)RHBannerModel來存儲(chǔ)banner圖的信息,這個(gè)model大家可以根據(jù)自己的需求做出相應(yīng)的改動(dòng)抑堡。

外漏的方法中有兩個(gè)是定制的初始化構(gòu)造方法摆出,可以直接傳入banner模型信息的數(shù)組,不需要再次調(diào)用配置banner模型信息的對(duì)象方法首妖;如果初始化方法使用了沒有傳入banner模型信息的init或者initWithFrame偎漫,那么后邊需要調(diào)用配置banner模型信息的對(duì)象方法configBannerWithModels

下面我們來看看在RHBannerView.m里邊的實(shí)現(xiàn)如下:

#import "RHBannerView.h"
#import "RHBannerCell.h"

#define Cell_Collection    @"Cell_Collection"
@interface RHBannerView () <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>

@property (nonatomic, strong) UICollectionView * collection;
@property (nonatomic, strong) UIPageControl * pageControl;
@property (nonatomic, strong) NSTimer * timer;

@property (nonatomic, strong) NSMutableArray * dataArr;

@property (nonatomic, assign) NSInteger page;
@end
@implementation RHBannerView

- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    
    if (self) {
        
        _page = 1;
        _intervalTime = 3;
        [self addSubviews];
        self.pageStyle = RHBannerViewPageStyleRight;
        self.backgroundColor = [UIColor yellowColor];
    }
    return self;
}

- (instancetype)initWithModels:(NSArray<RHBannerModel *> *)models {
    
    self = [super init];
    
    if (self) {
        
        [self configBannerWithModels:models];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame models:(NSArray<RHBannerModel *> *)models {
    
    self = [super initWithFrame:frame];
    
    if (self) {
        
        _page = 1;
        _intervalTime = 3;
        [self addSubviews];
        self.pageStyle = RHBannerViewPageStyleRight;
        self.backgroundColor = [UIColor yellowColor];
        [self configBannerWithModels:models];
    }
    return self;
}

- (void)addSubviews {
    
    [self addSubview:self.collection];
    [self addSubview:self.pageControl];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    _collection.frame = self.bounds;
    [self makeConstraintForPageControlWithPageStyle:self.pageStyle];
    if (self.dataArr.count > 1) {
        
        [_collection setContentOffset:CGPointMake(self.bounds.size.width, 0)];
    }
    [_collection reloadData];
}

#pragma mark - public

- (void)configBannerWithModels:(NSArray<RHBannerModel *> *)models {
    
    [self.dataArr removeAllObjects];
    [self removeTimer];
    _pageControl.numberOfPages = 0;
    
    if (models.count == 0) {
        
        [_collection reloadData];
        return;
    }
    
    if (models.count == 1) {
        
        [self.dataArr addObjectsFromArray:models];
    } else {
        
        [self.dataArr addObject:models.lastObject];
        [self.dataArr addObjectsFromArray:models];
        [self.dataArr addObject:models.firstObject];
        [_collection setContentOffset:CGPointMake(self.bounds.size.width, 0)];
        _pageControl.numberOfPages = models.count;
        [self makeConstraintForPageControlWithPageStyle:self.pageStyle];
        [self addTimer];
    }
    [_collection reloadData];
}

- (void)run {
    
    if (self.dataArr.count > 1) {
        
        [self addTimer];
    }
}

- (void)stop {
    
    [self removeTimer];
}

#pragma mark - private

- (void)makeConstraintForPageControlWithPageStyle:(RHBannerViewPageStyle)pageStyle {
    
    float interval = 15;
    switch (pageStyle) {
        case RHBannerViewPageStyleLeft:
            _pageControl.frame = CGRectMake(10, self.bounds.size.height - 50, self.dataArr.count * interval, 50);
            break;
        case RHBannerViewPageStyleMiddle:
            _pageControl.frame = CGRectMake((self.bounds.size.width - self.dataArr.count * interval) / 2 , self.bounds.size.height - 50, self.dataArr.count * interval, 50);
            break;
        case RHBannerViewPageStyleRight:
            _pageControl.frame = CGRectMake(self.bounds.size.width - 10 - self.dataArr.count * interval, self.bounds.size.height - 50, self.dataArr.count * interval, 50);
            break;
            
        default:
            break;
    }
}

#pragma mark - timer

- (void)addTimer {
    
    if (!self.timer) {
        
        self.timer = [NSTimer scheduledTimerWithTimeInterval:self.intervalTime target:self selector:@selector(bannerRun) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    }
}

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

- (void)bannerRun {
    
    _page++;
    [self.collection setContentOffset:CGPointMake(_page * self.bounds.size.width, 0) animated:YES];
    
    if (_page == self.dataArr.count - 1) {
        
        _page = 1;
    }
}

#pragma mark - collectionView delegate and dataSource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    
    return self.dataArr.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    RHBannerCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:Cell_Collection forIndexPath:indexPath];
    if (indexPath.row < self.dataArr.count) {
        
        RHBannerModel * model = self.dataArr[indexPath.row];
        [cell configCellWithImageUrl:model.picture placeholderImage:[UIImage imageNamed:model.placeholderName]];
    }
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    
    NSInteger index = indexPath.row;
    if (index == 0) {
        
        index = self.dataArr.count - 3;
    } else if (index == self.dataArr.count - 1) {
        
        index = 0;
    } else {
        
        index -= 1;
    }
    if (self.delegate && [self.delegate respondsToSelector:@selector(bannerView:didSelectAtIndex:)]) {
        
        [self.delegate bannerView:self didSelectAtIndex:index];
    }
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    return self.bounds.size;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    if (scrollView == _collection) {
        
        if (self.dataArr.count > 1) {
            
            _page = _collection.contentOffset.x / self.bounds.size.width;
            
            if (_collection.contentOffset.x == 0) {
                
                _pageControl.currentPage = self.dataArr.count - 3;
                [_collection setContentOffset:CGPointMake(self.bounds.size.width * (self.dataArr.count - 2), 0)];
            } else if (_collection.contentOffset.x == self.bounds.size.width * (self.dataArr.count - 1)) {
                
                _pageControl.currentPage = 0;
                [_collection setContentOffset:CGPointMake(self.bounds.size.width, 0)];
            } else if (_collection.contentOffset.x == self.bounds.size.width * _page) {
                
                _pageControl.currentPage = _page - 1;
            }
        }
    }
}

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

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    
    [self addTimer];
}

#pragma mark - setter and getter

- (UICollectionView *)collection {
    
    if (!_collection) {
        
        UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init];
        layout.minimumInteritemSpacing = 0;
        layout.minimumLineSpacing = 0;
        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        UICollectionView * collection = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
        collection.dataSource = self;
        collection.delegate = self;
        collection.bounces = NO;
        collection.pagingEnabled = YES;
        collection.showsHorizontalScrollIndicator = NO;
        collection.backgroundColor = [UIColor whiteColor];
        [collection registerClass:[RHBannerCell class] forCellWithReuseIdentifier:Cell_Collection];
        _collection = collection;
    }
    return _collection;
}

- (UIPageControl *)pageControl {
    
    if (!_pageControl) {
        
        UIPageControl * pageControl = [[UIPageControl alloc] init];
        pageControl.pageIndicatorTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.9];
        pageControl.currentPageIndicatorTintColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9];
        _pageControl = pageControl;
    }
    return _pageControl;
}

- (NSMutableArray *)dataArr {
    
    if (!_dataArr) {
        
        _dataArr = [NSMutableArray array];
    }
    return _dataArr;
}

- (void)setPageStyle:(RHBannerViewPageStyle)pageStyle {
    
    _pageStyle = pageStyle;
    [self makeConstraintForPageControlWithPageStyle:pageStyle];
}

- (void)setPageTintColor:(UIColor *)pageTintColor {
    
    _pageTintColor = pageTintColor;
    self.pageControl.pageIndicatorTintColor = pageTintColor;
}

- (void)setCurrentPageTintColor:(UIColor *)currentPageTintColor {
    
    _currentPageTintColor = currentPageTintColor;
    self.pageControl.currentPageIndicatorTintColor = currentPageTintColor;
}

- (void)setIntervalTime:(NSTimeInterval)intervalTime {
    
    _intervalTime = intervalTime;
    
    if (self.dataArr.count > 0) {
        
        [self removeTimer];
        [self addTimer];
    }
}

@end

這里主要就是UICollectionViewUIPageControl的布局實(shí)現(xiàn)有缆,在UICollectionView的點(diǎn)擊代理方法中進(jìn)行RHBannerView的代理回調(diào)象踊。RHBannerCell只有一個(gè)UIImageView來放banner圖片,其中使用到了第三方庫(kù)SDWebImage妒貌,有需求的朋友可以進(jìn)行修改通危。

OK!到這里封裝就結(jié)束了灌曙,我們來看一下如何使用:

#import "ViewController.h"
#import "RHBannerView.h"

@interface ViewController () <RHBannerViewDelegate>

@property (nonatomic, strong) RHBannerView * bannerView;

@property (nonatomic, strong) RHBannerView * bannerView2;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view addSubview:self.bannerView];
    [self.view addSubview:self.bannerView2];
    [self makeConstraintsForUI];
    
    RHBannerModel * model1 = [[RHBannerModel alloc] init];
    model1.placeholderName = @"001.jpg";
    RHBannerModel * model2 = [[RHBannerModel alloc] init];
    model2.placeholderName = @"002.jpg";
    RHBannerModel * model3 = [[RHBannerModel alloc] init];
    model3.placeholderName = @"003.jpg";
    RHBannerModel * model4 = [[RHBannerModel alloc] init];
    model4.placeholderName = @"004.jpg";
    RHBannerModel * model5 = [[RHBannerModel alloc] init];
    model5.placeholderName = @"005.jpg";
    [_bannerView configBannerWithModels:@[model1, model2, model3, model4, model5]];
}

- (void)makeConstraintsForUI {
    
    [_bannerView mas_makeConstraints:^(MASConstraintMaker *make) {
       
        make.left.mas_equalTo(@0);
        make.top.mas_equalTo(@0);
        make.right.mas_equalTo(@0);
        make.height.mas_equalTo(_bannerView.mas_width).multipliedBy(9/16.0);
    }];
}

#pragma mark - bannerView delegate

- (void)bannerView:(RHBannerView *)bannerView didSelectAtIndex:(NSInteger)index {
    
    if (bannerView == _bannerView) {
        
        NSLog(@"點(diǎn)擊了上邊bannerView第%@個(gè)圖片", @(index));
    } else {
        
        NSLog(@"點(diǎn)擊了下邊bannerView2第%@個(gè)圖片", @(index));
    }
    
}

- (RHBannerView *)bannerView {
    
    if (!_bannerView) {
        
        RHBannerView * bannerView = [[RHBannerView alloc] init];
        bannerView.pageStyle = RHBannerViewPageStyleMiddle;
        bannerView.delegate = self;
        bannerView.pageTintColor = [UIColor lightGrayColor];
        bannerView.currentPageTintColor = [UIColor redColor];
        bannerView.intervalTime = 2;
        _bannerView = bannerView;
    }
    return _bannerView;
}

- (RHBannerView *)bannerView2 {
    
    if (!_bannerView2) {
        
        RHBannerModel * model1 = [[RHBannerModel alloc] init];
        model1.placeholderName = @"001.jpg";
        RHBannerModel * model2 = [[RHBannerModel alloc] init];
        model2.placeholderName = @"002.jpg";
        RHBannerModel * model3 = [[RHBannerModel alloc] init];
        model3.placeholderName = @"003.jpg";
        RHBannerModel * model4 = [[RHBannerModel alloc] init];
        model4.placeholderName = @"004.jpg";
        RHBannerModel * model5 = [[RHBannerModel alloc] init];
        model5.placeholderName = @"005.jpg";
        RHBannerView * bannerView = [[RHBannerView alloc] initWithFrame:CGRectMake(0, 300, self.view.bounds.size.width, 200) models:@[model1, model2, model3, model4, model5]];
        bannerView.delegate = self;
        bannerView.intervalTime = 3;
        _bannerView2 = bannerView;
    }
    return _bannerView2;
}
@end

大家可以看到使用起來無論是初始化創(chuàng)建的時(shí)候添加約束傳入banner圖片信息菊碟,還是后期添加約束傳入banner圖片信息都非常簡(jiǎn)單。下面給大家呈現(xiàn)一下效果圖如下:


banner.gif

對(duì)了在刺,demo已經(jīng)上傳到git上邊逆害,有需要的朋友可以前往下載查看头镊,下載地址為:https://github.com/guorenhao/RHBannerView.git

最后還是希望能夠幫助到有需要的猿友們,希望我們能夠共同成長(zhǎng)進(jìn)步魄幕,愿我們能夠在開發(fā)的道路上越走越遠(yuǎn)相艇!謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纯陨,一起剝皮案震驚了整個(gè)濱河市坛芽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翼抠,老刑警劉巖咙轩,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異阴颖,居然都是意外死亡活喊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門量愧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钾菊,“玉大人,你說我怎么就攤上這事偎肃∩诽蹋” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵软棺,是天一觀的道長(zhǎng)红竭。 經(jīng)常有香客問我,道長(zhǎng)喘落,這世上最難降的妖魔是什么茵宪? 我笑而不...
    開封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮瘦棋,結(jié)果婚禮上稀火,老公的妹妹穿的比我還像新娘。我一直安慰自己赌朋,他們只是感情好凰狞,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沛慢,像睡著了一般赡若。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上团甲,一...
    開封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天逾冬,我揣著相機(jī)與錄音,去河邊找鬼。 笑死身腻,一個(gè)胖子當(dāng)著我的面吹牛产还,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嘀趟,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼脐区,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼懦胞!你這毒婦竟也來了兆衅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤帖渠,失蹤者是張志新(化名)和其女友劉穎尤溜,沒想到半個(gè)月后倔叼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體汗唱,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宫莱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哩罪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片授霸。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖际插,靈堂內(nèi)的尸體忽然破棺而出碘耳,到底是詐尸還是另有隱情,我是刑警寧澤框弛,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布辛辨,位于F島的核電站,受9級(jí)特大地震影響瑟枫,放射性物質(zhì)發(fā)生泄漏斗搞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一慷妙、第九天 我趴在偏房一處隱蔽的房頂上張望僻焚。 院中可真熱鬧,春花似錦膝擂、人聲如沸虑啤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狞山。三九已至,卻和暖如春叉寂,著一層夾襖步出監(jiān)牢的瞬間萍启,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工办绝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伊约,地道東北人姚淆。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像屡律,于是被迫代替她去往敵國(guó)和親腌逢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,855評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)超埋、插件搏讶、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評(píng)論 4 62
  • 早上12點(diǎn)位于烏魯木齊的一家家裝司公里媒惕,三人正圍坐電腦跟前談?wù)摷已b細(xì)節(jié),突然一通電話打到了設(shè)計(jì)師林巧的手機(jī)上来庭。她側(cè)...
    努力紅閱讀 257評(píng)論 0 0
  • 功能:1.提供接口妒蔚,直接調(diào)用添加:左視圖,標(biāo)題月弛,以及右視圖 2.closure(閉包)提供回調(diào)方法肴盏,監(jiān)聽點(diǎn)擊事件 ...
    1693c7e88afe閱讀 2,389評(píng)論 0 1
  • 在法律文件中通常包括定義部分,常見的中文表述有:“……的意思是……”帽衙,“(所稱)……是指……”菜皂,我們常常翻譯成“S...
    六十度冰閱讀 1,332評(píng)論 0 50