使用UICollectionView實現
思路
- 很明顯整體它是一個列表,它的分組是一個列表,它里面的好友列表也是一個列表,所以就可以使用組頭來設置分組列表,使用cell設置好友列表;
- 當點擊組頭的時候會展開好友列表,其實原理上就是單獨刷新某一組的數據。
流程
- 控制器的代碼(HomeViewController):本類主要配置UICollectionView顯示,以及處理組展開/關閉狀態。
#import "HomeViewController.h"
#import "YDWFriendListShowCollectionViewCell.h"
#import "YDWFriendHeaderReusableView.h"static NSString
* const kYDWFriendListShowCollectionViewCellIndentifier
= @"YDWFriendListShowCollectionViewCell";
static NSString
* const kYDWFriendHeaderReusableViewIndentifier
= @"YDWFriendHeaderReusableView";@interface HomeViewController ()<UICollectionViewDelegate
,UICollectionViewDataSource
,FriendHeaderReusableViewDelegate
>
@property(nonatomic
,strong
) UICollectionView
*collectionView
;
@property(nonatomic
,strong
) NSArray
*headerArray
;
@property (nonatomic
, strong
) NSMutableArray
* dataArray
;
@property (nonatomic
, strong
) NSMutableArray
* boolArray
;@end@implementation HomeViewController
- (void)viewDidLoad
{[super viewDidLoad
];[self setupNavigation
];[self addSubviews
];[self getListData
];
}#pragma mark - UICollectionViewDelegate,UICollectionViewDataSource
- (NSInteger
)numberOfSectionsInCollectionView
:(UICollectionView
*)collectionView
{return self.headerArray
.count
;
}- (NSInteger
)collectionView
:(UICollectionView
*)collectionView numberOfItemsInSection
:(NSInteger
)section
{if ([self.boolArray
[section
] boolValue
] == NO
) {return 0;} else {return [self.dataArray
[section
] count
];}
}- (UICollectionViewCell
*)collectionView
:(UICollectionView
*)collectionView cellForItemAtIndexPath
:(NSIndexPath
*)indexPath
{YDWFriendListShowCollectionViewCell
*cell
= [collectionView dequeueReusableCellWithReuseIdentifier
:kYDWFriendListShowCollectionViewCellIndentifier forIndexPath
:indexPath
];cell
.contentView
.backgroundColor
= [UIColor whiteColor
];cell
.nameLabel
.text
= [NSString stringWithFormat
:@"好友%ld", (long)indexPath
.item
];cell
.detailsLabel
.text
= [NSString stringWithFormat
:@"簽名%ld", (long)indexPath
.item
];return cell
;
}- (UICollectionReusableView
*)collectionView
:(UICollectionView
*)collectionView viewForSupplementaryElementOfKind
:(NSString
*)kind atIndexPath
:(NSIndexPath
*)indexPath
{YDWFriendHeaderReusableView
*reusView
= [collectionView dequeueReusableSupplementaryViewOfKind
:UICollectionElementKindSectionHeader withReuseIdentifier
:kYDWFriendHeaderReusableViewIndentifier forIndexPath
:indexPath
];reusView
.delegte
= self;reusView
.backgroundColor
= [UIColor whiteColor
];reusView
.tag
= indexPath
.section
;reusView
.imageView
.image
= [self.boolArray
[indexPath
.section
] boolValue
] ? [UIImage imageNamed
:[NSString stringWithFormat
:@"zhankai"]] : [UIImage imageNamed
:[NSString stringWithFormat
:@"shouqi"]];reusView
.titleLabel
.text
= self.headerArray
[indexPath
.section
];reusView
.numLabel
.text
= [NSString stringWithFormat
:@"%ld/%lu",(long)indexPath
.section
, (unsigned long)[self.dataArray
[indexPath
.section
] count
]];return reusView
;
}#pragma mark - FriendHeaderReusableViewDelegate
- (void)friendHeaderReusableView
:(YDWFriendHeaderReusableView
*)friendHeaderReusableView didSelectItemAtSection
:(NSInteger
)section
{if ([self.boolArray
[section
] boolValue
] == YES
) {[self.boolArray replaceObjectAtIndex
:section withObject
:@NO
];} else {[self.boolArray replaceObjectAtIndex
:section withObject
:@YES
];}[self.collectionView reloadSections
:[NSIndexSet indexSetWithIndex
:section
]];
}#pragma mark - Private Methods
- (void)setupNavigation
{self.navigationItem
.title
= @"聯系人";
}- (void)addSubviews
{self.collectionView
.frame
= CGRectMake(0, 100, SCREEN_WIDTH
, SCREEN_HEIGHT
- 15);[self.view addSubview
:self.collectionView
];
}- (void)getListData
{NSArray
*headerArr
= [NSArray arrayWithObjects
:@"特別關心", @"我的好友", @"朋友", @"家人",nil
];self.headerArray
= headerArr
;NSArray
*itemArr
= [NSArray arrayWithObjects
:@5, @10, @7,@3, nil
];for (int i
= 0; i
< self.headerArray
.count
; i
++) {[self.boolArray addObject
:@NO
];NSMutableArray
* friendArr
= [[NSMutableArray alloc
] init
];for (int j
= 0; j
< [itemArr
[i
] intValue
]; j
++) {[friendArr addObject
:@(j
)];}[self.dataArray addObject
:friendArr
];}[self.collectionView reloadData
];
}#pragma mark - Lazy Loading
- (NSMutableArray
*)dataArray
{if (!_dataArray
) {_dataArray
= [[NSMutableArray alloc
] init
];}return _dataArray
;
}- (NSMutableArray
*)boolArray
{if (!_boolArray
) {_boolArray
= [[NSMutableArray alloc
] init
];}return _boolArray
;
}- (UICollectionView
*)collectionView
{if (!_collectionView
) {UICollectionViewFlowLayout
*layout
= [[UICollectionViewFlowLayout alloc
] init
];layout
.itemSize
= CGSizeMake(SCREEN_WIDTH
, 70);layout
.minimumLineSpacing
= 0;layout
.minimumInteritemSpacing
= 0;layout
.scrollDirection
= UICollectionViewScrollDirectionVertical
;layout
.headerReferenceSize
= CGSizeMake(SCREEN_WIDTH
, 40);_collectionView
= [[UICollectionView alloc
] initWithFrame
:CGRectZero collectionViewLayout
:layout
];_collectionView
.backgroundColor
= [UIColor whiteColor
];_collectionView
.delegate
= self;_collectionView
.dataSource
= self;_collectionView
.alwaysBounceVertical
= YES
;_collectionView
.showsVerticalScrollIndicator
= YES
;[_collectionView registerClass
:[YDWFriendHeaderReusableView class
] forSupplementaryViewOfKind
:UICollectionElementKindSectionHeader withReuseIdentifier
:kYDWFriendHeaderReusableViewIndentifier
];[_collectionView registerClass
:[YDWFriendListShowCollectionViewCell class
] forCellWithReuseIdentifier
:kYDWFriendListShowCollectionViewCellIndentifier
];}return _collectionView
;
}
@end
- YDWFriendHeaderReusableView:本類主要布局組標題以及指示(展開/關閉)控件,其次,通過添加點擊手勢結合委托模式,傳遞tag值。
YDWFriendHeaderReusableView .h和YDWFriendHeaderReusableView.m:
#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN
@class YDWFriendHeaderReusableView
;
@protocol FriendHeaderReusableViewDelegate
<NSObject
>- (void)friendHeaderReusableView
:(YDWFriendHeaderReusableView
*)friendHeaderReusableView didSelectItemAtSection
:(NSInteger
)section
;@end@interface YDWFriendHeaderReusableView
: UICollectionReusableView
@property(nonatomic
,weak
) id
<FriendHeaderReusableViewDelegate
>delegte
;
@property(nonatomic
,weak
) UIImageView
*imageView
;
@property(nonatomic
,weak
) UILabel
*titleLabel
;
@property(nonatomic
,weak
) UILabel
*numLabel
;
@endNS_ASSUME_NONNULL_END
#import "YDWFriendHeaderReusableView.h"@interface YDWFriendHeaderReusableView ()@end@implementation YDWFriendHeaderReusableView
#pragma mark - 初始化
- (instancetype
)initWithFrame
:(CGRect
)frame
{self = [super initWithFrame
:frame
];if (self) {self.userInteractionEnabled
= YES
;UITapGestureRecognizer
*tapGes
= [[UITapGestureRecognizer alloc
] initWithTarget
:self action
:@selector(clickView
:)];[self addGestureRecognizer
:tapGes
];[self addSubviews
];}return self;
}#pragma mark - 設置UI界面
- (void)addSubviews
{UIImageView
*imageView
= [[UIImageView alloc
] init
];[self addSubview
:imageView
];self.imageView
= imageView
;UILabel
*titleLabel
= [[UILabel alloc
] init
];titleLabel
.font
= [UIFont systemFontOfSize
:18];titleLabel
.textColor
= [UIColor darkGrayColor
];[self addSubview
:titleLabel
];self.titleLabel
= titleLabel
;UILabel
*numLabel
= [[UILabel alloc
] init
];numLabel
.font
= [UIFont systemFontOfSize
:14];numLabel
.textAlignment
= NSTextAlignmentRight
;numLabel
.textColor
= [UIColor lightGrayColor
];[self addSubview
:numLabel
];self.numLabel
= numLabel
;}
- (void)layoutSubviews
{[super layoutSubviews
];self.imageView
.frame
= CGRectMake(10, 10, 20, 20);CGFloat numW
= 60;CGFloat titleX
= CGRectGetMaxX(self.imageView
.frame
) + 10;CGFloat titleW
= SCREEN_WIDTH
- titleX
- numW
-15;self.titleLabel
.frame
= CGRectMake(titleX
, 10, titleW
, 20);CGFloat numX
= SCREEN_WIDTH
- numW
- 10;self.numLabel
.frame
= CGRectMake(numX
, 10, numW
, 20);
}#pragma mark - 監聽事件
- (void)clickView
:(UITapGestureRecognizer
*)tapGes
{if ([self.delegte respondsToSelector
:@selector(friendHeaderReusableView
:didSelectItemAtSection
:)]) {[self.delegte friendHeaderReusableView
:self didSelectItemAtSection
:self.tag
];}
}
@end
- YDWFriendListShowCollectionViewCell:主要布局好友信息包括頭像、昵稱以及簽名,具體實現如下:
#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN
@interface YDWFriendListShowCollectionViewCell
: UICollectionViewCell
@property(nonatomic
,weak
) UIImageView
*imageView
;
@property(nonatomic
,weak
) UILabel
*nameLabel
;
@property(nonatomic
,weak
) UILabel
*detailsLabel
;@endNS_ASSUME_NONNULL_END
#import "YDWFriendListShowCollectionViewCell.h"@interface YDWFriendListShowCollectionViewCell ()@end@implementation YDWFriendListShowCollectionViewCell
#pragma mark - 初始化
- (instancetype
)initWithFrame
:(CGRect
)frame
{self = [super initWithFrame
:frame
];if (self) {[self addSubviews
];}return self;
}#pragma mark - 設置UI界面
- (void)addSubviews
{UIImageView
*imageView
= [[UIImageView alloc
] init
];imageView
.layer
.cornerRadius
= 50/2;imageView
.layer
.masksToBounds
= YES
;imageView
.backgroundColor
= [UIColor colorWithRed
:arc4random_uniform(256)/255.0 green
:arc4random_uniform(256)/255.0 blue
:arc4random_uniform(256)/255.0 alpha
:1.0];[self addSubview
:imageView
];self.imageView
= imageView
;UILabel
*nameLabel
= [[UILabel alloc
] init
];nameLabel
.font
= [UIFont systemFontOfSize
:18];nameLabel
.textColor
= [UIColor darkGrayColor
];[self addSubview
:nameLabel
];self.nameLabel
= nameLabel
;UILabel
*detailsLabel
= [[UILabel alloc
] init
];detailsLabel
.font
= [UIFont systemFontOfSize
:14];detailsLabel
.textAlignment
= NSTextAlignmentLeft
;detailsLabel
.textColor
= [UIColor lightGrayColor
];[self addSubview
:detailsLabel
];self.detailsLabel
= detailsLabel
;}
- (void)layoutSubviews
{[super layoutSubviews
];self.imageView
.frame
= CGRectMake(10, 10, 50, 50);CGFloat nameX
= CGRectGetMaxX(self.imageView
.frame
) + 10;CGFloat nameW
= SCREEN_WIDTH
- nameX
-10;self.nameLabel
.frame
= CGRectMake(nameX
, 10, nameW
, 20);CGFloat detailsX
= CGRectGetMaxX(self.imageView
.frame
) + 10;CGFloat detailsY
= CGRectGetMaxY(self.nameLabel
.frame
) + 5;CGFloat detailsW
= SCREEN_WIDTH
- detailsX
- 10;self.detailsLabel
.frame
= CGRectMake(detailsX
, detailsY
, detailsW
, 20);
}
@end
效果展示
使用UITableView實現
思路
- 這個可以展開收縮的UITableView,點擊的是TableView的section,每個section下面都對應一個數組,點擊section,就展開sction然后展示數組數據。
- 每次點擊section都要刷新當前點擊的這個section,不用reloadData,提高效率。
- 那么點擊的這個sction怎么知道自己是展開呢還是折疊起來呢?那么關鍵就是對這里的處理,需要加一個條件判斷是展開還是折疊。
實現方法
- 用一個boolArray去記錄每個section的狀態,當然光記錄還是不行的,還是不斷的改變這個boolArray對應section的值,展開了就把值替換為1,閉合了替換了0.那么這個0和1就是我們的依據,依據這個就可以返回這個scetion對應的row了。
- 用一個類去記錄和不斷的替換狀態,該model類增加一個狀態判斷的字段;
流程
- 控制器的代碼:本類主要配置UITableView顯示,以及處理組展開/關閉狀態。
#import "YDWSecondViewController.h"
#import "YDWFriendListShowTableViewCell.h"
#import "YDWFriendHeadView.h"static NSString
* const kYDWFriendListShowTableViewCellIndentifier
= @"YDWFriendListShowTableViewCell";
static NSString
* const kYDWFriendHeadViewIndentifer
= @"YDWFriendHeadView";@interface YDWSecondViewController ()<UITableViewDelegate
,UITableViewDataSource
,FriendHeadViewDelegate
>@property (nonatomic
, strong
) UITableView
*tableView
;@property(nonatomic
,strong
) NSArray
*headerArray
;
@property (nonatomic
, strong
) NSMutableArray
* dataArray
;
@property (nonatomic
, strong
) NSMutableArray
* boolArray
;@end@implementation YDWSecondViewController
- (void)viewDidLoad
{[super viewDidLoad
];[self setupNavigation
];[self setupAddTableView
];[self getListData
];
}#pragma mark - UITableViewDelegate,UITableViewDataSource
- (NSInteger
)numberOfSectionsInTableView
:(UITableView
*)tableView
{return self.dataArray
.count
;
}- (NSInteger
)tableView
:(UITableView
*)tableView numberOfRowsInSection
:(NSInteger
)section
{if ([self.boolArray
[section
] boolValue
] == NO
) {return 0;} else {return [self.dataArray
[section
] count
];}
}- (UITableViewCell
*)tableView
:(UITableView
*)tableView cellForRowAtIndexPath
:(NSIndexPath
*)indexPath
{YDWFriendListShowTableViewCell
*cell
= [tableView dequeueReusableCellWithIdentifier
:kYDWFriendListShowTableViewCellIndentifier
];if (!cell
) {cell
= [[NSBundle mainBundle
] loadNibNamed
:@"YDWFriendListShowTableViewCell" owner
:self options
:nil
].firstObject
;}cell
.selectionStyle
= UITableViewCellSelectionStyleNone
;return cell
;
}- (CGFloat
)tableView
:(UITableView
*)tableView heightForHeaderInSection
:(NSInteger
)section
{return 40;
}- (UIView
*)tableView
:(UITableView
*)tableView viewForHeaderInSection
:(NSInteger
)section
{YDWFriendHeadView
*headeView
= [tableView dequeueReusableHeaderFooterViewWithIdentifier
:kYDWFriendHeadViewIndentifer
];if (headeView
== nil
) {headeView
= [[YDWFriendHeadView alloc
] initWithReuseIdentifier
:kYDWFriendHeadViewIndentifer
];}headeView
.delegte
= self;headeView
.tag
= section
;headeView
.imageView
.image
= [self.boolArray
[section
] boolValue
] ? [UIImage imageNamed
:[NSString stringWithFormat
:@"zhankai"]] : [UIImage imageNamed
:[NSString stringWithFormat
:@"shouqi"]];headeView
.titleLabel
.text
= self.headerArray
[section
];headeView
.numLabel
.text
= [NSString stringWithFormat
:@"%ld/%lu",(long)section
, (unsigned long)[self.dataArray
[section
] count
]];return headeView
;
}#pragma mark - FriendHeadViewDelegate
- (void)friendHeaderReusableView
:(YDWFriendHeadView
*)friendHeaderReusableView didSelectItemAtSection
:(NSInteger
)section
{if ([self.boolArray
[section
] boolValue
] == YES
) {[self.boolArray replaceObjectAtIndex
:section withObject
:@NO
];} else {[self.boolArray replaceObjectAtIndex
:section withObject
:@YES
];}[self.tableView reloadSections
:[NSIndexSet indexSetWithIndex
:section
] withRowAnimation
:UITableViewRowAnimationFade
];
}#pragma mark - Private Methods
- (void)setupNavigation
{self.navigationItem
.title
= @"聯系人";
}- (void)setupAddTableView
{self.tableView
.frame
= self.view
.bounds
;[self.view addSubview
:self.tableView
];
}- (void)getListData
{NSArray
*headerArr
= [NSArray arrayWithObjects
:@"特別關心", @"我的好友", @"朋友", @"家人",nil
];self.headerArray
= headerArr
;NSArray
*itemArr
= [NSArray arrayWithObjects
:@5, @10, @7,@3, nil
];for (int i
= 0; i
< self.headerArray
.count
; i
++) {[self.boolArray addObject
:@NO
];NSMutableArray
* friendArr
= [[NSMutableArray alloc
] init
];for (int j
= 0; j
< [itemArr
[i
] intValue
]; j
++) {[friendArr addObject
:@(j
)];}[self.dataArray addObject
:friendArr
];}[self.tableView reloadData
];
}#pragma mark - Lazying Load
- (NSMutableArray
*)boolArray
{if (!_boolArray
) {_boolArray
= [[NSMutableArray alloc
] init
];}return _boolArray
;
}- (NSMutableArray
*)dataArray
{if (!_dataArray
) {_dataArray
= [[NSMutableArray alloc
] init
];}return _dataArray
;
}- (UITableView
*)tableView
{if (!_tableView
) {_tableView
= [[UITableView alloc
] init
];_tableView
.backgroundColor
= [UIColor whiteColor
];_tableView
.showsHorizontalScrollIndicator
= NO
;_tableView
.delegate
= self;_tableView
.dataSource
= self;_tableView
.separatorStyle
= UITableViewCellSeparatorStyleNone
;_tableView
.tableFooterView
= [UIView new
];[_tableView registerClass
:[YDWFriendHeadView class
] forHeaderFooterViewReuseIdentifier
:kYDWFriendHeadViewIndentifer
];}return _tableView
;
}@end
- YDWFriendHeadView:本類主要布局組標題以及指示(展開/關閉)控件,其次,通過添加點擊手勢結合委托模式,傳遞tag值。
NS_ASSUME_NONNULL_BEGIN
@class YDWFriendHeadView
;
@protocol FriendHeadViewDelegate
<NSObject
>- (void)friendHeaderReusableView
:(YDWFriendHeadView
*)friendHeaderReusableView didSelectItemAtSection
:(NSInteger
)section
;@end@interface YDWFriendHeadView
: UITableViewHeaderFooterView
@property(nonatomic
,weak
) id
<FriendHeadViewDelegate
>delegte
;
@property(nonatomic
,weak
) UIImageView
*imageView
;
@property(nonatomic
,weak
) UILabel
*titleLabel
;
@property(nonatomic
,weak
) UILabel
*numLabel
;
@endNS_ASSUME_NONNULL_END
#import "YDWFriendHeadView.h"@implementation YDWFriendHeadView
#pragma mark - 初始化
- (instancetype
)initWithReuseIdentifier
:(NSString
*)reuseIdentifier
{if (self = [super initWithReuseIdentifier
:reuseIdentifier
]) {self.userInteractionEnabled
= YES
;self.contentView
.backgroundColor
= [UIColor whiteColor
];UITapGestureRecognizer
*tapGes
= [[UITapGestureRecognizer alloc
] initWithTarget
:self action
:@selector(clickView
:)];[self addGestureRecognizer
:tapGes
];[self addSubviews
];}return self;
}- (void)awakeFromNib
{[super awakeFromNib
];[self addSubviews
];
}#pragma mark - 設置UI界面
- (void)addSubviews
{UIImageView
*imageView
= [[UIImageView alloc
] init
];[self addSubview
:imageView
];self.imageView
= imageView
;UILabel
*titleLabel
= [[UILabel alloc
] init
];titleLabel
.font
= [UIFont systemFontOfSize
:18];titleLabel
.textColor
= [UIColor darkGrayColor
];[self addSubview
:titleLabel
];self.titleLabel
= titleLabel
;UILabel
*numLabel
= [[UILabel alloc
] init
];numLabel
.font
= [UIFont systemFontOfSize
:14];numLabel
.textAlignment
= NSTextAlignmentRight
;numLabel
.textColor
= [UIColor lightGrayColor
];[self addSubview
:numLabel
];self.numLabel
= numLabel
;}
- (void)layoutSubviews
{[super layoutSubviews
];self.imageView
.frame
= CGRectMake(10, 10, 20, 20);CGFloat numW
= 60;CGFloat titleX
= CGRectGetMaxX(self.imageView
.frame
) + 10;CGFloat titleW
= SCREEN_WIDTH
- titleX
- numW
-15;self.titleLabel
.frame
= CGRectMake(titleX
, 10, titleW
, 20);CGFloat numX
= SCREEN_WIDTH
- numW
- 10;self.numLabel
.frame
= CGRectMake(numX
, 10, numW
, 20);
}#pragma mark - 監聽事件
- (void)clickView
:(UITapGestureRecognizer
*)tapGes
{if ([self.delegte respondsToSelector
:@selector(friendHeaderReusableView
:didSelectItemAtSection
:)]) {[self.delegte friendHeaderReusableView
:self didSelectItemAtSection
:self.tag
];}
}
@end
- YDWFriendListShowTableViewCell:主要布局好友信息包括頭像、昵稱以及簽名,具體實現如下:
#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN
@interface YDWFriendListShowTableViewCell
: UITableViewCell
@property (weak
, nonatomic
) IBOutlet UIImageView
*headImageView
;
@property (weak
, nonatomic
) IBOutlet UILabel
*nameLabel
;
@property (weak
, nonatomic
) IBOutlet UILabel
*signLabel
;@endNS_ASSUME_NONNULL_END
#import "YDWFriendListShowTableViewCell.h"@implementation YDWFriendListShowTableViewCell
- (void)awakeFromNib
{[super awakeFromNib
];self.headImageView
.backgroundColor
= [UIColor colorWithRed
:arc4random_uniform(256)/255.0 green
:arc4random_uniform(256)/255.0 blue
:arc4random_uniform(256)/255.0 alpha
:1.0];[self.headImageView
.layer setMasksToBounds
:YES
];[self.headImageView
.layer setCornerRadius
:25];}- (void)setSelected
:(BOOL
)selected animated
:(BOOL
)animated
{[super setSelected
:selected animated
:animated
];}
@end
效果展示:與UICollectionView實現得的效果一致。
- 詳細代碼與具體邏輯見demo:iOS之仿QQ好友列表展開收縮效果的實現。
總結
以上是生活随笔為你收集整理的iOS之仿QQ好友列表展开收缩效果的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。