补充上篇漏洞
在上一篇UI的学习笔记中,对定时器和视图移动做一定补充。
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn1.frame = CGRectMake(100, 100, 80, 80);
[btn1 setTitle:@"启动计时" forState:UIControlStateNormal];
[btn1 addTarget:self action:@selector(pressStart) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn1];
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn2.frame = CGRectMake(100, 200, 80, 40);
[btn2 setTitle:@"停止计时" forState:UIControlStateNormal];
[btn2 addTarget:self action:@selector(pressStop) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn2];
UIView *view = [[UIView alloc] init];
view.frame = CGRectMake(20, 100, 50, 50);
view.backgroundColor = [UIColor cyanColor];
[self.view addSubview:view];
//设置view标签值通过父视图获得对应视图对象
view.tag = 101;
}
-(void)pressStart {
//NSTimer类方法创建并启动定时器
//参数1:每隔多长时间调用定时函数(以秒为单位)
//参数2:实现定时函数的对象
//参数3:定时器函数对象
//参数4:一个给定参数(无参传nil)的定时器函数
//参数5:定时器是否重复操作(NO表示只完成一次)
_timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(updateTimer:) userInfo:@"⌛️!" repeats:YES];
}
-(void)updateTimer:(NSString*)timer {
NSLog(@"%@", _timer.userInfo);
//通过标签指针改变view的frame属性
UIView *view = [self.view viewWithTag:101];
//从self.view坐标系原点开始移动
view.frame = CGRectMake(view.frame.origin.x + 1, view.frame.origin.y + 1, 80, 80);
}
-(void)pressStop {
if (_timer != nil) {
//invalidate方法:用于使当前状态或缓存失效并触发更新
[_timer invalidate];
NSLog(@"停止计时!");
}
}
@end
以上是我们原来的代码,但是我们在运行的时候会发现,如果我们按下两次按钮后,我们的视图无法停止,因此我们做以下修改:
我们将修改pressStart函数,对其进行判空处理:
-(void)pressStart {
if (_timer == nil) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(updateTimer:) userInfo:@"⌛️!" repeats:YES];
} else {
[_timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:0.03]];
}
}
这样就可以解决我们以上所说到的问题
布局子视图
布局子视图目的:使子视图跟随父视图的移动而移动,使其相对位置不变。
手动布局子视图
以下是演示代码:
新建一个SuperView类实现子视图
SuperView.h
#import <UIKit/UIKit.h>
@interface SuperView : UIView {
UIView *_view01;
UIView *_view02;
UIView *_view03;
UIView *_view04;
}
-(void)createSubViews;
@end
SuperView.m
#import "SuperView.h"
@implementation SuperView
-(void)createSubViews {
//左上角视图
_view01 = [[UIView alloc] init];
_view01.frame = CGRectMake(0, 0, 40, 40);
//右上角视图
_view02 = [[UIView alloc] init];
_view02.frame = CGRectMake(self.bounds.size.width - 40, 0, 40, 40);
//右下角视图
_view03 = [[UIView alloc] init];
_view03.frame = CGRectMake(self.bounds.size.width - 40, self.bounds.size.height - 40, 40, 40);
//左下角视图
_view04 = [[UIView alloc] init];
_view04.frame = CGRectMake(0, self.bounds.size.height - 40, 40, 40);
_view01.backgroundColor = [UIColor cyanColor];
_view02.backgroundColor = [UIColor cyanColor];
_view03.backgroundColor = [UIColor cyanColor];
_view04.backgroundColor = [UIColor cyanColor];
[self addSubview:_view01];
[self addSubview:_view02];
[self addSubview:_view03];
[self addSubview:_view04];
}
//当需要重新布局时调用此函数
//通过此函数重新设定子视图的位置
//手动调整子视图的位置
-(void)layoutSubviews {
_view01.frame = CGRectMake(0, 0, 40, 40);
_view02.frame = CGRectMake(self.bounds.size.width - 40, 0, 40, 40);
_view03.frame = CGRectMake(self.bounds.size.width - 40, self.bounds.size.height - 40, 40, 40);
_view04.frame = CGRectMake(0, self.bounds.size.height - 40, 40, 40);
}
@end
ViewController.m
#import "ViewController.h"
#import "SuperView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建父视图
SuperView *sView = [[SuperView alloc] init];
sView.frame = CGRectMake(20, 20, 180, 200);
[sView createSubViews];
sView.backgroundColor = [UIColor blueColor];
[self.view addSubview:sView];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(240, 480, 80, 40);
[btn setTitle:@"放大" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(pressLarge) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
UIButton *btn02 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn02.frame = CGRectMake(240, 520, 80, 40);
[btn02 setTitle:@"缩小" forState:UIControlStateNormal];
[btn02 addTarget:self action:@selector(pressSmall) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn02];
sView.tag = 101;
}
//放大父视图动画
-(void)pressLarge {
SuperView *sView = (SuperView*)[self.view viewWithTag:101];
[UIView animateWithDuration:1 animations:^{
sView.frame = CGRectMake(20, 20, 300, 400);
}];
}
//缩小父视图
-(void)pressSmall {
SuperView *sView = (SuperView*)[self.view viewWithTag:101];
[UIView animateWithDuration:1 animations:^{
sView.frame = CGRectMake(20, 20, 300, 200);
}];
}
@end
运行效果:
自动布局子视图
自动布局子视图直接通过OC提供的属性实现。
代码演示:
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController {
//创建父视图对象
UIView *_superView;
//左上角label
UILabel *_label01;
//右上角
UILabel *_label02;
//右下角
UILabel *_label03;
//左下角
UILabel *_label04;
//中间的
UIView *_centerView;
}
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_superView = [[UIView alloc] init];
_superView.frame = CGRectMake(20, 20, 180, 280);
_superView.backgroundColor = [UIColor blueColor];
_label01 = [[UILabel alloc] init];
//相对于父视图
_label01.frame = CGRectMake(0, 0, 40, 40);
_label01.text = @"1";
_label01.backgroundColor = [UIColor cyanColor];
_label02 = [[UILabel alloc] init];
_label02.frame = CGRectMake(180 - 40, 0, 40, 40);
_label02.text = @"2";
_label02.backgroundColor = [UIColor cyanColor];
_label03 = [[UILabel alloc] init];
_label03.frame = CGRectMake(0, 280 - 40, 40, 40);
_label03.text = @"3";
_label03.backgroundColor = [UIColor cyanColor];
_label04 = [[UILabel alloc] init];
_label04.frame = CGRectMake(180 - 40, 280 - 40, 40, 40);
_label04.text = @"4";
_label04.backgroundColor = [UIColor cyanColor];
[_superView addSubview:_label01];
[_superView addSubview:_label02];
[_superView addSubview:_label03];
[_superView addSubview:_label04];
_centerView = [[UIView alloc] init];
_centerView.frame = CGRectMake(0, 0, _superView.bounds.size.width - 40, 40);
//中心点
_centerView.center = CGPointMake(180 / 2, 280 / 2);
_centerView.backgroundColor = [UIColor greenColor];
[self.view addSubview:_superView];
[_superView addSubview:_centerView];
//设置自动布局属性
//通过此变量来调整视图在父视图的位置
//_centerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;//可自动调整高
_label02.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;//视图距离父视图左侧可以变化
_label03.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
_label04.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin;
_centerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//使用局部变量区分视图大小状态
static BOOL isLarge = NO;
//动画效果
[UIView animateWithDuration:1 animations:^{
if (isLarge == NO) {
self->_superView.frame = CGRectMake(10, 10, 350, 500);
isLarge = YES;
} else {
self->_superView.frame = CGRectMake(20, 20, 180, 280);
isLarge = NO;
}
}];
}
@end
代码中值得注意的是,在touchesBegan函数中,每次判断完是变大还是变小后,要将这个变量重置,这样就可以实现状态的交替变化和实现。
导航控制器
- 导航控制器是层级管理关系,有导航栏、按钮等功能。
- 导航控制器管理视图控制器
导航控制器基础
SceneDelegate.m
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
self.window.frame = [UIScreen mainScreen].bounds;
//创建一个根视图控制器
VCRoot *root = [[VCRoot alloc] init];
//创建导航控制器用来管理多个视图控制器的切换
//层级的方式管理多个视图控制器
//创建控制器时,一定要有一个根视图控制器
//参数:作为导航控制器的根视图控制器
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:root];
//将window的根视图设置为导航控制器
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
}
根视图部分代码
VCRoot.m
#import "VCRoot.h"
@interface VCRoot ()
@end
@implementation VCRoot
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
//设置导航栏文字
self.title = @"根视图";
//设置导航元素项的标题
//当navigationItem.title未设置时,标题显示为title
//当二者都设置时,标题显示为navigationItem.title
//当二者都未设置时,不显示
self.navigationItem.title = @"向前看";
//设置导航栏左侧按钮
//参数1:按钮上的文字
//参数2:按钮风格
//参数3:事件持有者
//参数4:按钮的事件函数
UIBarButtonItem *lefrBtn = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStyleDone target:self action:@selector(pressLeft)];
//将我们创建好的左侧按钮赋值给左侧属性
self.navigationItem.leftBarButtonItem = lefrBtn;
//右侧按钮
UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(pressRight)];
self.navigationItem.rightBarButtonItem = rightBtn;
//标签对象
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 50, 40)];
label.text = @"text";
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor blueColor];
UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithCustomView:label];
//创建一个按钮数组
NSArray *arrayBtn = [NSArray arrayWithObjects:rightBtn, item3, nil];
//给右侧按钮数组赋值
self.navigationItem.rightBarButtonItems = arrayBtn;
}
-(void)pressLeft {
NSLog(@"向左!");
}
-(void)pressRight {
NSLog(@"向右!");
}
运行效果:
导航控制器切换
先认识几个方法函数:
-
navigationBar:导航栏对象
-
navigationItem:导航元素项对象
-
translucent:导航栏透明度
导航控制器的核心方法:
-
pushViewController:推入视图控制器(将新控制器压入栈顶)
-
popViewController:弹出视图控制器(将当前控制器弹出栈)
导航控制器的结构:(采用栈结构管理多个视图控制器)
[UINavigationController]
└── [Root View Controller] (第一个界面)
└── [Pushed View Controller 1] (第二个界面)
└── [Pushed View Controller 2] (第三个界面)
代码演示:
SceneDelegate.m
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
self.window.frame = [UIScreen mainScreen].bounds;
//创建根视图控制器并直接赋值给创建的导航控制器的根视图对象
//创建好导航控制器即创建好根视图控制器
//将导航控制器作为window的根视图控制器
//VCRoot作为导航控制器的根视图控制器
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[VCRoot alloc] init]];
[self.window makeKeyWindow];
}
VCRoot.m
#import "VCRoot.h"
#import "VCSecond.h"
#import "VCThird.h"
@interface VCRoot ()
@end
@implementation VCRoot
- (void)viewDidLoad {
[super viewDidLoad];
//设置导航栏透明度
//默认透明度为YES(可透明的)
self.navigationController.navigationBar.translucent = NO;//使导航栏不透明
//设置导航栏风格
self.navigationController.navigationBar.barStyle = UIBarStyleDefault;
self.view.backgroundColor = [UIColor blueColor];
self.title = @"根视图";
UIBarButtonItem *next = [[UIBarButtonItem alloc] initWithTitle:@"下一级" style:UIBarButtonItemStylePlain target:self action:@selector(pressNext)];
self.navigationItem.rightBarButtonItem = next;
}
-(void)pressNext {
//创建新的视图控制器
VCSecond *vcSecond = [[VCSecond alloc] init];
//使用当前视图控制器的导航控制器对象进行跳转
[self.navigationController pushViewController:vcSecond animated:YES];
//当切换到下一页时,导航控制器自动设置上一页面的title为该页的返回键
}
VCSecond.m
#import "VCSecond.h"
#import "VCThird.h"
@interface VCSecond ()
@end
@implementation VCSecond
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.title = @"视图二";
UIBarButtonItem *btnNext = [[UIBarButtonItem alloc] initWithTitle:@"第三极" style:UIBarButtonItemStylePlain target:self action:@selector(pressNext)];
self.navigationItem.rightBarButtonItem = btnNext;
}
-(void)pressNext {
VCThird *vcThird = [[VCThird alloc] init];
//推入第三个视图控制器
[self.navigationController pushViewController:vcThird animated:YES];
}
VCThird.m
#import "VCThird.h"
@interface VCThird ()
@end
@implementation VCThird
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor cyanColor];
self.title = @"第三级";
//当自定义左侧按钮时,返回按钮会被左侧按钮替代
UIBarButtonItem *btnLeft = [[UIBarButtonItem alloc] initWithTitle:@"退出" style:UIBarButtonItemStylePlain target:self action:@selector(pressBack)];
self.navigationItem.leftBarButtonItem = btnLeft;
UIBarButtonItem *btnRight = [[UIBarButtonItem alloc] initWithTitle:@"返回根视图" style:UIBarButtonItemStylePlain target:self action:@selector(pressRight)];
self.navigationItem.rightBarButtonItem = btnRight;
}
-(void)pressRight {
//直接返回到根视图
[self.navigationController popToRootViewControllerAnimated:YES];
}
-(void)pressBack {
//将当前的视图控制器弹出,返回上一级界面
[self.navigationController popViewControllerAnimated:YES];
NSLog(@"返回上一级");
}
导航栏和工具栏
首先认识几个方法:
-
barStyle:导航栏风格
-
barTintColor:导航栏颜色
-
tintColor:导航栏风格颜色
-
toolBarItems:工具栏元素数组
-
UIBarItemFlexibleSpace:自动调整距离按钮风格
值得注意的是,在新版本中,设置导航控制器的外观颜色风格等需要使用UINavigationBarAppearance类。
SceneDelegate.m
#import "SceneDelegate.h"
#import "VCRoot.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
self.window.frame = [UIScreen mainScreen].bounds;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[VCRoot alloc] init]];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
}
- 导航栏的代码
#import "VCRoot.h"
#import "VCRoot02.h"
@interface VCRoot ()
@end
@implementation VCRoot
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor yellowColor];
self.title = @"根视图";
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle:@"右侧按钮" style:UIBarButtonItemStylePlain target:self action:nil];
self.navigationItem.rightBarButtonItem = btn;
UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
//设置对象背景颜色
appearance.backgroundColor = [UIColor redColor];
//创建对象的阴影图像
appearance.shadowImage = [[UIImage alloc] init];
//设置对象的阴影颜色
appearance.shadowColor = nil;
//设置导航栏按钮颜色
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
//设置普通样式导航栏
self.navigationController.navigationBar.standardAppearance = appearance;
//设置滚动样式导航栏
self.navigationController.navigationBar.scrollEdgeAppearance = appearance;
//隐藏导航栏
//方法1:hidden继承于UIView
self.navigationController.navigationBar.hidden = NO;
//方法2:navigationBarHidden是一个属性
self.navigationController.navigationBarHidden = NO;
}
- 工具栏
//显示工具栏对象
//是否隐藏工具栏(默认为YES)
self.navigationController.toolbarHidden = NO;
//设置工具栏是否透明(默认为YES)
self.navigationController.toolbar.translucent = NO;
UIBarButtonItem *btn1 = [[UIBarButtonItem alloc] initWithTitle:@"左侧" style:UIBarButtonItemStylePlain target:nil action:nil];
UIBarButtonItem *btn2 = [[UIBarButtonItem alloc] initWithTitle:@"右侧" style:UIBarButtonItemStylePlain target:self action:@selector(pressBack)];
//设置一个自定义类型的button用来创建图片
UIButton *btnC = [UIButton buttonWithType:UIButtonTypeCustom];
[btnC setImage:[UIImage imageNamed:@"/Users/mac/Desktop/BtnC.jpg"] forState:UIControlStateNormal];
btnC.frame = CGRectMake(0, 0, 60, 60);
//将自定义按钮(UIButton或UIView)包装成UIBarButtonItem在导航栏显示
UIBarButtonItem *btn3 = [[UIBarButtonItem alloc] initWithCustomView:btnC];
//按钮排列方式
//设置一个宽度固定的占位按钮,放到数组中分隔开各按钮
UIBarButtonItem *btnF1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
btnF1.width = 110;
//设置自动计算宽度的按钮
UIBarButtonItem *btnF2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
//组合按钮和间距并设置到 UIToolbar
NSArray *arrayBtn = [NSArray arrayWithObjects:btn1, btnF1, btn3, btnF2, btn2, nil];
self.toolbarItems = arrayBtn;
-(void)pressBack {
VCRoot02 *vc = [[VCRoot02 alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
其中,着重注意两个方法名:
- UIBarButtonSystemItemFixedSpace:在工具栏中插入一个 固定宽度的空白区域,用于强制分隔按钮。
- UIBarButtonSystemItemFlexibleSpace:插入一个 自动填充剩余空间 的占位符,使相邻的按钮可以靠左、靠右或居中,用于动态调整布局。
分栏控制器
分栏控制器是主要用于同时展示多个视图控制器并使其交互的控件。
分栏控制器基础
通过创建三个视图控制器并赋值给分栏控制器。
这里值得注意的是,如果在视图控制器文件中和SceneDelegate.m文件中同时设置了分栏控制器按钮风格,视图控制器文件中的风格会覆盖SceneDelegate.m中的。
VCRoot01.m
#import "VCRoot01.h"
@interface VCRoot01 ()
@end
@implementation VCRoot01
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个分栏按钮对象
//参数1:标题内容
//参数2:显示图片
//参数3:对象标记值
UITabBarItem *tabBarItem = [[UITabBarItem alloc] initWithTitle:@"👈" image:nil tag:101];
self.tabBarItem = tabBarItem;
}
VCRoot02.m
#import "VCRoot02.h"
@interface VCRoot02 ()
@end
@implementation VCRoot02
- (void)viewDidLoad {
[super viewDidLoad];
//根据系统风格设置分栏控制器按钮
//参数1:分栏控制器风格
//参数2:对象的标签值
UITabBarItem *tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemContacts tag:103];//联系人样式风格
//为分栏按钮设置提示的标记值信息(标签栏按钮右上角的小徽标)
tabBarItem.badgeValue = @"22";
self.tabBarItem = tabBarItem;
}
VCRoot03.m
#import "VCRoot03.h"
@interface VCRoot03 ()
@end
@implementation VCRoot03
- (void)viewDidLoad {
[super viewDidLoad];
UITabBarItem *tabBarItem = [[UITabBarItem alloc] initWithTitle:@"👉" image:nil tag:101];
self.tabBarItem = tabBarItem;
}
SceneDelegate.m
#import "SceneDelegate.h"
#import "VCRoot01.h"
#import "VCRoot02.h"
#import "VCRoot03.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
//创建三个视图控制器
VCRoot01 *vc1 = [[VCRoot01 alloc] init];
vc1.title = @"视图一";
VCRoot02 *vc2 = [[VCRoot02 alloc] init];
vc2.title = @"视图二";
VCRoot03 *vc3 = [[VCRoot03 alloc] init];
vc3.title = @"视图三";
vc1.view.backgroundColor = [UIColor cyanColor];
vc2.view.backgroundColor = [UIColor grayColor];
vc3.view.backgroundColor = [UIColor greenColor];
//创建分栏控制器对象
UITabBarController *tbc = [[UITabBarController alloc] init];
//创建一个控制器数组对象
//注意⚠️:分栏控制器按钮显示顺序取决于添加进数组的顺序
NSArray *arrVC = [NSArray arrayWithObjects:vc1, vc2, vc3, nil];
//将按钮标签赋值给分栏控制器
tbc.viewControllers = arrVC;
//将分栏控制器作为根视图控制器
self.window.rootViewController = tbc;
//通过设置分视图控制器索引来确定打开程序显示的是哪一个视图控制器
//此时分栏控制器选中的分栏控制器对象即为索引为2的视图控制器(即vc3)
tbc.selectedIndex = 2;
if (tbc.selectedViewController == vc3) {
NSLog(@"go go go 出发喽");
}
//设置分栏控制器工具栏透明度
tbc.tabBar.translucent = NO;
tbc.tabBar.backgroundColor = [UIColor whiteColor];//分栏控制器工具栏颜色
tbc.tabBar.tintColor = [UIColor blueColor];//分栏控制器按钮选择时颜色
}
分栏控制器高级
在分栏控制器中添加按钮时,下面页面最多显示五个按钮,当多于五个按钮时,多于五个的按钮会被自动折叠放入"more"中。可以通过拖动替换被隐藏和显示的视图按钮。
其主要内容在于实现UITabBarControllerDelegate协议。
- willBeginCustomizingViewControllers:编辑前
- willEndCustomizingViewControllers:即将结束前
- didEndCustomizingViewControllers:已经结束编辑
#import "SceneDelegate.h"
#import "ViewController01.h"
#import "ViewController02.h"
#import "ViewController03.h"
#import "ViewController04.h"
#import "ViewController05.h"
#import "ViewController06.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
ViewController01 *vc1 = [[ViewController01 alloc] init];
ViewController02 *vc2 = [[ViewController02 alloc] init];
ViewController03 *vc3 = [[ViewController03 alloc] init];
ViewController04 *vc4 = [[ViewController04 alloc] init];
ViewController05 *vc5 = [[ViewController05 alloc] init];
ViewController06 *vc6 = [[ViewController06 alloc] init];
vc1.title = @"视图1";
vc2.title = @"视图2";
vc3.title = @"视图3";
vc4.title = @"视图4";
vc5.title = @"视图5";
vc6.title = @"视图6";
vc1.view.backgroundColor = [UIColor redColor];
vc2.view.backgroundColor = [UIColor orangeColor];
vc3.view.backgroundColor = [UIColor yellowColor];
vc4.view.backgroundColor = [UIColor greenColor];
vc5.view.backgroundColor = [UIColor blueColor];
vc6.view.backgroundColor = [UIColor purpleColor];
NSArray *arrVC = [NSArray arrayWithObjects:vc1, vc2, vc3, vc4, vc5, vc6, nil];
UITabBarController *btc = [[UITabBarController alloc] init];
btc.viewControllers = arrVC;
self.window.rootViewController = btc;
//处理协议函数设置代理
btc.delegate = self;
}
-(void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers {
NSLog(@"编辑前");
}
-(void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed {
NSLog(@"即将结束前");
}
-(void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed {
if (changed == YES) {
NSLog(@"顺序发生改变");
}
NSLog(@"已经结束编辑");
}
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSLog(@"选中控制对象");
}
运行效果及控制台打印结果:
照片墙案例
先来认识一下userInteractionEnabled属性:
-
是UIView类的一个布尔属性
-
用于控制视图是否接收和响应用户交互事件
-
- 如果为YES,UIView将会接收有关touch和keyboard的相关操作,按照时间处理方法来响应事件
- 如果为NO,UIView将会忽略掉本应该发生在自身的touch和keyboard事件
代码演示:
ImageViewController.h
#import <UIKit/UIKit.h>
@interface ImageViewController : UIViewController
@property(nonatomic, assign) NSUInteger imageTag;
@property(nonatomic, retain) UIImage *image;
@property(nonatomic, retain) UIImageView *imageView;
@end
ImageViewController.m
#import "ImageViewController.h"
#import "RootViewController.h"
@interface ImageViewController ()
@end
@implementation ImageViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"图片展示";
UIImageView *_imageView = [[UIImageView alloc] init];
_imageView.frame = CGRectMake(0, 100, 394, 650);
_imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"/Users/mac/Desktop/%lu.jpg", _imageTag - 100]];
[self.view addSubview:_imageView];
}
@end
RootViewController.m
#import "RootViewController.h"
#import "ImageViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"图片展示";
self.view.backgroundColor = [UIColor yellowColor];
self.navigationController.navigationBar.translucent = YES;
//创建一个滚动视图
UIScrollView *sv = [[UIScrollView alloc] init];
sv.frame = CGRectMake(5, 10, 394, 852);
sv.contentSize = CGSizeMake(394, 852 * 1.5);//画布
//打开交互事件
//关闭会导致点击等手势操作无效
sv.userInteractionEnabled = YES;
//给根视图添加图片
for (int i = 0; i < 9; i++) {
NSString *strName = [NSString stringWithFormat:@"/Users/mac/Desktop/%d.jpg", i + 1];
UIImage *image = [UIImage imageNamed:strName];
//创建图片视图对象
UIImageView *iView = [[UIImageView alloc] initWithImage:image];
iView.frame = CGRectMake(10 + (i % 3) * 125, (i / 3) * 165, 110, 150);
[sv addSubview:iView];
//打开交互事件
iView.userInteractionEnabled = YES;
//点击执行事件函数
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pressTap:)];
tap.numberOfTapsRequired = 1;//设置触发手势需要点击的次数
tap.numberOfTouchesRequired = 1;//设置触发手势所需要的手指数量
[iView addGestureRecognizer:tap];
iView.tag = 101 + i;
}
[self.view addSubview:sv];
}
-(void)pressTap:(UITapGestureRecognizer*)tap {
UIImageView *imageView = (UIImageView*)tap.view;
//创建显示视图控制器
ImageViewController *imageShow = [[ImageViewController alloc] init];
imageShow.imageTag = imageView.tag;
[self.navigationController pushViewController:imageShow animated:YES];
}
SceneDelegate.m
#import "SceneDelegate.h"
#import "RootViewController.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
self.window.frame = [UIScreen mainScreen].bounds;
//创建导航控制器
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[RootViewController alloc] init]];
//将该导航控制器赋为根视图控制器
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
}