1. 程式人生 > >iOS 多級下拉選單

iOS 多級下拉選單

前言

App 常用控制元件 -- 多級下拉選單, 如團購類, 房屋類, 對資料進行篩選. 有一級, 二級, 三級, 再多就不會以這種樣式,呈現給使用者了. 作者就簡單聊一下 多級下拉選單


二級下拉篩選選單.png

一 目標

  1. 預設顯示一個 TableView, 點選資料後, 新增第二個TableView, 並實現大小變化
  2. 第二次開啟下拉選單. 儲存上次選中資料

二 選單控制元件DropMenuView

.h檔案
#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 (nonatomic, strong) UIView *arrowView; /** 控制元件設定 @param view 提供控制元件 位置資訊 @param tableNum 顯示TableView數量 @param arr 使用資料 */
-(void)creatDropView:(UIView *)view withShowTableNum:(NSInteger)tableNum withData:(NSArray *)arr; /** 檢視消失 */ - (void)dismiss; @end
.m檔案
#import "DropMenuView.h"

#define kWidth [UIScreen mainScreen].bounds.size.width
#define kHeight [UIScreen mainScreen].bounds.size.height

@interface DropMenuView
()<UITableViewDelegate, UITableViewDataSource>
{ @private /** 儲存 選擇的資料(行數) */ NSInteger selects[3]; } @property (nonatomic, assign) BOOL show; // 按鈕點選後 檢視顯示/隱藏 @property (nonatomic, assign) CGFloat rowHeightNum; // 設定 rom 高度 /* 底層取消按鈕 */ @property (nonatomic, strong) UIButton *cancelButton; /** 表檢視陣列 */ @property (nonatomic, strong) NSArray *tableViewArr; /** 表檢視的 底部檢視 */ @property (nonatomic, strong) UIView *tableViewUnderView; /** 顯示 TableView 數量 */ @property (nonatomic, assign) NSInteger tableCount; /** 資料 */ @property (nonatomic, strong) NSArray *dataArr; @end @implementation DropMenuView - (instancetype)init { self = [super init]; if (self) { /** 資料初始化 */ self.dataArr = [NSArray array]; /** 儲存 初始值為-1 */ for (int i = 0; i < 3; i++) { selects[i] = -1; } /* 底層取消按鈕 */ self.cancelButton = [UIButton 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]; /** 表檢視的 底部檢視初始化 */ self.tableViewUnderView = [[UIView alloc] init]; self.tableViewUnderView.backgroundColor = [UIColor colorWithRed:0.74 green:0.73 blue:0.76 alpha:1.000]; [self.cancelButton addSubview:self.tableViewUnderView]; /** 預設設定為no, row高度為40 */ self.show = NO; self.rowHeightNum = 40.0f; } return self; } -(void)creatDropView:(UIView *)view withShowTableNum:(NSInteger)tableNum withData:(NSArray *)arr{ if (!self.show) { self.show = !self.show; // 顯示 TableView數量 self.tableCount = tableNum; // 資料 self.dataArr = arr; for (UITableView *tableView in self.tableViewArr) { [tableView reloadData]; } // 初始位置 設定 CGFloat x = 0.f; CGFloat y = view.frame.origin.y + view.frame.size.height; CGFloat w = 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{ /** 什麼也不選擇時候, 再次點選按鈕 消失檢視 */ [self dismiss]; } } #pragma mark - 載入選中的TableView -(void)loadSelects{ [self.tableViewArr enumerateObjectsUsingBlock:^(UITableView *tableView, NSUInteger idx, BOOL * _Nonnull stop) { // 重新整理TableView資料 [tableView reloadData]; // 選中TableView某一行 [tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:selects[idx] inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone]; // 加 !idx 是因為 迴圈第一次 idx == 0 方法不執行, 所以需要迴圈一次 載入一個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的 位置 -(void)adjustTableViews{ // 顯示的 TableView 數量 int addTableCount = 0; for (UITableView *tableView in self.tableViewArr) { if (tableView.superview) { addTableCount++; } } for (int i = 0; i < addTableCount; i++) { UITableView *tableView = self.tableViewArr[i]; CGRect 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協議 /** 行數 */ -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ NSInteger __block count; [self.tableViewArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (obj == tableView) { NSInteger firstSelectRow = ((UITableView *)self.tableViewArr[0]).indexPathForSelectedRow.row ; NSInteger secondSelectRow = ((UITableView *)self.tableViewArr[1]).indexPathForSelectedRow.row ; count = [self countForChooseTable:idx firstTableSelectRow:firstSelectRow withSecondTableSelectRow:secondSelectRow]; } }]; return count; } // 可以將 方法提出來, 如果有需要 可以設定為協議實現封裝, 作者僅提取一個, 其他均在 TableView自身協議中寫 -(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) { return [self.dataArr[firstSelectRow][@"subcategories"] count]; }else{ return [self.dataArr[firstSelectRow][@"sub"] count]; } } }else{ if (secondSelectRow == -1) { return 0; }else{ return [self.dataArr[firstSelectRow][@"sub"][secondSelectRow][@"sub"] count]; } } } /** 自定義cell */ -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"DropCell"]; cell.textLabel.font = [UIFont systemFontOfSize:14]; if (self.tableCount == 1) { cell.textLabel.text = self.dataArr[indexPath.row][@"label"]; }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 (self.tableCount == 3){ NSInteger firstSelectRow = ((UITableView *)self.tableViewArr[0]).indexPathForSelectedRow.row; NSInteger secondSelectRow = ((UITableView *)self.tableViewArr[1]).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][@"sub"][indexPath.row][@"name"]; }else if (tableView == self.tableViewArr[2]){ cell.textLabel.text = self.dataArr[firstSelectRow][@"sub"][secondSelectRow][@"sub"][indexPath.row]; } } return cell; } /** 點選 */ -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ UITableView *secondTableView = self.tableViewArr[1]; UITableView *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][@"subcategories"][indexPath.row]]; } }else if (self.tableCount == 3){ NSInteger firstSelectRow = ((UITableView *)self.tableViewArr[0]).indexPathForSelectedRow.row; NSInteger secondSelectRow = ((UITableView *)self.tableViewArr[1]).indexPathForSelectedRow.row; if (tableView == self.tableViewArr[0]) { if (!secondTableView.superview) { [self.tableViewUnderView addSubview:secondTableView]; } [self adjustTableViews]; [secondTableView reloadData]; }else if (tableView == self.tableViewArr[1]){ if (!thirdTableView.superview) { [self.tableViewUnderView addSubview:thirdTableView]; } [self adjustTableViews]; [thirdTableView 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 - 記錄 選擇狀態 -(void)saveSelects{ [self.tableViewArr enumerateObjectsUsingBlock:^(UITableView *tableView, NSUInteger idx, BOOL * _Nonnull stop) { selects[idx] = tableView.superview ? tableView.indexPathForSelectedRow.row : -1; }]; } #pragma mark - 檢視消失 - (void)dismiss{ if(self.superview) { self.show = !self.show; [self endEditing:YES]; [UIView animateWithDuration:.25f animations:^{ self.alpha = .0f; } completion:^(BOOL finished) { [self.tableViewUnderView.subviews enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) { [obj removeFromSuperview]; }]; [self removeFromSuperview]; [UIView animateWithDuration:0.2 animations:^{ if (self.arrowView) { self.arrowView.transform = CGAffineTransformMakeRotation(0); } }]; }]; } } /** 底部按鈕, 檢視消失 */ -(void)clickCancelButton:(UIButton *)button{ [self dismiss]; } /** 懶載入 */ -(NSArray *)tableViewArr{ if (_tableViewArr == nil) { _tableViewArr = @[[[UITableView alloc] init], [[UITableView alloc] init], [[UITableView alloc] init]]; for (UITableView *tableView in _tableViewArr) { [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"DropCell"]; tableView.delegate = self; tableView.dataSource = self; tableView.frame = CGRectMake(0, 0, 0, 0); tableView.backgroundColor = [UIColor whiteColor]; tableView.tableFooterView = [[UIView alloc] init]; tableView.showsVerticalScrollIndicator = NO; tableView.rowHeight = self.rowHeightNum; } } return _tableViewArr; } @end

三 呼叫控制元件MenuScreeningView

.h檔案
#import <UIKit/UIKit.h>

@interface MenuScreeningView : UIView

#pragma mark - 篩選選單消失
-(void)menuScreeningViewDismiss;

@end
.m檔案
#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 *oneLinkageDropMenu;
@property (nonatomic, strong) DropMenuView *twoLinkageDropMenu;
@property (nonatomic, strong) DropMenuView *threeLinkageDropMenu;

@property (nonatomic, strong) NSArray *addressArr;
@property (nonatomic, strong) NSArray *categoriesArr;
@property (nonatomic, strong) NSArray *sortsArr;


@end


@implementation MenuScreeningView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {


        self.oneLinkageButton = [UIButton buttonWithType:UIButtonTypeCustom];
        self.oneLinkageButton.frame = CGRectMake(0, 0, kWidth/3, 36);
        [self setUpButton:self.oneLinkageButton withText:@"一級"];

        self.oneLinkageDropMenu = [[DropMenuView alloc] init];
        self.oneLinkageDropMenu.arrowView = self.oneLinkageButton.imageView;
        self.oneLinkageDropMenu.delegate = self;



        self.twoLinkageButton = [UIButton buttonWithType:UIButtonTypeCustom];
        self.twoLinkageButton.frame = CGRectMake(kWidth/3, 0, kWidth/3, 36);
        [self setUpButton:self.twoLinkageButton withText:@"二級"];

        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:@"三級"];

        self.threeLinkageDropMenu = [[DropMenuView alloc] init];
        self.threeLinkageDropMenu.arrowView = self.threeLinkageButton.imageView;
        self.threeLinkageDropMenu.delegate = self;


        /** 最下面橫線 */
        UIView *horizontalLine = [[UIView alloc] initWithFrame: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 - 按鈕點選推出選單 (並且其他的選單收起)
-(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 creatDropView: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 - 篩選選單消失
-(void)menuScreeningViewDismiss{

    [self.oneLinkageDropMenu dismiss];
    [self.twoLinkageDropMenu dismiss];
    [self.threeLinkageDropMenu dismiss];
}


#pragma mark - 協議實現
-(void)dropMenuView:(DropMenuView *)view didSelectName:(NSString *)str{

    if (view == self.oneLinkageDropMenu) {

        [self.oneLinkageButton setTitle:str forState:UIControlStateNormal];
        [self buttonEdgeInsets: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:11];
    button.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
    [button setTitleColor:[UIColor colorWithWhite:0.3 alpha:1.000] forState:UIControlStateNormal];
    [button setImage:[UIImage imageNamed:@"downarr"] forState:UIControlStateNormal];

    [self 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, -button.imageView.bounds.size.width + 
            
           

相關推薦

iOS 多級選單

前言 App 常用控制元件 -- 多級下拉選單, 如團購類, 房屋類, 對資料進行篩選. 有一級, 二級, 三級, 再多就不會以這種樣式,呈現給使用者了. 作者就簡單聊一下 多級下拉選單 二級下拉篩選選單.png 一 目標 預設顯示一個 TableView,

JS--jQuery實現的多級選單效果程式碼

這篇文章主要介紹了jQuery實現的多級下拉選單效果程式碼,涉及jquery滑鼠事件及頁面元素的顯示與隱藏效果實現技巧,非常具有實用價值,需要的朋友可以參考下: 本文例項講述了jQuery實現的多級下拉選單效果程式碼。供大家參考。具體如下: 這是一款jQuery多級下拉選單,在支援html5

Bootstrop多級選單

原地址找不到了,只為學習,如有侵權,盡情諒解 - 需要引用bootstrap.min.css和bootstrap.min.css.js - 程式碼如下 <head> <meta charset="UTF-8">

Excel多級選單聯動自動匹配內容

4.一級下選單引用的是第一行的資料,我們對一級下拉選單進行定義。選中第一行的資料,點選選單欄中的【定義名稱】,在輸入區域名稱這裡輸入名稱,例如“首行”,然後點選確定。可以看到在名稱管理器裡多了一個名稱“首行”。

bootstrap多級選單

<!DOCTYPE HTML> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Bootstrap 3 的多級下拉選單示例</

Bootstrap 3的多級選單示例

Bootstrap 雖好,但對於複雜的介面,還是有N多元件需要自己擴充套件,並且要往簡潔、大氣的Bootstrap介面上靠,著實要費一些功夫。下面分享一個Bootstrap 3的多級下拉選單,無需第三方Js指令碼,複製後直接可用。 <!DOCTYPE HTML>

iOS選單效果實現

原文地址:https://www.jianshu.com/p/d1b7ebba9ac7控制元件的屬性以及介面:/* 主按鈕 可以自定義樣式 可在.m檔案中修改預設的一些屬性 */ @property (nonatomic,strong) UIButton * mainBtn

iOS點選選單的實現(利用UITableView + UIButton + UILabel)

我們在學習的過程中,可能會遇到需要新增下拉選單功能的時候,有的小夥伴可能一時半會想不出來怎樣實現,那麼我今天就來給大家分享一下我的方法 先看一下效果圖 左邊是一個UIButton,點選前是如下效果 這是點選星期三後的效果 這樣,就實現

Ajax動態訪問資料庫設計html多級select選單的方法

getArea(0,$('<select>'));//呼叫方法,第一個引數是要查詢專案的id,根據資料庫來就好,第二個引數是一個select物件,可以是現有的,也可以生成一個新的在頁面重新

iOS 微信右上角選單效果之CMPopTipView,各種角度各種位置

早之前在專案中寫了一個類似微信右上角下拉的選單封裝,但是是寫死的,當時根本沒有考慮到去其他地方彈出這個東西,雖然看起來彈個窗出來很簡單,但是你位子不確定之後彈出來是有點麻煩的,反正我總是覺得,我們能想到的,老外早就想到了,多給自己弄點工具庫,多看看原始碼,指不定哪天我也搞出一

Bootstrap 選單多級聯動

直接上乾貨 <!DOCTYPE HTML> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Bootstrap 3 的多級下拉選單示

EXCEL如何實現多級聯動選單

首先來說一下我們要實現的效果,就是我們選擇1級選單後,2級選單裡就有對應1級選單的內容,我們選擇2級選單的項的時候,3級選單會產生對應2級選單項的內容,以此類推,來說一下我實現這種功能的原理,就是為不同的列的內容設定了名稱,而這個名稱恰好就是上一級選單裡的選擇項。這樣的情況下,在資料有效性中的函式讀取的其實

IOS使用UItableView實現選單元件(UITableView的使用方法)

一. 基礎版本 在登陸介面有時需要儲存已經登陸的賬號資訊,可以點開一個下拉選單選擇儲存的賬號,這裡是用UIKit的表格元件編寫一個下拉選單元件demo,實現思路如下: 1.首先在一個UIViewController裡放一個按鈕或者標籤框,用來顯示當

Bootstrap元件---選單多級選單 ,按鈕

下拉選單       選單: ,dropdown(.dropup改變這個是上顯示)   data-toggle="dropdown" (啟用文字處)      .dropdown-menu   .pull-left   .pull-right        按鈕組:.btn

ios實現刷新,上加載

nor llb __weak count stat 實現 sele share mode 1、自定義cell //#import "EnjoyListModel.h" @protocol EnjoyCollectionCellOfViewDelegate <NSO

微信小程序-ios系統-出現白色,如何處理呢?

esc 測試 固定 操作 進行 col 安卓 上下滾動 inf 這幾天做小程序,有些頁面都是全屏的背景,在安卓上背景是固定的,而在ios上上拉下拉出現白色,測試說體驗不太好,一開始我以為是下拉上拉刷新造成的,關閉了依然是這樣。為了體驗好點,可以按一下解決: 方式一:   可

用jquery製作一個二級導航選單

大體流程:        1使用$(function(){...})獲取到想要作用的HTML元素。       2通過使用children()方法尋找子元素。    &

多級列表預設觸發事件載入資料

jQuery.get("./getProvinceList",{},function(data){ console.log(); var list = data.data.list; var html = "<option value='0

純css製作導航選單

 轉載文章,覺得作者思路很好  <nav>         <ul>         

CSS實戰心得筆記——常用選單

寫作目的 花了一個月左右的時間,學完了HTML5和CSS的基礎知識,主要通過W3school、菜鳥教程和網易雲課堂的網課。學習過程中CSDN的很多部落格給了我幫助和啟發,效果要比生硬的教程好得多。因此,開始實戰練習的過程中,把每個案例的實現及其思路記錄在這裡,作為總結。 常用下拉選單