• 网易新闻侧滑抽屉效果(利用父子控制器实现)


    一:类似于网易的抽屉效果,启动有广告,进入主界面后,点击左上角按钮,侧滑左抽屉,点击右上角,侧滑出右抽屉。点击左抽屉按钮,对视图进行切换

     二代码:

    1:启动图展示广告界面实现:先吧启动图控制器作为窗口的根视图控制器,展示完广告消失后,再切换窗口的根视图控制器为主控制器。其中窗口指的是项目中的主窗口也就是keyWindow,主窗口主要负责接收一些键盘事件,文本框输入事件,若是键盘文本框,textView或是textfield不能输入,则考虑是不是当前窗口是否是主窗口

    @interface HMAdViewController ()
    
    @end
    
    @implementation HMAdViewController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // 1.背景图片
        UIImageView *bg = [[UIImageView alloc] init];
        bg.image = [UIImage imageNamed:@"Default"];
        bg.frame = self.view.bounds;
        [self.view addSubview:bg];
        
        // 2.广告图片(真实的广告图片应该要先下载广告图片)
        UIImageView *ad = [[UIImageView alloc] init];
        ad.image = [UIImage imageNamed:@"ad"];
        ad.width = 280;
        ad.height = 300;
        ad.centerX = self.view.width * 0.5;
        ad.y = 60;
        [self.view addSubview:ad];
        
        // 3.2s后调到下一个主界面
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            UIWindow *window = [UIApplication sharedApplication].keyWindow;
            UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
            window.rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"Main"];
        });
    }
    
    @end

    2:当启动图广告界面展示完毕后,切换窗口根视图控制器。

      1 #import "HMMainViewController.h"
      2 #import "HMLeftMenu.h"
      3 #import "HMRightMenuController.h"
      4 #import "HMNavigationController.h"
      5 #import "HMNewsViewController.h"
      6 #import "HMReadingViewController.h"
      7 #import "HMTitleView.h"
      8 
      9 #define HMNavShowAnimDuration 0.25
     10 #define HMCoverTag 100
     11 #define HMLeftMenuW 150
     12 #define HMLeftMenuH 300
     13 #define HMLeftMenuY 50
     14 
     15 @interface HMMainViewController () <HMLeftMenuDelegate>
     16 /**
     17  *  正在显示的导航控制器
     18  */
     19 @property (nonatomic, weak) HMNavigationController *showingNavigationController;
     20 @property (nonatomic, strong) HMRightMenuController *rightMenuVc;
     21 @property (nonatomic, weak) HMLeftMenu *leftMenu;
     22 @end
     23 
     24 @implementation HMMainViewController
     25 
     26 - (void)viewDidLoad
     27 {
     28     [super viewDidLoad];
     29     
     30     // 1.创建子控制器
     31     [self setupAllChildVcs];
     32     
     33     // 2.添加左菜单
     34     [self setupLeftMenu];
     35     
     36     // 3.添加右菜单
     37     [self setupRightMenu];
     38 }
     39 
     40 
     41 /**
     42  *  添加右菜单
     43  */
     44 - (void)setupRightMenu
     45 {
     46     HMRightMenuController *rightMenuVc = [[HMRightMenuController alloc] init];
     47     rightMenuVc.view.x = self.view.width - rightMenuVc.view.width;
     48     [self.view insertSubview:rightMenuVc.view atIndex:1];
     49     self.rightMenuVc = rightMenuVc;
     50 }
     51 
     52 /**
     53  *  添加左菜单
     54  */
     55 - (void)setupLeftMenu
     56 {
     57     HMLeftMenu *leftMenu = [[HMLeftMenu alloc] init];
     58     leftMenu.delegate = self;
     59     leftMenu.height = HMLeftMenuH;
     60     leftMenu.width = HMLeftMenuW;
     61     leftMenu.y = HMLeftMenuY;
     62     [self.view insertSubview:leftMenu atIndex:1];
     63     self.leftMenu = leftMenu;
     64 }
     65 
     66 /**
     67  *  创建子控制器
     68  */
     69 - (void)setupAllChildVcs
     70 {
     71     // 1.新闻控制器
     72     HMNewsViewController *news = [[HMNewsViewController alloc] init];
     73     [self setupVc:news title:@"新闻"];
     74     
     75     // 2.订阅控制器
     76     HMReadingViewController *reading = [[HMReadingViewController alloc] init];
     77     [self setupVc:reading title:@"订阅"];
     78     
     79     // 3.图片控制器
     80     UIViewController *photo = [[UIViewController alloc] init];
     81     [self setupVc:photo title:@"图片"];
     82     
     83     // 4.视频控制器
     84     UIViewController *video = [[UIViewController alloc] init];
     85     [self setupVc:video title:@"视频"];
     86     
     87     // 5.跟帖控制器
     88     UIViewController *comment = [[UIViewController alloc] init];
     89     [self setupVc:comment title:@"跟帖"];
     90     
     91     // 6.电台控制器
     92     UIViewController *radio = [[UIViewController alloc] init];
     93     [self setupVc:radio title:@"电台"];
     94 }
     95 
     96 - (UIStatusBarStyle)preferredStatusBarStyle
     97 {
     98     return UIStatusBarStyleLightContent;
     99 }
    100 
    101 /**
    102  *  初始化一个控制器
    103  *
    104  *  @param vc      需要初始化的控制器
    105  *  @param title   控制器的标题
    106  */
    107 - (void)setupVc:(UIViewController *)vc title:(NSString *)title
    108 {
    109     // 1.设置背景色
    110     vc.view.backgroundColor = HMRandomColor;
    111     
    112     // 2.设置标题
    113     HMTitleView *titleView = [[HMTitleView alloc] init];
    114     titleView.title = title;
    115     vc.navigationItem.titleView = titleView;
    116     
    117     // 3.设置左右按钮
    118     vc.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithImageName:@"top_navigation_menuicon" target:self action:@selector(leftMenuClick)];
    119     vc.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithImageName:@"top_navigation_infoicon" target:self action:@selector(rightMenuClick)];
    120     
    121     // 4.包装一个导航控制器
    122     HMNavigationController *nav = [[HMNavigationController alloc] initWithRootViewController:vc];
    123     // 让newsNav成为self(HMMainViewController)的子控制器,能保证:self在,newsNav就在
    124     // 如果两个控制器互为父子关系,那么它们的view也应该互为父子关系
    125     [self addChildViewController:nav];
    126 }
    127 
    128 #pragma mark - 监听导航栏按钮点击
    129 - (void)leftMenuClick
    130 {
    131     self.leftMenu.hidden = NO;
    132     self.rightMenuVc.view.hidden = YES;
    133     
    134     [UIView animateWithDuration:HMNavShowAnimDuration animations:^{
    135         // 取出正在显示的导航控制器的view
    136         UIView *showingView = self.showingNavigationController.view;
    137         
    138         // 缩放比例
    139         CGFloat navH = [UIScreen mainScreen].bounds.size.height - 2 * HMLeftMenuY;
    140         CGFloat scale = navH / [UIScreen mainScreen].bounds.size.height;
    141         
    142         // 菜单左边的间距
    143         CGFloat leftMenuMargin = [UIScreen mainScreen].bounds.size.width * (1 - scale) * 0.5;
    144         CGFloat translateX = HMLeftMenuW - leftMenuMargin;
    145         
    146         CGFloat topMargin = [UIScreen mainScreen].bounds.size.height * (1 - scale) * 0.5;
    147         CGFloat translateY = HMLeftMenuY - topMargin;
    148         
    149         // 缩放
    150         CGAffineTransform scaleForm = CGAffineTransformMakeScale(scale, scale);
    151         // 平移
    152         CGAffineTransform translateForm = CGAffineTransformTranslate(scaleForm, translateX / scale, translateY / scale);
    153         
    154         showingView.transform = translateForm;
    155         
    156         // 添加一个遮盖
    157         UIButton *cover = [[UIButton alloc] init];
    158         cover.tag = HMCoverTag;
    159         [cover addTarget:self action:@selector(coverClick:) forControlEvents:UIControlEventTouchUpInside];
    160         cover.frame = showingView.bounds;
    161         [showingView addSubview:cover];
    162     }];
    163 }
    164 
    165 - (void)coverClick:(UIView *)cover
    166 {
    167     [UIView animateWithDuration:HMNavShowAnimDuration animations:^{
    168         self.showingNavigationController.view.transform = CGAffineTransformIdentity;
    169     } completion:^(BOOL finished) {
    170         [cover removeFromSuperview];
    171     }];
    172 }
    173 
    174 - (void)rightMenuClick
    175 {
    176     self.leftMenu.hidden = YES;
    177     self.rightMenuVc.view.hidden = NO;
    178     
    179     [UIView animateWithDuration:HMNavShowAnimDuration animations:^{
    180         // 取出正在显示的导航控制器的view
    181         UIView *showingView = self.showingNavigationController.view;
    182         
    183         // 缩放比例
    184         CGFloat navH = [UIScreen mainScreen].bounds.size.height - 2 * HMLeftMenuY;
    185         CGFloat scale = navH / [UIScreen mainScreen].bounds.size.height;
    186         
    187         // 菜单左边的间距
    188         CGFloat leftMenuMargin = [UIScreen mainScreen].bounds.size.width * (1 - scale) * 0.5;
    189         CGFloat translateX = leftMenuMargin - self.rightMenuVc.view.width;
    190         
    191         CGFloat topMargin = [UIScreen mainScreen].bounds.size.height * (1 - scale) * 0.5;
    192         CGFloat translateY = HMLeftMenuY - topMargin;
    193         
    194         // 缩放
    195         CGAffineTransform scaleForm = CGAffineTransformMakeScale(scale, scale);
    196         // 平移
    197         CGAffineTransform translateForm = CGAffineTransformTranslate(scaleForm, translateX / scale, translateY / scale);
    198         
    199         showingView.transform = translateForm;
    200         
    201         // 添加一个遮盖
    202         UIButton *cover = [[UIButton alloc] init];
    203         cover.tag = HMCoverTag;
    204         [cover addTarget:self action:@selector(coverClick:) forControlEvents:UIControlEventTouchUpInside];
    205         cover.frame = showingView.bounds;
    206         [showingView addSubview:cover];
    207     } completion:^(BOOL finished) {
    208         [self.rightMenuVc didShow];
    209     }];
    210 }
    211 
    212 #pragma mark - HMLeftMenuDelegate
    213 - (void)leftMenu:(HMLeftMenu *)menu didSelectedButtonFromIndex:(int)fromIndex toIndex:(int)toIndex
    214 {
    215     // 0.移除旧控制器的view
    216     HMNavigationController *oldNav = self.childViewControllers[fromIndex];
    217     [oldNav.view removeFromSuperview];
    218     
    219     // 1.显示新控制器的view
    220     HMNavigationController *newNav = self.childViewControllers[toIndex];
    221     [self.view addSubview:newNav.view];
    222     
    223     // 2.设置新控制的transform跟旧控制器一样
    224     newNav.view.transform = oldNav.view.transform;
    225     // 设置阴影
    226     newNav.view.layer.shadowColor = [UIColor blackColor].CGColor;
    227     newNav.view.layer.shadowOffset = CGSizeMake(-3, 0);
    228     newNav.view.layer.shadowOpacity = 0.2;
    229     
    230     // 一个导航控制器的view第一次显示到它的父控件上时,如果transform的缩放值被改了,上面的20高度当时是不会出来
    231     
    232     // 2.设置当前正在显示的控制器
    233     self.showingNavigationController = newNav;
    234     
    235     // 3.点击遮盖
    236     [self coverClick:[newNav.view viewWithTag:HMCoverTag]];
    237 }
    238 @end

    3:封装NAV导航控制器

     1 #import "HMNavigationController.h"
     2 #import "HMNavigationBar.h"
     3 
     4 @interface HMNavigationController ()
     5 
     6 @end
     7 
     8 @implementation HMNavigationController
     9 
    10 + (void)initialize
    11 {
    12     UINavigationBar *appearance = [UINavigationBar appearance];
    13     
    14     // 设置导航栏背景
    15     [appearance setBackgroundImage:[UIImage imageNamed:@"top_navigation_background"] forBarMetrics:UIBarMetricsDefault];
    16 }
    17 
    18 - (void)viewDidLoad
    19 {
    20     [super viewDidLoad];
    21     
    22     // 替换为自定义的导航栏
    23     [self setValue:[[HMNavigationBar alloc] init] forKeyPath:@"navigationBar"];
    24 }
    25 
    26 #pragma mark - 这个方法也是专门用来布局子控件(当控制器的view尺寸发生改变的时候会调用)
    27 //- (void)viewDidLayoutSubviews
    28 //{
    29 //    [super viewDidLayoutSubviews];
    30 //    
    31 //    for (UIButton *button in self.navigationBar.subviews) {
    32 //        if (![button isKindOfClass:[UIButton class]]) continue;
    33 //
    34 //        if (button.centerX < self.navigationBar.width * 0.5) { // 左边的按钮
    35 //            button.x = 0;
    36 //        } else if (button.centerX > self.navigationBar.width * 0.5) { // 右边的按钮
    37 //            button.x = self.view.width - button.width;
    38 //        }
    39 //    }
    40 //}
    41 
    42 @end

    4:封装导航栏:目的是调整导航栏上左右item距离边框的位置.。左右按钮的背景图片,应该做成图片在中间,四周为镂空的图片

     1 #import "HMNavigationBar.h"
     2 
     3 @implementation HMNavigationBar
     4 
     5 - (id)initWithFrame:(CGRect)frame
     6 {
     7     self = [super initWithFrame:frame];
     8     if (self) {
     9         // Initialization code
    10     }
    11     return self;
    12 }
    13 
    14 - (void)layoutSubviews
    15 {
    16     [super layoutSubviews];
    17     
    18     for (UIButton *button in self.subviews) {
    19         if (![button isKindOfClass:[UIButton class]]) continue;
    20 
    21         if (button.centerX < self.width * 0.5) { // 左边的按钮
    22             button.x = 0;
    23         } else if (button.centerX > self.width * 0.5) { // 右边的按钮
    24             button.x = self.width - button.width;
    25         }
    26     }
    27 }
    28 @end

    5:封装titleView:titleView由图片和文字构成,可以用button来实现,既可以设置图片也可以设置文字

    1 #import <UIKit/UIKit.h>
    2 
    3 @interface HMTitleView : UIButton
    4 @property (nonatomic, copy) NSString *title;
    5 @end
     1 #import "HMTitleView.h"
     2 
     3 @implementation HMTitleView
     4 
     5 - (id)initWithFrame:(CGRect)frame
     6 {
     7     self = [super initWithFrame:frame];
     8     if (self) {
     9         self.userInteractionEnabled = NO;
    10         [self setImage:[UIImage imageNamed:@"navbar_netease"] forState:UIControlStateNormal];
    11         [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    12         self.titleLabel.font = [UIFont boldSystemFontOfSize:22];
    13         self.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, 0);
    14         self.height = self.currentImage.size.height;
    15     }
    16     return self;
    17 }
    18 
    19 - (void)setTitle:(NSString *)title
    20 {
    21     _title = [title copy];
    22     
    23     [self setTitle:title forState:UIControlStateNormal];
    24     
    25     NSDictionary *attrs = @{NSFontAttributeName : self.titleLabel.font};
    26     CGFloat titleW = [title boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;
    27     
    28     self.width = titleW + self.titleEdgeInsets.left + self.currentImage.size.width;
    29 }
    30 @end

    6:封装item,uiview,image分类

    1 #import <UIKit/UIKit.h>
    2 
    3 @interface UIBarButtonItem (Extension)
    4 + (UIBarButtonItem *)itemWithImageName:(NSString *)imageName target:(id)target action:(SEL)action;
    5 @end
     1 #import "UIBarButtonItem+Extension.h"
     2 
     3 @implementation UIBarButtonItem (Extension)
     4 + (UIBarButtonItem *)itemWithImageName:(NSString *)imageName target:(id)target action:(SEL)action
     5 {
     6     UIButton *button = [[UIButton alloc] init];
     7     [button setBackgroundImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
     8     
     9     // 设置按钮的尺寸为背景图片的尺寸
    10     button.size = button.currentBackgroundImage.size;
    11     
    12     // 监听按钮点击
    13     [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    14     return [[UIBarButtonItem alloc] initWithCustomView:button];
    15 }
    16 @end
     1 #import <UIKit/UIKit.h>
     2 
     3 @interface UIView (Extension)
     4 @property (nonatomic, assign) CGFloat x;
     5 @property (nonatomic, assign) CGFloat y;
     6 @property (nonatomic, assign) CGFloat centerX;
     7 @property (nonatomic, assign) CGFloat centerY;
     8 @property (nonatomic, assign) CGFloat width;
     9 @property (nonatomic, assign) CGFloat height;
    10 @property (nonatomic, assign) CGSize size;
    11 @end
     1 #import "UIView+Extension.h"
     2 
     3 @implementation UIView (Extension)
     4 
     5 - (void)setX:(CGFloat)x
     6 {
     7     CGRect frame = self.frame;
     8     frame.origin.x = x;
     9     self.frame = frame;
    10 }
    11 
    12 - (CGFloat)x
    13 {
    14     return self.frame.origin.x;
    15 }
    16 
    17 - (void)setY:(CGFloat)y
    18 {
    19     CGRect frame = self.frame;
    20     frame.origin.y = y;
    21     self.frame = frame;
    22 }
    23 
    24 - (CGFloat)y
    25 {
    26     return self.frame.origin.y;
    27 }
    28 
    29 - (void)setCenterX:(CGFloat)centerX
    30 {
    31     CGPoint center = self.center;
    32     center.x = centerX;
    33     self.center = center;
    34 }
    35 
    36 - (CGFloat)centerX
    37 {
    38     return self.center.x;
    39 }
    40 
    41 - (void)setCenterY:(CGFloat)centerY
    42 {
    43     CGPoint center = self.center;
    44     center.y = centerY;
    45     self.center = center;
    46 }
    47 
    48 - (CGFloat)centerY
    49 {
    50     return self.center.y;
    51 }
    52 
    53 - (void)setWidth:(CGFloat)width
    54 {
    55     CGRect frame = self.frame;
    56     frame.size.width = width;
    57     self.frame = frame;
    58 }
    59 
    60 - (CGFloat)width
    61 {
    62     return self.frame.size.width;
    63 }
    64 
    65 - (void)setHeight:(CGFloat)height
    66 {
    67     CGRect frame = self.frame;
    68     frame.size.height = height;
    69     self.frame = frame;
    70 }
    71 
    72 - (CGFloat)height
    73 {
    74     return self.frame.size.height;
    75 }
    76 
    77 - (void)setSize:(CGSize)size
    78 {
    79 //    self.width = size.width;
    80 //    self.height = size.height;
    81     CGRect frame = self.frame;
    82     frame.size = size;
    83     self.frame = frame;
    84 }
    85 
    86 - (CGSize)size
    87 {
    88     return self.frame.size;
    89 }
    90 
    91 @end
    1 #import <UIKit/UIKit.h>
    2 
    3 @interface UIImage (Extension)
    4 + (UIImage *)imageWithColor:(UIColor *)color;
    5 @end
     1 #import "UIImage+Extension.h"
     2 
     3 @implementation UIImage (Extension)
     4 + (UIImage *)imageWithColor:(UIColor *)color
     5 {
     6     CGFloat imageW = 100;
     7     CGFloat imageH = 100;
     8     // 1.开启基于位图的图形上下文
     9     UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageW, imageH), NO, 0.0);
    10     
    11     // 2.画一个color颜色的矩形框
    12     [color set];
    13     UIRectFill(CGRectMake(0, 0, imageW, imageH));
    14     
    15     // 3.拿到图片
    16     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    17     
    18     // 4.关闭上下文
    19     UIGraphicsEndImageContext();
    20     
    21     return image;
    22 }
    23 @end

    7:封装左侧菜单

     1 #import <UIKit/UIKit.h>
     2 @class HMLeftMenu;
     3 
     4 @protocol HMLeftMenuDelegate <NSObject>
     5 @optional
     6 - (void)leftMenu:(HMLeftMenu *)menu didSelectedButtonFromIndex:(int)fromIndex toIndex:(int)toIndex;
     7 @end
     8 
     9 @interface HMLeftMenu : UIView
    10 @property (nonatomic, weak) id<HMLeftMenuDelegate> delegate;
    11 @end
      1 #import "HMLeftMenu.h"
      2 #import "HMLeftMenuButton.h"
      3 
      4 @interface HMLeftMenu()
      5 @property (nonatomic, weak) HMLeftMenuButton *selectedButton;
      6 @end
      7 
      8 @implementation HMLeftMenu
      9 
     10 #pragma mark - 初始化
     11 - (id)initWithFrame:(CGRect)frame
     12 {
     13     self = [super initWithFrame:frame];
     14     if (self) {
     15         self.backgroundColor = [UIColor clearColor];
     16         
     17         CGFloat alpha = 0.2;
     18         
     19         [self setupBtnWithIcon:@"sidebar_nav_news" title:@"新闻" bgColor:HMColorRGBA(202, 68, 73, alpha)];
     20         [self setupBtnWithIcon:@"sidebar_nav_reading" title:@"订阅" bgColor:HMColorRGBA(190, 111, 69, alpha)];
     21         [self setupBtnWithIcon:@"sidebar_nav_photo" title:@"图片" bgColor:HMColorRGBA(76, 132, 190, alpha)];
     22         [self setupBtnWithIcon:@"sidebar_nav_video" title:@"视频" bgColor:HMColorRGBA(101, 170, 78, alpha)];
     23         [self setupBtnWithIcon:@"sidebar_nav_comment" title:@"跟帖" bgColor:HMColorRGBA(170, 172, 73, alpha)];
     24         [self setupBtnWithIcon:@"sidebar_nav_radio" title:@"电台" bgColor:HMColorRGBA(190, 62, 119, alpha)];
     25     }
     26     return self;
     27 }
     28 
     29 - (void)setDelegate:(id<HMLeftMenuDelegate>)delegate
     30 {
     31     _delegate = delegate;
     32     
     33     // 默认选中新闻按钮
     34     [self buttonClick:[self.subviews firstObject]];
     35 //    [self buttonClick:self.subviews[1]];
     36 }
     37 
     38 /**
     39  *  添加按钮
     40  *
     41  *  @param icon  图标
     42  *  @param title 标题
     43  */
     44 - (HMLeftMenuButton *)setupBtnWithIcon:(NSString *)icon title:(NSString *)title bgColor:(UIColor *)bgColor
     45 {
     46     HMLeftMenuButton *btn = [[HMLeftMenuButton alloc] init];
     47     btn.tag = self.subviews.count;
     48     [btn addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchDown];
     49     [self addSubview:btn];
     50     
     51     // 设置图片和文字
     52     [btn setImage:[UIImage imageNamed:icon] forState:UIControlStateNormal];
     53     [btn setTitle:title forState:UIControlStateNormal];
     54     [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
     55     btn.titleLabel.font = [UIFont systemFontOfSize:17];
     56     
     57     // 设置按钮选中的背景
     58     [btn setBackgroundImage:[UIImage imageWithColor:bgColor] forState:UIControlStateSelected];
     59     
     60     // 设置高亮的时候不要让图标变色
     61     btn.adjustsImageWhenHighlighted = NO;
     62     
     63     // 设置按钮的内容左对齐
     64     btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
     65     
     66     // 设置间距
     67     btn.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
     68     btn.contentEdgeInsets = UIEdgeInsetsMake(0, 30, 0, 0);
     69     
     70     return btn;
     71 }
     72 
     73 - (void)layoutSubviews
     74 {
     75     [super layoutSubviews];
     76     
     77     // 设置按钮的frame
     78     int btnCount = self.subviews.count;
     79     CGFloat btnW = self.width;
     80     CGFloat btnH = self.height / btnCount;
     81     for (int i = 0; i<btnCount; i++) {
     82         HMLeftMenuButton *btn = self.subviews[i];
     83         btn.width = btnW;
     84         btn.height = btnH;
     85         btn.y = i * btnH;
     86     }
     87 }
     88 
     89 #pragma mark - 私有方法
     90 /**
     91  *  监听按钮点击
     92  */
     93 - (void)buttonClick:(HMLeftMenuButton *)button
     94 {
     95     // 0.通知代理
     96     if ([self.delegate respondsToSelector:@selector(leftMenu:didSelectedButtonFromIndex:toIndex:)]) {
     97         [self.delegate leftMenu:self didSelectedButtonFromIndex:self.selectedButton.tag toIndex:button.tag];
     98     }
     99     
    100     // 1.控制按钮的状态
    101     self.selectedButton.selected = NO;
    102     button.selected = YES;
    103     self.selectedButton = button;
    104 }
    105 @end

    8:封装右侧菜单

    1 #import <UIKit/UIKit.h>
    2 
    3 @interface HMRightMenuController : UIViewController
    4 /**
    5  *  右边菜单全部显示出来
    6  */
    7 - (void)didShow;
    8 @end
     1 #import "HMRightMenuController.h"
     2 #import "HMRightMenuCenterViewRow.h"
     3 
     4 @interface HMRightMenuController ()
     5 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
     6 @property (weak, nonatomic) IBOutlet UIView *centerView;
     7 @property (weak, nonatomic) IBOutlet UIView *bottomView;
     8 @end
     9 
    10 @implementation HMRightMenuController
    11 - (void)viewDidLoad
    12 {
    13     [super viewDidLoad];
    14     
    15     // 1.填充中间的内容
    16     [self setupCenterView];
    17     
    18     // 2.填充底部的内容
    19     [self setupBottomView];
    20 }
    21 
    22 /**
    23  *  填充中间的内容
    24  */
    25 - (void)setupCenterView
    26 {
    27     HMRightMenuCenterViewRow *row =[self setupCenterViewRow:@"商城 能赚能花,土豪当家" icon:@"promoboard_icon_mall"];
    28     [self setupCenterViewRow:@"活动 4.0发布会粉丝招募" icon:@"promoboard_icon_activities"];
    29     [self setupCenterViewRow:@"应用 金币从来都是这送的" icon:@"promoboard_icon_apps"];
    30     
    31     self.centerView.height = self.centerView.subviews.count * row.height;
    32 }
    33 
    34 - (HMRightMenuCenterViewRow *)setupCenterViewRow:(NSString *)title icon:(NSString *)icon
    35 {
    36     HMRightMenuCenterViewRow *row = [HMRightMenuCenterViewRow centerViewRow];
    37     row.icon = icon;
    38     row.title = title;
    39     row.y = row.height * self.centerView.subviews.count;
    40     [self.centerView addSubview:row];
    41     return row;
    42 }
    43 
    44 /**
    45  *  填充底部的内容
    46  */
    47 - (void)setupBottomView
    48 {
    49     
    50 }
    51 
    52 - (void)didShow
    53 {
    54     // 让头像旋转
    55 //    [UIView animateWithDuration:1.0 animations:^{
    56 //        self.iconView.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0);
    57 //    } completion:^(BOOL finished) {
    58 //        self.iconView.image = [UIImage imageNamed:@"user_defaultgift"];
    59 //        
    60 //        [UIView animateWithDuration:1.0 animations:^{
    61 //            self.iconView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
    62 //        }];
    63 //    }];
    64 //    CATransition
    65 //    CATransition *anim = [CATransition animation];
    66 //    anim.duration = 1.0;
    67 //    anim.type = @"rippleEffect";
    68 //    [self.iconView.layer addAnimation:anim forKey:nil];
    69     
    70     [UIView transitionWithView:self.iconView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
    71         self.iconView.image = [UIImage imageNamed:@"user_defaultgift"];
    72     } completion:^(BOOL finished) {
    73         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    74             [UIView transitionWithView:self.iconView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
    75                 self.iconView.image = [UIImage imageNamed:@"default_avatar"];
    76             } completion:nil];
    77         });
    78     }];
    79 }
    80 
    81 @end

    1 #import <UIKit/UIKit.h>
    2 
    3 @interface HMRightMenuCenterViewRow : UIView
    4 + (instancetype)centerViewRow;
    5 
    6 @property (nonatomic, copy) NSString *icon;
    7 @property (nonatomic, copy) NSString *title;
    8 @end
     1 #import "HMRightMenuCenterViewRow.h"
     2 
     3 @interface HMRightMenuCenterViewRow()
     4 @property (weak, nonatomic) IBOutlet UIButton *titleView;
     5 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
     6 @end
     7 
     8 @implementation HMRightMenuCenterViewRow
     9 + (instancetype)centerViewRow
    10 {
    11     return [[[NSBundle mainBundle] loadNibNamed:@"HMRightMenuCenterViewRow" owner:nil options:nil] lastObject];
    12 }
    13 
    14 - (void)setIcon:(NSString *)icon
    15 {
    16     _icon = [icon copy];
    17     
    18     self.iconView.image = [UIImage imageNamed:icon];
    19 }
    20 
    21 - (void)setTitle:(NSString *)title
    22 {
    23     _title = [title copy];
    24     
    25     [self.titleView setTitle:title forState:UIControlStateNormal];
    26 }
    27 @end

     

    三:知识点总结:

    1:启动图的广告展示界面:1:创建启动图展示控制器,其中广告的图片一般是从服务器获取,搞个定时器,GCD延迟函数,经过一段时间后,再切换窗口的根视图控制器为主控制器。 UIWindow *window = [UIApplication sharedApplication].keyWindow;keyWindow为主窗口,负责键盘处理和文本框输入事件,若是textView,textField不能处理-输入事件,或是响应键盘则判断当前显示窗口是否是主窗口keyWindow。2:其中还可以通过keyWindow获取rootViewController,和当前显示的导航控制器,keyWindow.rootViewController, TabBarVC *tab =  keyWindow.rootViewController; NAV *nav = tab.selecteViewcontroller;得到当前显示的导航控制器,nav.viewControllers,得到当前导航控制器栈里的所有控制器。

    2:sattic const 定义常量来代替宏定义: static const CGFloat HMNavShowAnimDuration = 0.25;来代替 #define HMNavShowAnimDuration 0.25 ,因为static const定义的常量在系统中只会开辟一份内存,而#define,所定义的每一个常量都会开辟一份临时的内存空间。用static修饰的全局变量,只能是全局变量,该变量才会限制在本类中使用,外部不可以访问,若不加static,则用ertern,就可以在其他类中访问该变量。const在前在后都是一样的,定义字符串变量时,static NSString * const name = @"name";则指针name不可改变。const修饰变量或是常量时,就看const右侧是什么,则const右侧的指针或是变量不可改变。

    3:创建子控制器addChildViewController:苹果官方建议当控制器互为父子关系时,控制器上的view也应该为父子关系。1:将创建子控制器的代码封装起来,创建子控制器对象,将子控制对象和title作为参数传入。2:titleView的封装:1:因为titleView为图片和文字构成,所以用button去封装titleView,创建控件继承UIButton,设置自身属性,btn的ennable,或是userenable为NO,titleLable.font,titleColor,setImage,btn.adjustImageWhenHeighlight(当setImage时),titleEdgeInsets,imageEdgeInset,contentEdgeInset,继承UIcontrol的contentHorizanAliment(整个btn文本的对其方式),btn的高度,self.height =self.currentImage.size.height;self.currentImage获得当前的image,btn.currentBackgroundImage,获得背景图片 2:懒加载子控件,添加到父视图上,无 3:layoutSubView布局子控件 4:向外界提供model接口,重写model的set方法,外界提供title接口,重写title的set方法,btn要设置自身的宽度自适应,用boundingRectWithSize,如下:

     NSDictionary *attrs = @{NSFontAttributeName : self.titleLabel.font};    CGFloat titleW = [title boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width; self.width = titleW + self.titleEdgeInsets.left + self.currentImage.size.width;

     其中,只要赋值,就调用set方法,想获得此变量,就调用get方法,没必要再UIFont去设置,boundingRectWithSize,单行绘制文本时,两个参数都穿MAXFLOAT,基于基线绘制NSStringDrawingUsesLineFragmentOrigin,若是多行,则先设置lable.numberoflines = 0;再限制宽度或是高度,参数采用基线绘制,NSStringDrawingUsesLineFragmentOrigin,和行间距 NSStringDrawingUsesFontLeading。总的宽度就为,image的宽度+self.titleEdgeInsets.left+self.currentImage.size.width。其中titleEdgeInsets的设置,指的是距离左侧图片的距离,为正数,则指的是右侧距离

    4:自定义导航栏上的左右item,自定义btn,btn setBackgroundImage,图片为按钮的背景图片,btn的大小为图片的大小, button.size = button.currentBackgroundImage.size;

    5:封装导航控制器:1:继承系统导航控制器,因为设置全局导航栏的属性,只需设置一次就好,所以写在+ (void)initialize里,该方法只在该方法所在类第一个方法被调用之前被调用一次,只在整个项目中只会调用一次。先获得全局导航栏,item对象,利用settitleTextAttribute forState属性,可以设置不同状态下的属性 2:左右item距离屏幕左右边框的距离很大,想要调整,1:可遍历系统控件的子控件,找出左右按钮,再设置左右按钮的frame 2:自定义bar用kvc代替系统的bar:新建类继承系统的bar,在layoutSubView方法中,则子类继承了系统bar的属性,遍历子控件数组,self.subViews,在遍历时,要做条件过滤,不符合条件的直接return,或是continue。找到子控件的时候停止遍历,做性能优化。找到左右按钮后,判断左右按钮的btn的center与中点比较,看是哪个左右item。3:设置完frame之后,再在封装的nav控制器中创建对象,setValue forKeyPath ,kvc来代替系统的控件,第二个参数,就是nav控制器下属性定义的navBar,调用此方法,得是某个控制器下的某个属性

      // 替换为自定义的导航栏    [self setValue:[[HMNavigationBar alloc] init] forKeyPath:@"navigationBar"];4:其中:layoutSubView方法只适用于在UIView中,在控制器中调整子控件可以重写系统方法:- (void)viewDidLayoutSubviews,但是不要忘记调用super

    6:[self addChildViewController:nav];1:添加子控制器,能则父控制器就对子控制器有一个强引用,只要父控制器在,则子控制器就在,而且控制器互为父子关系,则他们的view也应该互为父子关系。2:子控制器数组:self.childViewControllers,得到子控制器数组,只读,子控制器从父控制器移除,subNav removeFromParentViewController ,获得父控制器:subNav.parentViewController

     7:封装左侧菜单:1:有背景的话可以继承UIImageView,但要开启用户交互权限,也可以继承UIView,设置背景图片时,添加UIImageView,或是view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:]];,平铺图片,或有间隔线,或是调用drawInRect,画上一张图片 2:先设置自身的属性,clearcolor 3:懒加载控件,设置控件属性,添加到父视图上,创建相同的控件,例如button,可以采用for循环创建,也可以一个一个创建,传title,image,枚举tag值或是其他参数,封装一个button,创建对象,setImage,btn.adjust,setBackgroudImage,可以设枚举tag值,也可以通过设置self.subViews.count为tag值,也可以设置titleEdgeInset,ImageEdgeInset,contentEdgeInset,继承UIcontrol的也可以用contentHorizanAliment(文本的对齐方式),在layoutSubView里设置控件的frame,1:属性,成员变量 ,通过tag值取出,若是有多个子控件,可以设置tag值,遍历子控件数组,通过tag值将子控件取出2:放在大数组里,从数组里取出,若是又有button又有其他控件,则两两分别放在数组里,分别从数组里取出,设置frame 3:遍历subView,从subViews的数组里取出。4:设置按钮的回调:1:可通过协议代理,通知 ,block ,协议代理,block适用于层级较浅的回调,通知,多播委托适用于层级较深的结构 2 :若是监听系统的控件:继承UIControl的可以addTarget,可以系统的代理,系统通知,子类若没有查看父类,也可以重写系统的方法,不要忘记调用super方法,来实现监听 3:按钮的协议代理,传枚举tag值是为了在控制器实现监听点击,传fromIndex,传toIndex,是为了从数组取出旧的移除,并添加新的 4:按钮的回调方法,两个按钮状态的判断,btn.selected = !btn.isSelected,三个按钮切换状态则用按钮三部曲,若是传index则把代理方法放前面 5:设置按钮默认选中:1:直接设哪个按钮被选中,再设seletedBtn 2:返回按钮,调用按钮的点击方法,要考虑需不需要重写代理的setDelegate方法在该方法中设置按钮的默认选中。

    8:transform属性:1:当点击左上角按钮的时候,先进行缩放,在进行平移,在缩放的基础上进行平移,求缩放比例:缩放后的高度 = 屏幕高度 - 上下间距 ,用缩放的高度与原高度的比值就是缩放比例,在UIView的动画中先进行缩放,再在缩放的基础上进行平移,平移的距离,1-缩放比例,就为剩下的长度比例,0.5倍,就是缩放后的view的实际距屏宽度。2:在动画结束的时候设置一个遮盖效果,遮盖效果:1:可以为一个view,添加手势,2:也可以另遮盖为一个button,监听button的点击事件,button在此处不能为成员变量,button的点击事件中,动画先将transform清空,完成时,将button从父视图移除。3:监听点击事件:1:继承UIControl的可以addTarget 2:添加手势监听器 3:实现touch beagn,touch end,touch cancle 方法,配合UITouch,使用,UITouch *touch = [UITouch anyObject]; touch.view可以获得触摸点点击的view,CGPoint point = [touch locationInView:touch.view];此方法可获得触摸点,其中触摸点的是基于touch.view来计算的,如果此参数填父视图view,则是基于整个父视图来计算的。然后一般是遍历数组,做条件过滤,利用CGRectContainPoint方法,根据触摸点求出矩形框的rect,找到结果后停止遍历 4:transform是二维旋转,view的图层layer是三维动画,view.layer.transform = CAAFfitransform(,,,,);最后三个参数为xyz轴,若是010,则是绕着y轴上1点与原点连线的的向量旋转,第一个参数为旋转的角度。5:动画效果:1:二维动画:UIView + transform 2:三维动画:UIView +view.layer.transform  = CAAFi ,注意三个参数  3:转场动画:也就是翻转动画,[UIView transition...];翻转动画有各种参数值 4:三维动画也可以用CATranstion,CATranstion *ad = [CATranstion animation];ad.duration 动画时间,ad.type,动画的方式,字符串,[self.iconaImageView.layer addAnimation: ad forkey:nil];

    9:监听左侧菜单按钮的回调事件:效果是,点击左侧按钮,切换视图,动画清空transform。将旧的控制器取出,view从父视图上移除,再将新控制器取出,将新控制器的view添加到父视图上,此时可以不必设置新view的frame,默认为父视图的bounds。将旧控制器的transform赋值给新的控制器的transform,更新当前的控制器,动画回去,此时就是清空新控制器的transform,相当于点击了旧控制器的遮盖,将按钮从父视图上取出,调用按钮点击方法。

    10:在使用xib绘制界面的时候,有时明明尺寸设置正确,但是就不能正常显示,1:此时可以禁用autoLayout 2:setNeedsLayOut ,layOutIfNeed配合使用,异步调用layoutSubView,重新计算尺寸。3:当xib加载完毕后会调用awakeFromNib,在此方法中可以设置xib中控件的一些属性,当xib中已经设置了控件的尺寸,在外部依然可以修改xib中控件的尺寸

    11:右侧菜单的封装设计:1:对于控制器和view来说,要采取分层封装的思想,就是将view和或是控制器切分成一个个模块,将零散的控件封装在一个整体内,然后再考虑整个项目中其他地方有没有用到,若用到则考虑继承关心A继承B,或是B继承A,或是将AB公共部分抽成父类C,AB分别继承父类C,不同的部分在AB中单独实现 2:右侧的菜单封装,可以采取三种封装方法:1:看成是一个tableView,table的headerView,tableView,table的footerView 但是没有cell的复用,且按钮的回调监听,太复杂 2:还可以考虑封装一个大view,再将上中下封装为三个小view添加到大view上,但是同样涉及的问题就是按钮的监听回调太麻烦 3:考虑用一个控制器,在控制器内实现按钮的监听,在控制器内再将整体封装为上中下三个view。2:对于顶部view的封装以及动画,顶部view中的头像的翻转就用转场动画,每执行一次转场动画,转360度,并更换图片,动画完成时,执行GCD延迟函数,在执行一个转场动画转回来,再更改frame 3:中间View的封装,按钮会点亮,调用的是button的btn.showTouchWhenHeighlight。此方法若是button有图片,则只在button的图片处点亮,再将每一行封装为一个View,点图片和箭头都会亮,则其肯定为一个整体,所以可以考虑button为整个背景,将图片和箭头添加到button上,因为当点击图片和箭头时,默认没有开启用户的交互权限,通过的事件的传递可以找到触摸点所在的view,但是该view不能处理事件,则事件会又子控件传递给父控件去处理,也就是交给button去处理,buttonn能处理所以点击图片箭头都会被点亮 4:设置每个封装view的y值,view.y = self.subViews.count *height;总高度,self.subViews.count *height

  • 相关阅读:
    面对缓存,有哪些问题需要思考?
    .NET 文件格式相关开源项目
    (转)谈谈用ASP.NET开发的大型网站有哪些架构方式(成本)
    (转)基于微软平台IIS/ASP.NET开发的大型网站有哪些?
    sql查询优化策略
    初入linux系统
    Npoi操作Excel
    List GroupBy真实用法,Reflection(反射)用法,Enum用法,正则,搜索下拉布局
    3.2.2.4 文本匹配锚点
    3.2.2.3 单个表达式匹配多字符
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5724434.html
Copyright © 2020-2023  润新知