最近自由時間有點多,就開始擼控制元件。這個是我們常用的一個下拉分類控制元件,看了很多別人寫的,都是用TableView或者CollectionView整合在一起的感覺自定義性沒有那麼強,所以就嘗試用把TableView和CollectionView替換成UIViewController。其他廢話不多說了。
1、 介面檔案
#import <UIKit/UIKit.h>
UIKIT_EXTERN NSString *lzDropViewNotification;
NS_ASSUME_NONNULL_BEGIN
@class LZDropView;
@protocol LZDropViewDataSource <NSObject>
@required
/** Height corresponding to controller display */
- (NSArray<NSNumber *> *)setupCategoryControllerHeightInDropView:(LZDropView *)dropView;
/** Title corresponding controller array */
- (NSArray<UIViewController *> *)setupCategoryControllerInDropView:(LZDropView *)dropView;
/** Default display of Title Array */
- (NSArray<NSString *> *)setupCategoryTitleNameInDropView:(LZDropView *)dropView;
@end
@protocol LZDropViewDelegate <NSObject>
/** Click the column and select the information. */
- (void)dropView:(LZDropView *)dropView didSelectAtColumn:(NSInteger)column info:(NSString *)info;
@end
@interface LZDropView : UIView
/** Simple page configuration */
@property (nonatomic, weak) id <LZDropViewDataSource> dataSorce;
/** Click proxy event<##> */
@property (nonatomic, weak) id <LZDropViewDelegate> delegate;
@end
NS_ASSUME_NONNULL_END
複製程式碼
2、 實現檔案
#import "LZDropView.h"
NSString *lzDropViewNotification = @"nitification";
@interface LZDropView ()
@property (nonatomic, strong) NSArray<UIViewController *> *controllerArray;
@property (nonatomic, strong) NSArray<NSString *> *titleArray;
@property (nonatomic, strong) UIButton *containerView;
@property (nonatomic, strong) NSArray<NSNumber *> *controllerHeightArray;
@property (nonatomic, strong) NSMutableArray<UIButton *> *buttonArray;
@end
@implementation LZDropView
#pragma mark - Release memory
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Initialization
- (instancetype)init {
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationAction:) name:lzDropViewNotification object:nil];
}
return self;
}
#pragma mark - Draw the page
- (void)setupTitleButton:(NSArray<NSString *> *)array {
CGFloat width = UIScreen.mainScreen.bounds.size.width / array.count;
self.buttonArray = [NSMutableArray array];
for (NSString *name in array) {
NSInteger index = [array indexOfObject:name];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.titleLabel.font = [UIFont systemFontOfSize:15];
[button setTitle:[NSString stringWithFormat:@"%@ ▼", name] forState:UIControlStateNormal];
[button setTitle:[NSString stringWithFormat:@"%@ ▲", name] forState:UIControlStateSelected];
[button setTitleColor:UIColor.grayColor forState:UIControlStateNormal];
[button setTitleColor:UIColor.orangeColor forState:UIControlStateSelected];
button.frame = CGRectMake(width * index, 0, width, 45);
button.tag = index + 1000;
[button addTarget:self action:@selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
[self.buttonArray addObject:button];
}
}
#pragma mark - Button click event
- (void)buttonTouched:(UIButton *)sender {
if (sender.selected) {
[self closeControllerView];
} else {
[self openControllerViewWithButton:sender];
}
}
- (void)backButtonTouched:(UIButton *)sender {
[self closeControllerView];
}
#pragma mark - Notification event
- (void)notificationAction:(NSNotification *)notification {
if (![self.controllerArray containsObject:notification.object]) {
return;
}
NSInteger index = [self.controllerArray indexOfObject:notification.object];
UIButton *button = self.buttonArray[index];
[button setTitle:[NSString stringWithFormat:@"%@ ▼", notification.userInfo.allValues.firstObject] forState:UIControlStateNormal];
if (self.delegate && [self.delegate respondsToSelector:@selector(dropView:didSelectAtColumn:info:)]) {
[self.delegate dropView:self didSelectAtColumn:index info:notification.userInfo.allValues.firstObject];
}
[self closeControllerView];
}
#pragma mark - Close all controllers.
- (void)closeControllerView {
[UIView animateWithDuration:0.8 animations:^{
self.containerView.alpha = 0;
self.containerView.frame = CGRectMake(0, CGRectGetMaxY(self.frame), UIScreen.mainScreen.bounds.size.width, 0);
} completion:^(BOOL finished) {
[self.containerView removeFromSuperview];
}];
for (UIButton *button in self.buttonArray) {
button.selected = false;
}
}
#pragma mark - Open the corresponding controller.
- (void)openControllerViewWithButton:(UIButton *)sender {
for (UIButton *button in self.buttonArray) {
button.selected = false;
}
self.containerView.alpha = 1;
for (UIView *view in self.containerView.subviews) {
[view removeFromSuperview];
}
UIViewController *vc = self.controllerArray[sender.tag - 1000];
double vcHeight = [self.controllerHeightArray[sender.tag - 1000] doubleValue];
self.containerView.frame = CGRectMake(0, CGRectGetMaxY(self.frame), self.frame.size.width, 0);
vc.view.frame = CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 0);
[self.superview addSubview:self.containerView];
[self.containerView addSubview:vc.view];
[UIView animateWithDuration:0.6 animations:^{
self.containerView.frame = CGRectMake(0, CGRectGetMaxY(self.frame), self.frame.size.width, UIScreen.mainScreen.bounds.size.height);
vc.view.frame = CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, vcHeight);
} completion:^(BOOL finished) {
}];
sender.selected = true;
}
#pragma mark - Getter
- (UIView *)containerView {
if (!_containerView) {
_containerView = [[UIButton alloc] init];
_containerView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1];
[_containerView addTarget:self action:@selector(backButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
}
return _containerView;
}
#pragma mark - Setter
- (void)setDataSorce:(id<LZDropViewDataSource>)dataSorce {
_dataSorce = dataSorce;
if (self.dataSorce && [self.dataSorce respondsToSelector:@selector(setupCategoryControllerInDropView:)]){
self.controllerArray = [self.dataSorce setupCategoryControllerInDropView:self];
}
if (self.dataSorce && [self.dataSorce respondsToSelector:@selector(setupCategoryTitleNameInDropView:)]){
self.titleArray = [self.dataSorce setupCategoryTitleNameInDropView:self];
[self setupTitleButton:self.titleArray];
}
if (self.dataSorce && [self.dataSorce respondsToSelector:@selector(setupCategoryControllerHeightInDropView:)]) {
self.controllerHeightArray = [self.dataSorce setupCategoryControllerHeightInDropView:self];
}
if (self.controllerArray.count != self.titleArray.count ||
self.controllerArray.count != self.controllerHeightArray.count) {
@throw [NSException exceptionWithName:NSStringFromClass([self class]) reason:@"The number of corresponding arrays is inconsistent." userInfo:nil];
}
}
@end
複製程式碼
使用方式
1.遵循協議
<LZDropViewDataSource, LZDropViewDelegate>
複製程式碼
2.初始化
LZDropView *view = [[LZDropView alloc] init];
view.dataSorce = self;
view.delegate = self;
view.backgroundColor = UIColor.whiteColor;
view.frame = CGRectMake(0, 100, UIScreen.mainScreen.bounds.size.width, 45);
[self.view addSubview:view];
複製程式碼
- 實現代理和資料來源
#pragma mark - LZDropViewDataSource
- (NSArray<UIViewController *> *)setupCategoryControllerInDropView:(LZDropView *)dropView {
return @[[[TableViewController alloc] init],
[[TableViewController alloc] init],
[[TableViewController alloc] init],
[[TableViewController alloc] init]];
}
- (NSArray<NSString *> *)setupCategoryTitleNameInDropView:(LZDropView *)dropView {
return @[@"全部",
@"附近",
@"只能排序",
@"篩選"];
}
- (NSArray<NSNumber *> *)setupCategoryControllerHeightInDropView:(LZDropView *)dropView {
return @[[NSNumber numberWithFloat:300],
[NSNumber numberWithFloat:400],
[NSNumber numberWithFloat:410],
[NSNumber numberWithFloat:420]];
}
#pragma mark - LZDropViewDelegate
- (void)dropView:(LZDropView *)dropView didSelectAtColumn:(NSInteger)column info:(NSString *)info {
NSLog(@"%ld---%@", column, info);
}
複製程式碼
- 點選controller中的資料顯示在按鈕的標題中,這因為跨介面顯示,我暫時沒有想到好的辦法,所以使用強大的通知傳值。
- 記錄選中狀態,應該是控制器裡面的操作,這裡就沒有實現
[[NSNotificationCenter defaultCenter] postNotificationName:lzDropViewNotification object:self userInfo:@{@"key":[NSString stringWithFormat:@"第%ldcell", indexPath.row]}];
複製程式碼
如果有什麼不好如果建議的地方,請批評指正!