美文网首页
重构:UIButton下拉列表极简封装

重构:UIButton下拉列表极简封装

作者: SoaringHeart | 来源:发表于2021-01-18 18:15 被阅读0次

实现下拉菜单,无侵入不继承;

ezgif.com-gif-maker.gif
 @property (nonatomic, strong) UIButton *button;

 #pragma mark -lazy
 - (UIButton *)button{
     if (!_button) {
         _button = ({
             UIButton *sender = [UIButton buttonWithType:UIButtonTypeCustom];
             [sender setTitle:@"下拉列表" forState:UIControlStateNormal];
             [sender setTitleColor:UIColor.systemBlueColor forState:UIControlStateNormal];
             sender.titleLabel.font = [UIFont systemFontOfSize:15];
             
             sender.titleLabel.adjustsFontSizeToFitWidth = YES;
             sender.imageView.contentMode = UIViewContentModeScaleAspectFit;
             sender;
         });
                 
         _button.menuTarget.hiddenClearButton = true;
         _button.menuTarget.list = @[@"北京", @"上海", @"广州", @"深圳", @"西安"].mutableCopy;
         _button.menuTarget.block = ^(NNMenuTarget *tagget) {
             DDLog(@"%@", tagget.selectedText);
         };
     }
     return _button;
 }

UIButton+Menu.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface NNButtonMenuTarget : NSObject

@property (nonatomic, strong) NSMutableArray<NSString *> *list;
@property (nonatomic, strong, readonly, nullable) NSString *selectedText;
@property (nonatomic, assign) bool hiddenClearButton;

@property (nonatomic, copy) UITableViewCell *(^blockCellForRow)(UITableView *tableView, NSIndexPath *indexPath, NSString *selectedText);
@property (nonatomic, copy) void(^block)(NNButtonMenuTarget *);

@end


@interface UIButton (Menu)

@property (nonatomic, strong, readonly) NNButtonMenuTarget *menuTarget;

@end

NS_ASSUME_NONNULL_END

UIButton+Menu.m

//
//  UIButton+Menu.m
//  SwiftTemplet
//
//  Created by Bin Shang on 2021/1/14.
//  Copyright © 2021 BN. All rights reserved.
//

#import "UIButton+Menu.h"
#import <objc/runtime.h>

@interface NNButtonMenuTarget()<UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong, readwrite) NSString *selectedText;

@property (nonatomic, weak) UIButton *button;

@end


@implementation NNButtonMenuTarget

- (void)dealloc{
    [self.button removeObserver:self forKeyPath:@"selected"];
}

#pragma mark -observe
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([object isKindOfClass:[UIButton class]]) {
//        UIButton *sender = (UIButton *)object;
        if ([keyPath isEqualToString:@"selected"]) {
            NSNumber *newValue = change[NSKeyValueChangeNewKey];
//            DDLog(@"newValue: %@", newValue);
            if (newValue.boolValue) {
                [self showHistory];
            } else {
                [self hideHistroy];
            }
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark -set,get
- (NSMutableArray<NSString *> *)list{
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setList:(NSMutableArray<NSString *> *)list{
    objc_setAssociatedObject(self, @selector(list), list, OBJC_ASSOCIATION_RETAIN);
    self.selectedText = list.firstObject;
    [self.tableView reloadData];
    if (self.block) {
        self.block(self);
    }
}

#pragma mark -tableview
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.list.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    if (self.blockCellForRow && self.blockCellForRow(tableView, indexPath, self.list[indexPath.row])) {
        return self.blockCellForRow(tableView, indexPath, self.list[indexPath.row]);
    }
    
    static NSString *identifier = @"UITextFieldHistoryCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }
    cell.separatorInset = UIEdgeInsetsZero;
    cell.textLabel.textColor = UIColor.grayColor;
    cell.textLabel.font = self.button.titleLabel.font ? : [UIFont systemFontOfSize:15];
    cell.textLabel.textAlignment = NSTextAlignmentCenter;
    cell.textLabel.adjustsFontSizeToFitWidth = YES;

    cell.textLabel.text = self.list[indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    self.selectedText = self.list[indexPath.row];
    [self hideHistroy];
    
    [self.button setTitle:self.selectedText forState:UIControlStateNormal];
    if (self.block) {
        self.block(self);
    }
    
    self.button.selected = !self.button.selected;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return tableView.rowHeight;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    CGFloat height = self.hiddenClearButton ? 0.01 : tableView.rowHeight;
    return height;
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
    if (self.hiddenClearButton) {
        return [[UIView alloc]init];
    }
    UIButton *sender = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [sender setTitle:@"全部清除" forState:UIControlStateNormal];
    [sender addTarget:self action:@selector(clearHistory) forControlEvents:UIControlEventTouchUpInside];
    return sender;
}


#pragma mark -functions

- (void)showHistory{
    if (self.tableView.superview || !self.list) {
        return;
    }
    if (self.list.count == 0) {
        NSLog(@"%s%@", __func__, @"列表为空!!!");
        return;
    }
    self.tableView.frame = CGRectMake(CGRectGetMinX(self.button.frame),
                                      CGRectGetMaxY(self.button.frame),
                                      CGRectGetWidth(self.button.frame),
                                      1);
    [self.button.superview addSubview:self.tableView];
    NSInteger count = self.hiddenClearButton ? self.list.count : self.list.count + 1;
    
    CGRect rect = self.tableView.frame;
    rect.size.height = self.tableView.rowHeight*count;

    [UIView animateWithDuration:0.35 animations:^{
        self.tableView.frame = rect;
    }];
}

- (void)hideHistroy{
    if (!self.tableView.superview) {
        return;
    }
    
    CGRect rect = self.tableView.frame;
    rect.size.height = 1;
    
    [UIView animateWithDuration:0.35 animations:^{
        self.tableView.frame = rect;
    } completion:^(BOOL finished) {
        [self.tableView removeFromSuperview];
    }];
}

- (void)clearHistory{
    [self.list removeAllObjects];
    self.selectedText = nil;
    [self hideHistroy];
    if (self.block) {
        self.block(self);
    }
}

#pragma mark -lazy
- (UITableView *)tableView{
    UITableView *view = objc_getAssociatedObject(self, _cmd);
    if (view) {
        return view;
    }
    
    UITableView *table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    [table registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITextFieldHistoryCell"];
    table.rowHeight = 45;
    table.layer.borderColor = UIColor.lightGrayColor.CGColor;
    table.layer.borderWidth = 0.5;
    table.delegate = self;
    table.dataSource = self;
    objc_setAssociatedObject(self, @selector(tableView), table, OBJC_ASSOCIATION_RETAIN);
    return table;
}

@end



@implementation UIButton (Menu)

- (NNButtonMenuTarget *)menuTarget{
    NNButtonMenuTarget *obj = objc_getAssociatedObject(self, _cmd);
    if (obj) {
        return obj;
    }
    NNButtonMenuTarget *tmp = [[NNButtonMenuTarget alloc]init];
    tmp.button = self;
    
    [tmp.button addObserver:tmp forKeyPath:@"selected" options:NSKeyValueObservingOptionNew context:nil];
    objc_setAssociatedObject(self, @selector(menuTarget), tmp, OBJC_ASSOCIATION_RETAIN);
    return tmp;
}

@end

相关文章

网友评论

      本文标题:重构:UIButton下拉列表极简封装

      本文链接:https://www.haomeiwen.com/subject/mcixzktx.html