iOS-UICollectionView入門

一唇敞、UICollectionView介紹

UICollectionView和UICollectionViewController類是iOS6新引進的API煌集,用于展示集合視圖,布局更加靈活败京,可實現(xiàn)多列布局,用法類似于UITableView和UITableViewController類涩哟,但也有所不同。

UICollectionView可以實現(xiàn)如下效果诗鸭,也是一個常用的控件:

二染簇、UICollectiomView使用

UICollectionView的創(chuàng)建和UITableView的創(chuàng)建有所不同:

UITableView的創(chuàng)建只需要設(shè)置frame即可使用

UICollectionView除了需要frame,還需要一個布局參數(shù)

-(id)initWithFrame:(CGRect)frame /* 尺寸 */

collectionViewLayout:(UICollectionViewLayout *)layout;/* 布局參數(shù) */

UITableView可以不需要注冊Cell視圖類强岸,手動創(chuàng)建Cell視圖類

UICollectionView必須注冊視圖類锻弓,才能顯示,不需要手動創(chuàng)建

UICollectionView的布局參數(shù):

1.是一個UICollectionViewLayout類的對象蝌箍,

但我們一般使用它的子類UICollectionViewFlowLayout

2.設(shè)置布局對象的滾動方向?qū)傩詓crollDirection:

typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {

UICollectionViewScrollDirectionVertical,? /*垂直滾動*/

UICollectionViewScrollDirectionHorizontal /* 水平滾動 */

};

3.垂直滾動青灼,表示Cell方塊布局是從左往右,從上到下排列的布局

4.水平滾動妓盲,表示Cell方塊布局是從上往下杂拨,從左到右排列的布局

5.和UITableView不同,UICollectionView只能在這里設(shè)置頂部視圖和底部視圖的大小

6.設(shè)置為垂直滾動時悯衬,頂部和底部視圖的寬度為UICollectionView的寬度弹沽,無法設(shè)置

7.設(shè)置為水平滾動時,頂部和底部視圖的高度為UICollectionView的高度筋粗,無法設(shè)置

UICollectionView的常用對象方法

/* 向容器視圖注冊Cell方塊視圖策橘,有2種方式,一種是類名注冊娜亿,一種是Xib注冊 */

- (void)registerClass:(Class)cellClass /* 視圖類 */

forCellWithReuseIdentifier:(NSString *)identifier;/* 綁定標識 */

- (void)registerNib:(UINib *)nib /* Xib */

forCellWithReuseIdentifier:(NSString *)identifier;/* 綁定標識 */

/* 從緩存池中取出Cell方塊視圖對象丽已,如果緩存池沒有,自動調(diào)用alloc/initWithFrame創(chuàng)建 */

- (UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier

forIndexPath:(NSIndexPath *)indexPath;

/* kind參數(shù)設(shè)置 */

NSString *const UICollectionElementKindSectionHeader;/* 頂部視圖用這個 */

NSString *const UICollectionElementKindSectionFooter;/* 底部視圖用這個 */

/* 向容器視圖注冊頂部視圖或者底部視圖买决,有2種方式沛婴,一種是類名注冊吼畏,一種是Xib注冊 */

- (void)registerClass:(Class)viewClass

forSupplementaryViewOfKind:(NSString *)kind /* 參考上面 */

withReuseIdentifier:(NSString *)identifier;/* 綁定標識 */

- (void)registerNib:(UINib *)nib

forSupplementaryViewOfKind:(NSString *)kind /* 參考上面 */

withReuseIdentifier:(NSString *)identifier;/* 綁定標識 */

/* 從緩存池中取出頂部視圖對象或者底部視圖對象,如果緩存池沒有嘁灯,自動調(diào)用alloc/initWithFrame創(chuàng)建 */

- (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)kind

withReuseIdentifier:(NSString *)identifier

forIndexPath:(NSIndexPath *)indexPath;

UICollectionView的數(shù)據(jù)源方法

@required

/* 設(shè)置容器視圖各個組都有多少個Cell方塊 */

- (NSInteger)collectionView:(UICollectionView *)collectionView

numberOfItemsInSection:(NSInteger)section;

/* 設(shè)置Cell方塊視圖泻蚊,類似于UITableViewCell的設(shè)置 */

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView

cellForItemAtIndexPath:(NSIndexPath *)indexPath;

@optional

/* 容器視圖有多少個組,默認返回1 */

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;

/* 設(shè)置頂部視圖和底部視圖旁仿,通過kind參數(shù)分辨是設(shè)置頂部還是底部 */

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView

viewForSupplementaryElementOfKind:(NSString *)kind

atIndexPath:(NSIndexPath *)indexPath;

UICollectionViewDelegate的常用方法

/* 選中Cell方塊時調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didSelectItemAtIndexPath:(NSIndexPath *)indexPath;

/* 取消選中Cell方塊時調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;

我們使用更多的是UICollectionViewDelegate子協(xié)議UICollectionViewDelegateFlowLayout

該協(xié)議不僅包含父協(xié)議所有方法藕夫,還可以進行一些布局設(shè)置

UICollectionViewDelegateFlowLayout的常用布局方法

/* 設(shè)置每個方塊的尺寸大小 */

- (CGSize)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

/* 設(shè)置方塊視圖和邊界的上下左右間距 */

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

insetForSectionAtIndex:(NSInteger)section;


下面是我自定義的Cell視圖類、頂部視圖類枯冈、底部視圖類,目錄結(jié)構(gòu)如下:


方塊視圖LTCollectionViewCell.h

#import "LTCollectionViewCell.h"

@interface LTCollectionViewCell : UICollectionViewCell

@property (strong, nonatomic) UILabel *textLabel;

/* 方塊視圖的緩存池標示 */

+ (NSString *)cellIdentifier;

/* 獲取方塊視圖對象 */

+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath;

@end

方塊視圖LTCollectionViewCell.m

#import "LTCollectionViewCell.h"

@implementation LTCollectionViewCell

/* 方塊視圖的緩存池標示 */

+ (NSString *)cellIdentifier{

static NSString *cellIdentifier = @"CollectionViewCellIdentifier";

return cellIdentifier;

? }?

/* 獲取方塊視圖對象 */

+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath

{

//從緩存池中尋找方塊視圖對象办悟,如果沒有尘奏,該方法自動調(diào)用alloc/initWithFrame創(chuàng)建一個新的方塊視圖返回

LTCollectionViewCell *cell =

[collectionView dequeueReusableCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]

forIndexPath:indexPath];

return cell;

? }

/* 注冊了方塊視圖后,當緩存池中沒有底部視圖的對象時候病蛉,自動調(diào)用alloc/initWithFrame創(chuàng)建 */

- (instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

//創(chuàng)建label

UILabel *textLabel = [[UILabel alloc] init];

//設(shè)置label尺寸

CGFloat x = 5;

CGFloat y = 5;

CGFloat width = frame.size.width - 10;

CGFloat height = frame.size.height - 10;

textLabel.frame = CGRectMake(x, y, width, height);

//設(shè)置label屬性

textLabel.numberOfLines = 0;

textLabel.textAlignment = NSTextAlignmentCenter;

textLabel.font = [UIFont systemFontOfSize:15];

//添加到父控件

[self.contentView addSubview:textLabel];

self.textLabel = textLabel;

? }

?return self;

}

@end

頂部視圖LTCollectionHeaderView.h

#import ?<UIKit/UIKit.h>

@interface LTCollectionHeaderView : UICollectionReusableView

@property (strong, nonatomic) UILabel *textLabel;

/* 頂部視圖的緩存池標示 */

+ (NSString *)headerViewIdentifier;

/* 獲取頂部視圖對象 */

+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath;

@end

頂部視圖LTCollectionHeaderView.m

#import "LTCollectionHeaderView.h"

@implementation LTCollectionHeaderView

/* 頂部視圖的緩存池標示 */

+ (NSString *)headerViewIdentifier{

static NSString *headerIdentifier = @"headerViewIdentifier";

return headerIdentifier;

?}

/* 獲取頂部視圖對象 */

+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath

{

//從緩存池中尋找頂部視圖對象炫加,如果沒有,該方法自動調(diào)用alloc/initWithFrame創(chuàng)建一個新的頂部視圖返回

LTCollectionHeaderView *headerView =

[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader

withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]

forIndexPath:indexPath];

return headerView;

?}

/* 注冊了頂部視圖后铺然,當緩存池中沒有頂部視圖的對象時候俗孝,自動調(diào)用alloc/initWithFrame創(chuàng)建 */

- (instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

//創(chuàng)建label

UILabel *textLabel = [[UILabel alloc] init];

//設(shè)置label尺寸

CGFloat x = 5;

CGFloat y = 5;

CGFloat width = frame.size.width - 10;

CGFloat height = frame.size.height - 10;

textLabel.frame = CGRectMake(x, y, width, height);

//設(shè)置label屬性

textLabel.numberOfLines = 0;

textLabel.textAlignment = NSTextAlignmentCenter;

//添加到父控件

[self addSubview:textLabel];

self.textLabel = textLabel;

?}

return self;

}

@end

底部視圖LTCollectionFooterView.h

#import ?<UIKit/UIKit.h>

@interface LTCollectionFooterView : UICollectionReusableView

@property (strong, nonatomic) UILabel *textLabel;

/* 底部視圖的緩存池標示 */

+ (NSString *)footerViewIdentifier;

/* 獲取底部視圖對象 */

+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath;

@end

底部視圖LTCollectionFooterView.m

#import "LTCollectionFooterView.h"

@implementation LTCollectionFooterView

/* 底部視圖的緩存池標示 */

+ (NSString *)footerViewIdentifier{

static NSString *footerIdentifier = @"footerViewIdentifier";

return footerIdentifier;

?}

/* 獲取底部視圖對象 */

+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath

{

//從緩存池中尋找底部視圖對象,如果沒有魄健,該方法自動調(diào)用alloc/initWithFrame創(chuàng)建一個新的底部視圖返回

LTCollectionFooterView *footerView =

[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter

withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]

forIndexPath:indexPath];

return footerView;

?}

/* 注冊了底部視圖后赋铝,當緩存池中沒有底部視圖的對象時候,自動調(diào)用alloc/initWithFrame創(chuàng)建 */

- (instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

//創(chuàng)建label

UILabel *textLabel = [[UILabel alloc] init];

//設(shè)置label尺寸

CGFloat x = 5;

CGFloat y = 5;

CGFloat width = frame.size.width - 10;

CGFloat height = frame.size.height - 10;

textLabel.frame = CGRectMake(x, y, width, height);

//設(shè)置label屬性

textLabel.numberOfLines = 0;

textLabel.textAlignment = NSTextAlignmentCenter;

//添加到父控件

[self addSubview:textLabel];

self.textLabel = textLabel;

?}

return self;

}

@end

下面是使用實例:

1. 視圖控制器屬性和相關(guān)方法

#import "ViewController.h"

#import "LTCollectionViewCell.h"

#import "LTCollectionHeaderView.h"

#import "LTCollectionFooterView.h"

@interface ViewController ()@property (strong, nonatomic) UICollectionView *collectionView;/*< 容器視圖 */

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//初始化容器視圖

[self initCollectionView];

}

2. 初始化容器視圖

/* 初始化容器視圖 */

- (void)initCollectionView

{

CGFloat x = 0;

CGFloat y = 20;

CGFloat width = self.view.frame.size.width;

CGFloat height = self.view.frame.size.height - 20;

//創(chuàng)建布局對象

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

//設(shè)置滾動方向為垂直滾動沽瘦,說明方塊是從左上到右下的布局排列方式

layout.scrollDirection = UICollectionViewScrollDirectionVertical;

//設(shè)置頂部視圖和底部視圖的大小革骨,當滾動方向為垂直時,設(shè)置寬度無效析恋,當滾動方向為水平時良哲,設(shè)置高度無效

layout.headerReferenceSize = CGSizeMake(100, 40);

layout.footerReferenceSize = CGSizeMake(100, 40);

//創(chuàng)建容器視圖

CGRect frame = CGRectMake(x, y, width, height);

UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame

collectionViewLayout:layout];

collectionView.delegate = self;//設(shè)置代理

collectionView.dataSource = self;//設(shè)置數(shù)據(jù)源

collectionView.backgroundColor = [UIColor whiteColor];//設(shè)置背景,默認為黑色

//添加到主視圖

[self.view addSubview:collectionView];

self.collectionView = collectionView;

//注冊容器視圖中顯示的方塊視圖

[collectionView registerClass:[LTCollectionViewCell class]

forCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]];

//注冊容器視圖中顯示的頂部視圖

[collectionView registerClass:[LTCollectionHeaderView class]

forSupplementaryViewOfKind:UICollectionElementKindSectionHeader

withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]];

//注冊容器視圖中顯示的底部視圖

[collectionView registerClass:[LTCollectionFooterView class]

forSupplementaryViewOfKind:UICollectionElementKindSectionFooter

withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]];

}

3. UICollectionViewDataSource數(shù)據(jù)源方法

#pragma mark - UICollectionViewDataSource

/* 設(shè)置容器中有多少個組 */

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{

return 10;

?}

/* 設(shè)置每個組有多少個方塊 */

- (NSInteger)collectionView:(UICollectionView *)collectionView

numberOfItemsInSection:(NSInteger)section

{

return 20;

?}

/* 設(shè)置方塊的視圖 */

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView

cellForItemAtIndexPath:(NSIndexPath *)indexPath

{

//獲取cell視圖助隧,內(nèi)部通過去緩存池中取筑凫,如果緩存池中沒有,就自動創(chuàng)建一個新的cell

LTCollectionViewCell *cell =

[LTCollectionViewCell cellWithCollectionView:collectionView

forIndexPath:indexPath];

//設(shè)置cell屬性

cell.contentView.backgroundColor = [UIColor redColor];

cell.textLabel.text = [NSString stringWithFormat:@"Cell %2ld",indexPath.row];

return cell;

?}

/* 設(shè)置頂部視圖和底部視圖 */

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView

viewForSupplementaryElementOfKind:(NSString *)kind

atIndexPath:(NSIndexPath *)indexPath

{

if ( [kind isEqualToString:UICollectionElementKindSectionHeader] ) {//頂部視圖

//獲取頂部視圖

LTCollectionHeaderView *headerView =

[LTCollectionHeaderView headerViewWithCollectionView:collectionView

forIndexPath:indexPath];

//設(shè)置頂部視圖屬性

headerView.backgroundColor = [UIColor orangeColor];

headerView.textLabel.text = [NSString stringWithFormat:@"-Header-%ld-",indexPath.section];

return headerView;

?} else if( [kind isEqualToString:UICollectionElementKindSectionFooter] ) {//底部視圖

//獲取底部視圖

LTCollectionFooterView *footerView =

[LTCollectionFooterView footerViewWithCollectionView:collectionView

forIndexPath:indexPath];

//設(shè)置底部視圖屬性

footerView.backgroundColor = [UIColor greenColor];

footerView.textLabel.text = [NSString stringWithFormat:@"-Footer-%ld-",indexPath.section];

return footerView;

?}?

return nil;

}

4. UICollectionViewDelegateFlowLayout布局代理方法

#pragma mark - UICollectionViewDelegateFlowLayout

/* 設(shè)置各個方塊的大小尺寸 */

- (CGSize)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

sizeForItemAtIndexPath:(NSIndexPath *)indexPath

{

CGFloat width = 50;

CGFloat height = 50;

return CGSizeMake(width, height);

?}

/* 設(shè)置每一組的上下左右間距 */

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

insetForSectionAtIndex:(NSInteger)section

{

return UIEdgeInsetsMake(10, 10, 10, 10);

}

5. 父協(xié)議UICollectionViewDelegate的代理方法

#pragma mark - UICollectionViewDelegate

/* 方塊被選中會調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didSelectItemAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"點擊選擇了第%ld組第%ld個方塊",indexPath.section,indexPath.row);

?}

/* 方塊取消選中會調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didDeselectItemAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"取消選擇第%ld組第%ld個方塊",indexPath.section,indexPath.row);

}

@end

效果圖如下并村,左邊為垂直滾動效果巍实,右邊為水平滾動效果


如果修改下布局代理方法的上下左右邊界距離:

/* 設(shè)置每一組的上下左右間距 */

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

insetForSectionAtIndex:(NSInteger)section

{

return UIEdgeInsetsMake(0, 0, 0, 0);

}



LearnDemo里面的CollectionViewDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市橘霎,隨后出現(xiàn)的幾起案子蔫浆,更是在濱河造成了極大的恐慌,老刑警劉巖姐叁,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓦盛,死亡現(xiàn)場離奇詭異洗显,居然都是意外死亡,警方通過查閱死者的電腦和手機原环,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門挠唆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嘱吗,你說我怎么就攤上這事玄组。” “怎么了谒麦?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵俄讹,是天一觀的道長。 經(jīng)常有香客問我绕德,道長患膛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任耻蛇,我火速辦了婚禮踪蹬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘臣咖。我一直安慰自己跃捣,他們只是感情好,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布夺蛇。 她就那樣靜靜地躺著疚漆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚊惯。 梳的紋絲不亂的頭發(fā)上愿卸,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音截型,去河邊找鬼趴荸。 笑死,一個胖子當著我的面吹牛宦焦,可吹牛的內(nèi)容都是我干的发钝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼波闹,長吁一口氣:“原來是場噩夢啊……” “哼酝豪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起精堕,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤孵淘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后歹篓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘫证,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡揉阎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了背捌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毙籽。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瓤介,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布毅否,位于F島的核電站,受9級特大地震影響乖坠,放射性物質(zhì)發(fā)生泄漏搀突。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一熊泵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甸昏,春花似錦顽分、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至翻默,卻和暖如春缸沃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背修械。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工趾牧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肯污。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓翘单,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蹦渣。 傳聞我的和親對象是個殘疾皇子哄芜,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

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