下拉框选择效果的实现原理
导航栏与下拉框的效果
实现的效果是在导航栏中间出现下拉框选择的效果,当选择某一个时,则上面的字也相应进行修改(此实例代码可以看Coding.net的源代码),这边有把它单独提取出来进行测试,源代码下载;接下来将简单介绍一下此实现的方式及主要代码;
1:因为我们是跟导航栏进行结合,所以这边用到的NavigationController,我们把这个页面的效果放在viewController中,弹出来的下拉列表这边是以表格的形式存在,每个则是表格的一行,行里面包括图标跟文字;
首先看一下AppDelegate.m的代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; ViewController *loginVC = [[ViewController alloc] init]; [self.window setRootViewController:[[UINavigationController alloc] initWithRootViewController:loginVC]]; [self.window makeKeyAndVisible]; return YES; }
接着是ViewController.h及ViewController.m的代码:
#import <UIKit/UIKit.h> #import "UIViewController+DownMenu.h" @interface ViewController : UIViewController @end
#import "ViewController.h" @interface ViewController () @property (nonatomic, assign) NSInteger curIndex; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _curIndex = 0; [self customDownMenuWithTitles:@[[DownMenuTitle title:@"冒泡广场" image:@"nav_tweet_all" badge:nil], [DownMenuTitle title:@"好友圈" image:@"nav_tweet_friend" badge:nil], [DownMenuTitle title:@"热门冒泡" image:@"nav_tweet_hot" badge:nil], [DownMenuTitle title:@"我的冒泡" image:@"nav_tweet_mine" badge:nil]] andDefaultIndex:_curIndex andBlock:^(id titleObj, NSInteger index) { [(DownMenuTitle *)titleObj setBadgeValue:nil]; _curIndex = index; [self refreshFirst]; }]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void)refreshFirst { NSLog(@"%ld",_curIndex); } @end
这边把一些内容封装到的UIViewController+DownMenu.h这个文件及实现里;
2:UIViewController+DownMenu主要代码如下:
#import <UIKit/UIKit.h> #import "UIDownMenuButton.h" @class DownMenuTitle; @interface UIViewController (DownMenu) - (UIDownMenuButton *)customDownMenuWithTitles:(NSArray *)titleList andDefaultIndex:(NSInteger)index andBlock:(void (^)(id titleObj, NSInteger index))block; - (UIDownMenuButton *)downMenuBtn; @end
#import "UIViewController+DownMenu.h" @implementation UIViewController (DownMenu) - (UIDownMenuButton *)customDownMenuWithTitles:(NSArray *)titleList andDefaultIndex:(NSInteger)index andBlock:(void (^)(id titleObj, NSInteger index))block{ UIDownMenuButton *navBtn = [[UIDownMenuButton alloc] initWithTitles:titleList andDefaultIndex:index andVC:self]; navBtn.menuIndexChanged = block; self.navigationItem.titleView = navBtn; return navBtn; } - (UIDownMenuButton *)downMenuBtn{ if (self.navigationItem.titleView || [self.navigationItem.titleView isKindOfClass:[UIDownMenuButton class]]) { UIDownMenuButton *navBtn = (UIDownMenuButton *)self.navigationItem.titleView; return navBtn; }else{ return nil; } } @end
注意:UIDownMenuButton这个就是上面每个行的封装,这边可以看到在其对它进行增加到nav里面;
3:UIDownMenuButton主要代码如下:
#import <UIKit/UIKit.h> #import "NSString+Common.h" @class DownMenuTitle; @interface UIDownMenuButton : UIButton <UITableViewDataSource, UITableViewDelegate> @property (nonatomic, assign) NSInteger curIndex; - (UIDownMenuButton *)initWithTitles:(NSArray *)titleList andDefaultIndex:(NSInteger)index andVC:(UIViewController *)viewcontroller; @property (nonatomic,copy) void(^menuIndexChanged)(id titleObj, NSInteger index); @end @interface DownMenuTitle : NSObject @property (nonatomic, strong) NSString *titleValue, *imageName, *badgeValue; + (DownMenuTitle *)title:(NSString *)title image:(NSString *)image badge:(NSString *)badge; @end
#define kNavImageWidth (15.0+5.0) #define kDownMenu_ContentLeftPading 27.0 #define kDownMenuCellHeight 50.0 #define kNavTitleFontSize 19 #define kScreen_Bounds [UIScreen mainScreen].bounds #define kScreen_Height [UIScreen mainScreen].bounds.size.height #define kScreen_Width [UIScreen mainScreen].bounds.size.width #define kKeyWindow [UIApplication sharedApplication].keyWindow #define DEGREES_TO_RADIANS(angle) ((angle)/180.0 *M_PI) #define RADIANS_TO_DEGREES(radians) ((radians)*(180.0/M_PI)) #import "UIDownMenuButton.h" #import "DownMenuCell.h" @interface UIDownMenuButton() @property (nonatomic, strong) NSArray *titleList; @property (nonatomic, assign) BOOL isShowing; @property (nonatomic, strong) UIView *mySuperView, *myTapBackgroundView; @property (nonatomic, strong) UITableView *myTableView; @end @implementation UIDownMenuButton - (UIDownMenuButton *)initWithTitles:(NSArray *)titleList andDefaultIndex:(NSInteger)index andVC:(UIViewController *)viewcontroller{ self = [super init]; if (self) { _titleList = titleList; _curIndex = index; _isShowing = NO; _mySuperView = viewcontroller.view; self.backgroundColor = [UIColor clearColor]; [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [self setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted]; [self.titleLabel setFont:[UIFont systemFontOfSize:kNavTitleFontSize]]; [self.titleLabel setMinimumScaleFactor:0.5]; [self addTarget:self action:@selector(changeShowing) forControlEvents:UIControlEventTouchUpInside]; [self refreshSelfUI]; } return self; } - (void)refreshSelfUI{ NSString *titleStr = @""; DownMenuTitle *menuObj = [self.titleList objectAtIndex:self.curIndex]; titleStr = menuObj.titleValue; CGFloat titleWidth = [titleStr getWidthWithFont:self.titleLabel.font constrainedToSize:CGSizeMake(kScreen_Width, 30)]; CGFloat btnWidth = titleWidth +kNavImageWidth; self.frame = CGRectMake((kScreen_Width-btnWidth)/2, (44-30)/2, btnWidth, 30); self.titleEdgeInsets = UIEdgeInsetsMake(0, -kNavImageWidth, 0, kNavImageWidth); self.imageEdgeInsets = UIEdgeInsetsMake(0, titleWidth, 0, -titleWidth); [self setTitle:titleStr forState:UIControlStateNormal]; [self setImage:[UIImage imageNamed:@"nav_arrow_down"] forState:UIControlStateNormal]; } - (void)changeShowing{ [kKeyWindow endEditing:YES]; if (!self.myTableView) { //定义其显示的位置 self.myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0,64, kScreen_Width, 0) style:UITableViewStylePlain]; [self.myTableView registerClass:[DownMenuCell class] forCellReuseIdentifier:kCellIdentifier_DownMenu]; self.myTableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.myTableView.dataSource = self; self.myTableView.delegate = self; self.myTableView.alpha = 0; self.myTableView.scrollEnabled = NO; } if (!self.myTapBackgroundView) { self.myTapBackgroundView = [[UIView alloc] initWithFrame:kScreen_Bounds]; self.myTapBackgroundView.backgroundColor = [UIColor clearColor]; UITapGestureRecognizer *bgTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeShowing)]; [self.myTapBackgroundView addGestureRecognizer:bgTap]; } if (self.isShowing) {//隐藏 CGRect frame = self.myTableView.frame; frame.size.height = 0; self.enabled = NO; [UIView animateWithDuration:0.3 animations:^{ [self refreshSelfUI]; self.myTapBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0]; self.myTableView.alpha = 0; self.myTableView.frame = frame; self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, DEGREES_TO_RADIANS(180)); } completion:^(BOOL finished) { [self.myTableView removeFromSuperview]; [self.myTapBackgroundView removeFromSuperview]; self.enabled = YES; self.isShowing = !self.isShowing; }]; }else{//显示 [[UIApplication sharedApplication].keyWindow addSubview:self.myTapBackgroundView]; [[UIApplication sharedApplication].keyWindow addSubview:self.myTableView]; [self.myTableView reloadData]; CGRect frame = self.myTableView.frame; frame.size.height = kDownMenuCellHeight *[self.titleList count]; self.enabled = NO; [UIView animateWithDuration:0.3 animations:^{ self.myTapBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2]; self.myTableView.alpha = 1.0; self.myTableView.frame = frame; self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, DEGREES_TO_RADIANS(180)); } completion:^(BOOL finished) { self.enabled = YES; self.isShowing = YES; }]; } } #pragma mark Table M - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [self.titleList count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ DownMenuCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier_DownMenu forIndexPath:indexPath]; DownMenuTitle *curItem =[self.titleList objectAtIndex:indexPath.row]; cell.curItem = curItem; cell.backgroundColor = (indexPath.row == self.curIndex)? [UIColor colorWithHexString:@"0xf3f3f3"] : [UIColor whiteColor]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return kDownMenuCellHeight; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ [tableView deselectRowAtIndexPath:indexPath animated:YES]; self.curIndex = indexPath.row; [self changeShowing]; if (self.menuIndexChanged) { self.menuIndexChanged([self.titleList objectAtIndex:_curIndex], _curIndex); } } - (void)setCurIndex:(NSInteger)curIndex{ _curIndex = curIndex; [UIView animateWithDuration:0.3 animations:^{ [self refreshSelfUI]; // [self.myTableView reloadData]; // [self.myTableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.3]; }]; } - (void)dealloc { self.myTableView.delegate = nil; } @end @implementation DownMenuTitle + (DownMenuTitle *)title:(NSString *)title image:(NSString *)image badge:(NSString *)badge{ DownMenuTitle *menuObj = [[DownMenuTitle alloc] init]; menuObj.titleValue = title; menuObj.badgeValue = badge; menuObj.imageName = image; return menuObj; } @end
其中refreshSelfUI这个方法里面是实现的选择时,对应文字跟箭头图标的变化;重点的内容在changeShowing这个方法,它有定义列表要显示的位置,列表的创建初始化,及背景模态的出现,显示及隐藏的内容,视图的创建及删除;最后一个是实体的赋值;
4:表格单元行的布局DownMenuCell,主要代码如下:
#define kCellIdentifier_DownMenu @"DownMenuCell" #import <UIKit/UIKit.h> #import "UIDownMenuButton.h" #import "UIColor+expanded.h" @interface DownMenuCell : UITableViewCell @property (strong, nonatomic) DownMenuTitle *curItem; @end
#import "DownMenuCell.h" @implementation DownMenuCell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Initialization code } return self; } - (void)awakeFromNib { // Initialization code } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } - (void)layoutSubviews{ [super layoutSubviews]; if (!_curItem) { return; } self.imageView.frame = CGRectMake(27, (50.0-25.0)/2, 25, 25); self.textLabel.frame = CGRectMake(65, (50.0-25.0)/2, 150, 25); self.textLabel.backgroundColor = [UIColor clearColor]; self.textLabel.textColor = [UIColor blackColor]; self.textLabel.font = [UIFont systemFontOfSize:15]; self.imageView.image = [UIImage imageNamed:_curItem.imageName]; self.textLabel.text = _curItem.titleValue;; } @end