iOS自定義控件:簡易下拉控件

寶兒姐鎮樓

最近自由時間有點多,就開始擼控件。這個是咱們經常使用的一個下拉分類控件,看了不少別人寫的,都是用TableView或者CollectionView整合在一塊兒的感受自定義性沒有那麼強,因此就嘗試用把TableView和CollectionView替換成UIViewController。其餘廢話很少說了。bash

一、 接口文件

#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
複製代碼

二、 實現文件

#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.遵循協議ide

<LZDropViewDataSource, LZDropViewDelegate>
複製代碼

2.初始化post

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];
複製代碼
  1. 實現代理和數據源
#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);
}

複製代碼
  1. 點擊controller中的數據顯示在按鈕的標題中,這由於跨界面顯示,我暫時沒有想到好的辦法,因此使用強大的通知傳值。
  2. 記錄選中狀態,應該是控制器裏面的操做,這裏就沒有實現
[[NSNotificationCenter defaultCenter] postNotificationName:lzDropViewNotification object:self userInfo:@{@"key":[NSString stringWithFormat:@"第%ldcell", indexPath.row]}];
複製代碼

效果圖

若是有什麼很差若是建議的地方,請批評指正!ui

相關文章
相關標籤/搜索