IOS multi-level drop-down menu

Preface

App common control — multi-level drop-down menu, such as housing, group purchase, screening. On data level, level two, level three, more will not be in this style, presented to the user. The simple chat multi-level drop-down menu

IOS multi-level drop-down menu
two level drop-down Filter menu.Png

One target

The default display of a TableView, click on the data, add second TableView, and realize the size changes, second times to open the drop-down menu. Save last selected data

Two menu control DropMenuView

.h file
#import < UIKit/UIKit.h> @class DropMenuView; @protocol DropMenuViewDelegate < NSObject> - (void) dropMenuView: (DropMenuView * view) didSelectName: (NSString * STR); @end @interface DropMenuView: UIView @property (nonatomic, weak) id< DropMenuViewDelegate> delegate; / * * * @property arrow changes (nonatomic, strong) UIView *arrowView; / * * control settings @param view provides position information of @param tableNum display TableView number @param arr using data - (void) creatDropView: * (UIView *) view withShowTableNum: (NSInteger) tableNum withData: (NSArray * ARR); / * * * / - view disappeared (void) dismiss; @end
.m file
#import "DropMenuView.h" #define kWidth [UIScreen mainScreen].bounds.size.width #define kHeight [UIScreen mainScreen].bounds.size.height @interface DropMenuView (<); UITableViewDelegate, UITableViewDataSource> @private {/ * * save the selected data (number of rows) * / NSInteger selects[3];} @property (nonatomic, assign) BOOL show; / / button click View show / hide @property (nonatomic, assign) CGFloat rowHeightNum; set the ROM / / / * * / @property at the bottom of the Cancel button (nonatomic, strong) UIButton *cancelButton; / * * * @property table view array (nonatomic, strong) NSArray *tableViewArr; @property / * * * / bottom view of the table view (nonatomic, strong) UIView *tableViewUnderView TableView; / * * * / display number (nonatom @ property IC assign, NSInteger tableCount); / * * * / data @property (nonatomic, strong) NSArray *dataArr; @end @implementation DropMenuView (instancetype init) {self = [super init]; if (self) {/ * * * self.dataArr = [NSArray array] initialization data; / * * save initial value for -1 / for (int i = 0; I < 3; i++) {selects[i] = -1;} / * * / self.cancelButton = [UIButton at the bottom of the Cancel button buttonWithType:UIButtonTypeCustom]; self.cancelButton.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.3]; [self.cancelButton addTarget:self action:@selector (clickCancelButton:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:self.cancelButton The bottom of the table view]; / * * * / self.tableViewUnderView = [[UIView alloc] view initialization init]; self.tableViewUnderView.backgroundColor = [UIColor colorWithRed:0.74 green:0.73 blue:0.76 alpha:1.000]; [self.cancelButton addSubview:self.tableViewUnderView]; / * * the default setting is no, the height is 40 row / self.show = NO; self.rowHeightNum = 40.0f;} return self;} - (void) creatDropView: (UIView * view withShowTableNum: (NSInteger) tableNum (NSArray) withData: (arr{*) if! Self.show) {self.show = self.show; / / TableView! Number self.tableCount = tableNum; / / data self.dataArr = arr; for (UITableView *tableView in self.tableView Arr {[tableView reloadData]}); / / set the initial position CGFloat x CGFloat = 0.f; y = view.frame.origin.y + view.frame.size.height = w; CGFloat kWidth; CGFloat H = kHeight - Y; self.frame = CGRectMake (x, y, W, H); self.cancelButton.frame = CGRectMake (0, 0, self.frame.size.width, self.frame.size.height); self.tableViewUnderView.frame = CGRectMake (0, 0, self.frame.size.width, self.rowHeightNum * 7); if (self.superview!) [[[UIApplication sharedApplication] keyWindow] {addSubview:self]; self.alpha = 0.0F; [UIView = animateWithDuration:0.2f animations:^{self.alpha 1.0F}]; [self loadSelects]; [self adjustTableViews]}else{;} / * * what is not selected, click the button again disappear view * / [self dismiss];}} #pragma mark - load the selected TableView - (void) loadSelects{[self.tableViewArr enumerateObjectsUsingBlock:^ (UITableView *tableView, NSUInteger IDX, BOOL * _Nonnull stop) {/ / [tableView / / reloadData] TableView refresh data; select a TableView a line of [tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:selects[idx] inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone]; / / IDX is a plus! For the first time IDX = = 0 circulating method does not perform, so the need for cyclic loading a TableView. If ((selects[idx]! = -1 & & tableView.superview!) ||! IDX) {[self.tableViewUnderView addSubview:tableView]; [UIView animateWithDuration:0.2 animations:^{if (self.arrowView) {self.arrowView.transform = CGAffineTransformMakeRotation (M_PI);}}}}];}]; #pragma mark - TableView reset position - (void) adjustTableViews{TableView int addTableCount / / display number = 0; for (UITableView *tableView in self.tableViewArr if (tableView.superview) {{addTableCount++}}); for (int i = 0; I < addTableCount; i++) {UITableView *tableView = self.tableViewArr[i]; CGR Ect adjustFrame = tableView.frame; adjustFrame.size.width = kWidth / addTableCount; adjustFrame.origin.x = adjustFrame.size.width * I + 0.5 * I; adjustFrame.size.height = self.tableViewUnderView.frame.size.height; tableView.frame = adjustFrame;}} #pragma mark - TableView protocol number - * / / * * (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section{NSInteger __block count enumerateObjectsUsingBlock:^ (ID _Nonnull; [self.tableViewArr obj, NSUInteger, IDX, BOOL * _Nonnull stop) {if (obj = = tableView) {NSInteger (firstSelectRow = (UITableView *) self.tableViewArr[0].IndexPathForSelectedRow.row; secondSelectRow = NSInteger) ((UITableView) self.tableViewArr[1]).IndexPathForSelectedRow.row; count = [self countForChooseTable:idx firstTableSelectRow:firstSelectRow withSecondTableSelectRow:secondSelectRow];}}]; return count;} / / can be raised, if there is a need to set the protocol implementation package, the author extracts only one, the others are in the TableView protocol itself in writing - (NSInteger) countForChooseTable: (NSInteger) idx firstTableSelectRow: (NSInteger) firstSelectRow withSecondTableSelectRow: (NSInteger) secondSelectRow{if (IDX = = 0) {return self.dataArr.count;}else if (IDX = = 1) {if (firstSelectRow = = -1) {return 0;}else{if (self.tableCount = = 2) {re Turn [self.dataArr[firstSelectRow][@ "subcategories"}else{return [self.dataArr[firstSelectRow][@ "count]; sub" count]}else{if ";}} (secondSelectRow = = -1) {return 0;}else{return [self.dataArr[firstSelectRow][@" sub "secondSelectRow][@, count]" sub "];}}} / * * * / - Custom cell (UITableViewCell *) tableView: (UITableView * cellForRowAtIndexPath: (tableView) NSIndexPath * indexPath{UITableViewCell *cell) = [tableView dequeueReusableCellWithIdentifier:@ =" DropCell "]; cell.textLabel.font [UIFont systemFontOfSize:14]; if (self.tableCount = = 1) {cell.textLabel.text =" label self.dataArr[indexPath.row][@ "];}else if (self.tableCount = = 2) {NSInteger (firstSelectRow = (UITableView *) self.tableViewArr[0]).IndexPathForSelectedRow.row; if (tableView = = self.tableViewArr[0]) {cell.textLabel.text self.dataArr[indexPath.row][@ =" name "];}else if (tableView = = self.tableViewArr[1]) {cell.textLabel.text = self.dataArr[firstSelectRow][@" subcategories "][indexPath.row];}else} if {NSInteger (self.tableCount = 3) (firstSelectRow = (UITableView *) self.tableViewArr[0] NSInteger (.IndexPathForSelectedRow.row); secondSelectRow = (UITableView *) self.tableViewArr[1]).IndexPathForSelectedRow.row; if (tableView = = self.tableViewArr[0]) {cell.text Label.text self.dataArr[indexPath.row][@ = "name"];}else if (tableView = = self.tableViewArr[1]) {cell.textLabel.text self.dataArr[firstSelectRow][@ = "sub"][indexPath.row][@ "name"];}else if (tableView = = self.tableViewArr[2]) {cell.textLabel.text self.dataArr[firstSelectRow][@ = "sub"][secondSelectRow][@ "sub"][indexPath.row] return cell;}};} / * * * click - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath{UITableView *secondTableView UITableView = self.tableViewArr[1]; *thirdTableView = self.tableViewArr[2]; if (self.tableCount = = 1) {[self saveSelects]; [self dismiss]; [_delegate dropMenuView: Self didSelectName:self.dataArr[indexPath.row][@ "label"}else "; if (self.tableCount = = 2) {if (tableView = = self.tableViewArr[0]) {if (! SecondTableView.superview) {[self.tableViewUnderView addSubview:secondTableView];} [secondTableView reloadData]; [self adjustTableViews];}else if (tableView = = self.tableViewArr[1]) {[self saveSelects]; [self dismiss]; NSInteger (firstSelectRow = (UITableView * self.tableViewArr[0]).IndexPathForSelectedRow.row) [_delegate dropMenuView:self didSelectName:self.dataArr[firstSelectRow][@;][indexPath.row]];}else" subcategories "} {if (self.tableCount = 3) NSInteger (firstSelectRow = (UITableView *) self.tableViewArr[0] NSInteger (.IndexPathForSelectedRow.row); secondSelectRow = (UITableView *) self.tableViewArr[1]).IndexPathForSelectedRow.row; if (tableView = = self.tableViewArr[0]) {if (! SecondTableView.superview) {[self.tableViewUnderView addSubview:secondTableView]}; [self adjustTableViews]; [secondTableView reloadData]; [thirdTableView reloadData];}else if (tableView = = self.tableViewArr[1]) {{if (thirdTableView.superview!) [self.tableViewUnderView addSubview:thirdTableView] [self adjustTableViews] [third;}; TableView reloadData];}else if (tableView = = self.tableViewArr[2]) {[self saveSelects]; [self dismiss]; [_delegate dropMenuView:self didSelectName:self.dataArr[firstSelectRow][@ "sub"][secondSelectRow][@ "sub][indexPath.row]]";}}} # pragma mark - record selection state (void) saveSelects{[self.tableViewArr enumerateObjectsUsingBlock:^ (UITableView *tableView, NSUInteger IDX, BOOL * _Nonnull stop) {selects[idx] tableVi = tableView.superview?

Three call control MenuScreeningView

.h file
#import < UIKit/UIKit.h> @interface MenuScreeningView: UIView #pragma mark - Filter menu disappears - (void) menuScreeningViewDismiss; @end
.m file
#import "MenuScreeningView.h" #import "DropMenuView.h" #define kWidth [UIScreen mainScreen].bounds.size.width #define kHeight [UIScreen mainScreen].bounds.size.height @interface MenuScreeningView (<); DropMenuViewDelegate> @property (nonatomic, strong) UIButton *oneLinkageButton; @property (nonatomic, strong) UIButton *twoLinkageButton @property (nonatomic, strong); UIButton *threeLinkageButton; @property (nonatomic, strong) DropMenuView (nonatomic * oneLinkageDropMenu; @property DropMenuView *twoLinkageDropMenu, strong); @property (nonatomic, strong) DropMenuView *threeLinkageDropMenu; @property (nonatomic, strong) NSArray *addressArr @property (nonatomic, strong); NSArray *categoriesArr; @property (nonatomic, strong) NSArray *sor TsArr; @end @implementation MenuScreeningView (instancetype) - initWithFrame: (CGRect frame) {self = [super initWithFrame:frame]; if (self) {self.oneLinkageButton buttonWithType:UIButtonTypeCustom] = [UIButton; self.oneLinkageButton.frame = CGRectMake (0, 0, kWidth/3, 36); [self setUpButton:self.oneLinkageButton withText:@ "a" self.oneLinkageDropMenu = [[DropMenuView]; alloc] init]; self.oneLinkageDropMenu.arrowView = self.oneLinkageButton.imageView; self.oneLinkageDropMenu.delegate = self self.twoLinkageButton; buttonWithType:UIButtonTypeCustom] = [UIButton; self.twoLinkageButton.frame = CGRectMake (kWidth/3, 0, kWidth/3, 36); [self setUpButton:sel F.twoLinkageButton withText:@ "two"]; self.twoLinkageDropMenu = [[DropMenuView alloc] init]; self.twoLinkageDropMenu.arrowView = self.twoLinkageButton.imageView; self.twoLinkageDropMenu.delegate = self; self.threeLinkageButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.threeLinkageButton.frame = CGRectMake (2 * kWidth/3, 0, kWidth/3, 36); [self setUpButton:self.threeLinkageButton withText:@ "three"]; self.threeLinkageDropMenu = [[DropMenuView alloc] init]; self.threeLinkageDropMenu.arrowView = self.threeLinkageButton.imageView; self.threeLinkageDropMenu.delegate = self the following lines; / * * * UIView *horizontalLine = [[UIView alloc] I NitWithFrame:CGRectMake (0, self.frame.size.height - 0.6, kWidth, 0.6); horizontalLine.backgroundColor = [UIColor colorWithWhite:0.8 alpha:1.000]; [self addSubview:horizontalLine];} return self;} #pragma mark - click on the button menu (and other menu away) - (void) clickButton: (UIButton * button{) if (button = = self.oneLinkageButton) {[self.twoLinkageDropMenu dismiss]; [self.threeLinkageDropMenu dismiss] [self.oneLinkageDropMenu; creatDropView:self withShowTableNum:1 withData:self.sortsArr];}else if (button = = self.twoLinkageButton) {[self.oneLinkageDropMenu dismiss]; [self.threeLinkageDropMenu dismiss]; [self.twoLinkageDropMenu creatDropV Iew:self withShowTableNum:2 withData:self.categoriesArr];}else if (button = = self.threeLinkageButton) {[self.oneLinkageDropMenu dismiss]; [self.twoLinkageDropMenu dismiss]; [self.threeLinkageDropMenu creatDropView:self withShowTableNum:3 withData:self.addressArr] #pragma mark;}} - selection menu - (void) menuScreeningViewDismiss{[self.oneLinkageDropMenu disappeared dismiss]; [self.twoLinkageDropMenu dismiss]; [self.threeLinkageDropMenu dismiss];} #pragma mark - Protocol - (void) dropMenuView: (DropMenuView * view didSelectName: (NSString) *) str{if (view = = self.oneLinkageDropMenu) {[self.oneLinkageButton setTitle:str forState:UIControlStateNormal]; [self buttonEdgeInset S:self.oneLinkageButton];}else if (view = = self.twoLinkageDropMenu) {[self.twoLinkageButton setTitle:str forState:UIControlStateNormal]; [self buttonEdgeInsets:self.twoLinkageButton];}else if (view = = self.threeLinkageDropMenu) {[self.threeLinkageButton setTitle:str forState:UIControlStateNormal]; [self buttonEdgeInsets:self.threeLinkageButton];}} - #pragma mark Button - (void) setUpButton: (UIButton * button) withText: (NSString *) str{[button addTarget:self action:@selector (clickButton:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:button]; [button setTitle:str forState:UIControlStateNormal]; button.titleLabel.font [UIFont = systemFontOfSize:1 1]; button.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; [button setTitleColor:[UIColor colorWithWhite:0.3 alpha:1.000] forState:UIControlStateNormal]; [button setImage:[UIImage imageNamed:@ forState:UIControlStateNormal] [self "downarr"]; buttonEdgeInsets:button] UIView *verticalLine; [[UIView = alloc]init]; verticalLine.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0]; [button addSubview:verticalLine]; verticalLine.frame = CGRectMake (button.frame.size.width - 0.5, 3, 0.5, 30);} - (void) buttonEdgeInsets: (UIButton *) button{[button setTitleEdgeInsets:UIEdgeInsetsMake (0, 0, -button.imageView.bounds.size.width + 2, button.imageView.bounds.size.width + 10)]; [button setImageEdgeInse Ts:UIEdgeInsetsMake (0, button.titleLabel.bounds.size.width + 10, -button.titleLabel.bounds.size.width + 0, 2]);} #pragma mark - lazy loading (NSArray *) addressArr{if (_addressArr = = Nil) {NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@ "address.plist" ofType:nil]]; _addressArr dic[@ = "address"];}} - return (NSArray * _addressArr; categoriesArr{(_categoriesArr) if = = Nil) {_categoriesArr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@ categories.plist ofType:nil]] return _categoriesArr;};} - (NSArray * sortsArr{) if (_sortsArr = = Nil) {_sortsArr = [NSArray arrayWithContentsOfFil E:[[NSBundle, mainBundle], pathForResource:@, sorts.plist, ofType:nil]],}, return, _sortsArr,}, @end

Four call

MenuScreeningView *menuScreening = [[MenuScreeningView alloc] initWithFrame:CGRectMake (0, 64, kWidth, 36)]; [self.view addSubview:menuScreening]; menuScreening.backgroundColor [UIColor = whiteColor];
Five effect diagram
IOS multi-level drop-down menu
multilevel drop-down menu.Gif
Six demo download

Because the data source can not upload the book last time, so upload a demo, details, there may be no attention, for reference only.
portal: https://github.com/Lucifer0103/LinkageMenu

Reference link: https://github.com/skytoup/SkyAssociationMenuView

Above!

App common control — multi-level drop-down menu, such as housing, group purchase, screening. On data level, level two, level three, more will not be in this style, presented to the user. The simple chat multi-level drop-down menu

因为数据源 无法上次上传[简书], 所以上传个demo, 细节方面, 可能有未注意地方,仅供参考.
传送门 : https://github.com/Lucifer0103/LinkageMenu

参考链接 : https://github.com/skytoup/SkyAssociationMenuView

以 上 !