你的位置:首页 > 操作系统

[操作系统]下拉框选择效果的实现原理


导航栏与下拉框的效果

实现的效果是在导航栏中间出现下拉框选择的效果,当选择某一个时,则上面的字也相应进行修改(此实例代码可以看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