不管是搜索框还是下拉菜单,我们都需要对背景的图片进行拉伸。定义一个Category分类对图片进行操作。
UIImage+Effect.h
#import <UIKit/UIKit.h> @interface UIImage (Effect) /** * 返回一张可以随意拉伸不变形的图片 * * @param name 图片名字 */ + (UIImage *)imageToResizable:(NSString *)name; @end
UIImage+Effect.m
#import "UIImage+Effect.h" @implementation UIImage (Effect) /** * 返回一张可以随意拉伸不变形的图片 * * @param name 图片名字 */ + (UIImage *)imageToResizable:(NSString *)name { UIImage *normal = [UIImage imageNamed:name]; CGFloat w = normal.size.width * 0.5; CGFloat h = normal.size.height * 0.5; return [normal resizableImageWithCapInsets:UIEdgeInsetsMake(h, w, h, w)]; } @end
搜索框
由于系统自带的不符合我们的要求,自定义一个搜索框
思路:
继承UITextField,设置背景图片,左边显示的图标。
SearchBar.h
#import <UIKit/UIKit.h> @interface SearchBar : UITextField +(instancetype)searchBar; @end
SearchBar.m
#import "SearchBar.h" #import "UIImage+Effect.h" @implementation SearchBar -(instancetype)initWithFrame:(CGRect)frame { if (self=[super initWithFrame:frame]) { self.font=[UIFont systemFontOfSize:15]; self.placeholder=@"请输入搜索条件"; self.background =[UIImage imageToResizable:@"searchbar_textfield_background"]; UIImageView *searchIcon=[[UIImageView alloc]init]; searchIcon.image=[UIImage imageNamed:@"searchbar_textfield_search_icon"]; searchIcon.height=30; searchIcon.width=30; // 保持图片原来的尺寸 searchIcon.contentMode=UIViewContentModeCenter; self.leftView=searchIcon; self.leftViewMode=UITextFieldViewModeAlways; } return self; } +(instancetype)searchBar { return [[self alloc]init]; } @end
使用时候很简单:
- (void)viewDidLoad { [super viewDidLoad]; SearchBar *searchBar=[SearchBar searchBar]; searchBar.width=300; searchBar.height=30; self.navigationItem.titleView=searchBar; }
标题带箭头
思路:
- 自定义按钮
- 原生的按钮,箭头是在左边,文字在右边,通过在加载layoutSubviews,调整文字的x值是箭头的x值,箭头的x值是文字的最大x值。
- 每次文字更改,重新计算文字的size
TitleButton.h
#import <UIKit/UIKit.h> @interface TitleButton : UIButton @end
TitleButton.m
// // TitleButton.m // Weibo // // Created by jiangys on 15/10/8. // Copyright © 2015年 Jiangys. All rights reserved. // #import "TitleButton.h" @implementation TitleButton - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; self.titleLabel.font = [UIFont boldSystemFontOfSize:17]; [self setImage:[UIImage imageNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; [self setImage:[UIImage imageNamed:@"navigationbar_arrow_up"] forState:UIControlStateSelected]; } return self; } // 目的:想在系统计算和设置完按钮的尺寸后,再修改一下尺寸 /** * 重写setFrame:方法的目的:拦截设置按钮尺寸的过程 * 如果想在系统设置完控件的尺寸后,再做修改,而且要保证修改成功,一般都是在setFrame:中设置 */ - (void)setFrame:(CGRect)frame { frame.size.width += 5; [super setFrame:frame]; } - (void)layoutSubviews { [super layoutSubviews]; // 如果仅仅是调整按钮内部titleLabel和imageView的位置,那么在layoutSubviews中单独设置位置即可 // 1.计算titleLabel的frame self.titleLabel.x = self.imageView.x; // 2.计算imageView的frame self.imageView.x = CGRectGetMaxX(self.titleLabel.frame) + 5; } - (void)setTitle:(NSString *)title forState:(UIControlState)state { [super setTitle:title forState:state]; // 只要修改了文字,就让按钮重新计算自己的尺寸 [self sizeToFit]; } - (void)setImage:(UIImage *)image forState:(UIControlState)state { [super setImage:image forState:state]; // 只要修改了图片,就让按钮重新计算自己的尺寸 [self sizeToFit]; } @end
使用:
/* 中间的标题按钮 */ TitleButton *titleButton = [[TitleButton alloc] init]; [titleButton setTitle:@"首页" forState:UIControlStateNormal]; // 监听标题点击 [titleButton addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside]; self.navigationItem.titleView = titleButton;
下拉菜单
思路:
- 自定义一个下拉框DropdownMenu,该下拉框是继承一个UIView,在DropdownMenu显示的时候,设置尺寸为整个windows宽高,并设置背景颜色为无色。
- 往DropdownMenu 增加一个用来显示菜单的容器UIImageView,该容器的背景图是新浪提供,在初始化的时候,传入tableController.View ,并设置大小。
- 显示的位置,在DropdownMenu显示时设置。
- 定义两个方法,除了Show显示方法,还需要定义一个销毁方法,当DropdownMenu被点击touchesBegan时,销毁(隐藏掉)
- 定义代理,当DropdownMenu显示或者隐藏的时候,对外通知
DropdownMenu.h
#import <UIKit/UIKit.h> @class DropdownMenu; @protocol DropdownMenuDelegate <NSObject> @optional - (void)dropdownMenuDidDismiss:(DropdownMenu *)menu; - (void)dropdownMenuDidShow:(DropdownMenu *)menu; @end @interface DropdownMenu : UIView @property (nonatomic, weak) id<DropdownMenuDelegate> delegate; /** * 内容 */ @property (nonatomic, strong) UIView *content; /** * 内容控制器 */ @property (nonatomic, strong) UIViewController *contentController; /** * 初始化菜单 */ +(instancetype)menu; /** * 显示 * * @param from 要显示的控件上 */ - (void)showFrom:(UIView *)from; /** * 销毁 */ - (void)dismiss; @end
DropdownMenu.m
// // DropdownMenu.m // Weibo // // Created by jiangys on 15/10/6. // Copyright © 2015年 Jiangys. All rights reserved. // #import "DropdownMenu.h" #import "UIImage+Effect.h" @interface DropdownMenu() /** * 将来用来显示具体内容的容器 */ @property (nonatomic, weak) UIImageView *containerView; @end @implementation DropdownMenu - (UIImageView *)containerView { if (!_containerView) { // 添加一个灰色图片控件 UIImageView *containerView = [[UIImageView alloc] init]; // 拉伸图片 containerView.image =[UIImage imageToResizable:@"popover_background"]; containerView.userInteractionEnabled = YES; // 开启交互 [self addSubview:containerView]; self.containerView = containerView; } return _containerView; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 清除颜色 self.backgroundColor = [UIColor clearColor]; } return self; } + (instancetype)menu { return [[self alloc] init]; } - (void)setContent:(UIView *)content { _content = content; // 调整内容的位置 content.x = 10; content.y = 15; // 设置灰色的高度 self.containerView.height = CGRectGetMaxY(content.frame) + 11; // 设置灰色的宽度 self.containerView.width = CGRectGetMaxX(content.frame) + 10; // 添加内容到灰色图片中 [self.containerView addSubview:content]; } - (void)setContentController:(UIViewController *)contentController { _contentController = contentController; self.content = contentController.view; } /** * 显示 */ - (void)showFrom:(UIView *)from { // 1.获得最上面的窗口 UIWindow *window = [[UIApplication sharedApplication].windows lastObject]; // 2.添加自己到窗口上 [window addSubview:self]; // 3.设置尺寸 self.frame = window.bounds; // 4.调整灰色图片的位置 // 默认情况下,frame是以父控件左上角为坐标原点 // 转换坐标系 CGRect newFrame = [from convertRect:from.bounds toView:window]; // CGRect newFrame = [from.superview convertRect:from.frame toView:window]; self.containerView.centerX = CGRectGetMidX(newFrame); self.containerView.y = CGRectGetMaxY(newFrame); // 通知外界,自己显示了 if ([self.delegate respondsToSelector:@selector(dropdownMenuDidShow:)]) { [self.delegate dropdownMenuDidShow:self]; } } /** * 销毁 */ - (void)dismiss { [self removeFromSuperview]; // 通知外界,自己被销毁了 if ([self.delegate respondsToSelector:@selector(dropdownMenuDidDismiss:)]) { [self.delegate dropdownMenuDidDismiss:self]; } } /** * 点击其它空白地方销毁 */ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self dismiss]; } @end
通用的时候,很简单,先实现代理,设置当前控制器为代理
/** * 标题点击 */ - (void)titleClick:(UIButton *)titleButton { // 1.创建下拉菜单 DropdownMenu *menu = [DropdownMenu menu]; menu.delegate = self; // 2.设置内容 TitleMenuViewController *vc = [[TitleMenuViewController alloc] init]; vc.view.height = 150; vc.view.width = 150; menu.contentController = vc; // 3.显示 [menu showFrom:titleButton]; }
该章节源码下载:http://pan.baidu.com/s/1pJ5UTjd
新浪微博Github:https://github.com/jiangys/Weibo