zoukankan      html  css  js  c++  java
  • iOS 新浪微博-2.0 搜索框/标题带箭头/下拉菜单

    不管是搜索框还是下拉菜单,我们都需要对背景的图片进行拉伸。定义一个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;

    下拉菜单

    思路:

    1. 自定义一个下拉框DropdownMenu,该下拉框是继承一个UIView,在DropdownMenu显示的时候,设置尺寸为整个windows宽高,并设置背景颜色为无色。
    2. 往DropdownMenu 增加一个用来显示菜单的容器UIImageView,该容器的背景图是新浪提供,在初始化的时候,传入tableController.View ,并设置大小。
    3. 显示的位置,在DropdownMenu显示时设置。
    4. 定义两个方法,除了Show显示方法,还需要定义一个销毁方法,当DropdownMenu被点击touchesBegan时,销毁(隐藏掉)
    5. 定义代理,当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

  • 相关阅读:
    Java小细节
    LinkedHashMap的accessOrder的作用
    异或运算及其应用
    什么是FullStack设计
    Java正则表达式收藏
    offsetLeft,Left,clientLeft的区别
    java文件常用操作(2) 从文件末尾开始读取文件
    java文件常用操作
    各种排序方法
    2013微软暑期实习笔试&面试总结
  • 原文地址:https://www.cnblogs.com/jys509/p/4856597.html
Copyright © 2011-2022 走看看