****转载请注明出处
一、可动态调整大小的导航条
要想调整导航条(NavigationBar)的大小或位置,只需改变他的frame即可。
但怎样让导航条上的那些控件(按钮、标题、searchbar之类的)也能成一定比例的缩小或者消失呢?当然是对这些视图做仿射变换(CGAfineTransfrom)。
我们知道UIBarButtonItem继承自UIBarItem,UIBarItem继承自NSObject,不能对它做一些UIView能做的仿射变换。
但是NavigationController.navigationItem有一个属性:titleView可作为我们自定义控件(所有继承自UIView的控件)的容器。
实现动态导航条的思路:当检测要触发调整导航条的事件时(scrollView向下向上滚动或Tap导航条等等),1、将导航条向上移动20个Point(因为状态栏的宽度是20),当然移动多少个Point你随意。2、对titleView上的控件做仿射变换
我们先来给导航条布局: 以下代码可放在ViewDidLoad里
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 44)];
contentView.tag = 1;
self.navigationItem.titleView = contentView;
UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
leftButton.center = CGPointMake(13, 22);//设置frame不行调整,但center确行
leftButton.tag = 4;
[leftButton setTitle:@"left" forState:UIControlStateNormal];
[leftButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[leftButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
[contentView addSubview:leftButton];
UIButton *rightButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
rightButton.tag = 2;
[rightButton setTitle:@"right" forState:UIControlStateNormal];
[rightButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[rightButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
rightButton.center = CGPointMake(280, 22);
[contentView addSubview:rightButton];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.tag = 3;
titleLabel.text = @"title";
[titleLabel sizeToFit];
titleLabel.center = CGPointMake(contentView.frame.size.width / 2, 22);
[contentView addSubview:titleLabel];
创建控件的代码都很简单,比较蛋疼的就是计算它们的位置。还有不要忘了给他们上个tag以便下面能得到这些视图的引用。
如果给titleView上个背景色,我们可以发现titleView的Frame,感觉有点奇怪,不知道苹果为什么这样做。但这并不意味着你的Subview只能在这个Frame以内,把Subview.frame.origin.x设置为负数就可以在它之外了嘛,效果如下图(我把导航条的背景色设置成了粉红)
下面实现调整导航条大小
static BOOL isShirink = 0;
- (void)shrinkNavBar{
UIView *contentView = [self.navigationItem.titleView viewWithTag:1];
UILabel *titleLabel = (UILabel *)[contentView viewWithTag:3];
UIButton *leftButton = (UIButton *)[contentView viewWithTag:4];
UIButton *rightButton = (UIButton *)[contentView viewWithTag:2];
CGPoint labelCenter = titleLabel.center;
CGPoint leftButtonCenter = leftButton.center;
CGPoint rightButtonCenter = rightButton.center;
CGRect navBarFrame = self.navigationController.navigationBar.frame;
CGAffineTransform labelTransform = CGAffineTransformMakeScale(0.9, 0.9);
CGAffineTransform buttonTransform = CGAffineTransformMakeScale(0.01, 0.01);
if (!isShirink) {
navBarFrame.origin.y -= 20;
labelCenter.y += 5;
leftButtonCenter.x -= 5;
rightButtonCenter.x += 5;
[UIView animateWithDuration:0.5 animations:^{
titleLabel.transform = labelTransform;
leftButton.transform = buttonTransform;
rightButton.transform = buttonTransform;
self.navigationController.navigationBar.frame = navBarFrame;
titleLabel.center = labelCenter;
leftButton.center = leftButtonCenter;
rightButton.center = rightButtonCenter;
}];
isShirink = ! isShirink;
}else{
navBarFrame.origin.y += 20;
labelCenter.y -= 5;
leftButtonCenter.x += 5;
rightButtonCenter.x -= 5;
[UIView animateWithDuration:0.5 animations:^{
titleLabel.transform = CGAffineTransformIdentity;
leftButton.transform = CGAffineTransformIdentity;
rightButton.transform = CGAffineTransformIdentity;
self.navigationController.navigationBar.frame = navBarFrame;
titleLabel.center = labelCenter;
leftButton.center = leftButtonCenter;
rightButton.center = rightButtonCenter;
}];
isShirink = !isShirink;
}
}
说明:用一个static的bool变量检查导航条的状态。 如果导航条没有被压缩,
就用UIView的 +animateWithDuration:animations:^(void)animation{}做压缩的动画效果。这里有个问题:导航条向上移动了,那么它的所有子视图也向上移动,这样使得titleLabel太靠近状态栏,我们想把它的位置往下调一些怎么做?
CGAfineTransformMakeScale是以view.layer.anchorPoint(锚点)为基准进行变换,这个点默认是(0.5,0.5)。view还有一个属性center,如果在scale变换的同时改变center的值,就可以调整它的位置,labelCenter.y += 5 向下调整5个单位。 注意以下,CGAfineTransform和center相互关联,并且都会改变frame的值,这之间的关系可以自己思考以下。
如果导航条已经被压缩,将以上操作倒过来就OK了。
CGAffineTransformIdentity可以把view恢复成没做仿射变换,这也是view.transform的默认值。
为了简单起见。我就以Tap导航条手势触发调整大小
讲以下代码添加进第一段代码的末尾:
UITapGestureRecognizer *tapGestureReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(shrinkNavBar)];
tapGestureReconizer.numberOfTapsRequired = 1;
tapGestureReconizer.numberOfTouchesRequired = 1;
[contentView addGestureRecognizer:tapGestureReconizer];
Perfect!
二、全透明导航条
只需要3行代码:
[self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationBar setShadowImage:[UIImage new]];
[self.navigationBar setTranslucent:YES];
效果如图: