自制一个UIView代替ViewController的导航栏视图跟随scrollview滑动而改变大小并且图片移动交错效果,列表的Header View中的图片产生视差滚动效果

#import <UIKit/UIKit.h>

@interface ELHeaderView : UIView
@property (nonatomic, weak) UIViewController *viewController;
@property (nonatomic, weak) UIScrollView *scrollView;

- (id)initWithFrame:(CGRect)frame backGroudImageURL:(NSString *)backImageURL headerImageURL:(NSString *)headerImageURL title:(NSString *)title subTitle:(NSString *)subTitle;
-(void)updateSubViewsWithScrollOffset:(CGPoint)newOffset;
@end

#import "ELHeaderView.h"
#import "UIImageView+WebCache.h"
#pragma mark - notes:
/*
self:
UIView
self.clipsToBounds = YES;//这个很重要
重写-(void)willMoveToSuperview:(UIView *)newSuperview方法设置一些视图对象(这方法执行时已经被加载对象出来了):
1.隐藏自己被添加到的viewControler成员对象的导航栏:
[[self.viewController navigationController] setNavigationBarHidden:YES];
2.让自己成为自己的scrollView成员变量的观察者(KVO)观察它的contentOffset:
[self.scrollView addObserver:self forKeyPath:@"contentOffset" options:(NSKeyValueObservingOptionNew) context:Nil];
因此需要实现KVO观察者回调拿到新的scrollerView的contentOffset:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
并且在该回调中调用自定义方法计算改变各个view的位置以及渐隐以及字体大小:
-(void)updateSubViewsWithScrollOffset:(CGPoint)newOffset;
3.设置scrollView的顶部的间隔区域://这个很重要
self.scrollView.contentInset = UIEdgeInsetsMake(self.frame.size.height, 0 ,0, 0);

scrollerView:
被添加到的viewController:
背景图:
附在self上
Y为-self.frame.size.height/2
高是self.frame.size.height*1.5

表头图片:
附在self上
z轴在背景图上
调整大小,位置
表头主标题:
附在self上
z轴在背景图上
调整大小,位置
表头副标题:
附在self上
z轴在背景图上
调整大小,位置
*/

@interface ELHeaderView()
@property (nonatomic, strong) UIImageView *backImageView;
@property (nonatomic, strong) UIImageView *headerImageView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic,strong) UILabel *subTitleLabel;
@end

@implementation ELHeaderView

- (id)initWithFrame:(CGRect)frame backGroudImageURL:(NSString *)backImageURL headerImageURL:(NSString *)headerImageURL title:(NSString *)title subTitle:(NSString *)subTitle{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
_backImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, -0.5*frame.size.height, frame.size.width, frame.size.height*1.5)];
[_backImageView setImageWithURL:[NSURL URLWithString:backImageURL]];
_headerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(frame.size.width*0.5-0.125*frame.size.height, 0.25*frame.size.height, 0.25*frame.size.height, 0.25*frame.size.height)];
[_headerImageView setImageWithURL:[NSURL URLWithString:headerImageURL]];
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0.6*frame.size.height, frame.size.width, frame.size.height*0.2)];
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.font = [UIFont boldSystemFontOfSize:20];
_titleLabel.text = title;
_subTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0.85*frame.size.height, frame.size.width, frame.size.height*0.1)];
_subTitleLabel.textAlignment = NSTextAlignmentCenter;
_subTitleLabel.font = [UIFont systemFontOfSize:12];
_subTitleLabel.text = subTitle;
_titleLabel.textColor = [UIColor whiteColor];
_subTitleLabel.textColor = [UIColor whiteColor];

[self addSubview:_backImageView];
[self addSubview:_headerImageView];
[self addSubview:_titleLabel];
[self addSubview:_subTitleLabel];
self.clipsToBounds = YES;
}
return self;
}

-(void)willMoveToSuperview:(UIView *)newSuperview{
[[self.viewController navigationController] setNavigationBarHidden:YES];
[self.scrollView addObserver:self forKeyPath:@"contentOffset" options:(NSKeyValueObservingOptionNew) context:Nil];
self.scrollView.contentInset = UIEdgeInsetsMake(self.frame.size.height, 0 ,0, 0);
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
CGPoint newOffset = [change[@"new"] CGPointValue];
[self updateSubViewsWithScrollOffset:newOffset];
}

-(void)updateSubViewsWithScrollOffset:(CGPoint)newOffset{
float destinaOffset = -60;
float startChangeOffset = -self.scrollView.contentInset.top;
newOffset = CGPointMake(newOffset.x, newOffset.y<startChangeOffset?startChangeOffset:(newOffset.y>destinaOffset?destinaOffset:newOffset.y));
float titleDestinateOffset = self.frame.size.height-40;
float newY = -newOffset.y-self.scrollView.contentInset.top;
float d = destinaOffset-startChangeOffset;
float alpha = 1-(newOffset.y-startChangeOffset)/d;
self.subTitleLabel.alpha = alpha;
self.frame = CGRectMake(0, newY, self.frame.size.width, self.frame.size.height);
self.backImageView.frame = CGRectMake(0, -0.5*self.frame.size.height+(1.5*self.frame.size.height-60)*(1-alpha), self.backImageView.frame.size.width, self.backImageView.frame.size.height);
self.titleLabel.frame = CGRectMake(0, 0.6*self.frame.size.height+(titleDestinateOffset-0.6*self.frame.size.height)*(1-alpha), self.titleLabel.frame.size.width, self.titleLabel.frame.size.height);
self.titleLabel.font = [UIFont boldSystemFontOfSize:16+(alpha)*4];
}
@end

时间: 2024-10-14 03:11:18

自制一个UIView代替ViewController的导航栏视图跟随scrollview滑动而改变大小并且图片移动交错效果,列表的Header View中的图片产生视差滚动效果的相关文章

自定义导航栏返回时的滑动手势处理

现在使用默认模板创建的iOS App都支持手势返回功能,如果导航栏的返回按钮是自定义的那么则会失效,也可以参考这里手动设置无效. if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.navigationController.interactivePopGestureRecognizer.enabled = NO; } 如果是因为自定义导航按钮而导

ios 导航栏透明, 上下滑动 导航栏 颜色渐变

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "PingFang SC"; color: #008400 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Menlo; color: #3d1d81 } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Menlo; color: #008400 } p.p4 {

改良版 导航栏自动跟随

css部分: .container { /*最外层div定宽*/ position: relative; width: 15rem; height: 1rem; margin-top: 20rem; } .con { /*第二层div,设置溢出为滚动条*/ overflow-x: scroll; overflow-y: hidden; height: 1rem; font-size: 0.4rem; width: 15rem; position: absolute; top: 0; } .nav

使用bootstrap3.0搭建一个具有自定义风格的侧边导航栏

由于工作变动,新的项目组,可能会涉及到更多的类似于后台管理系统这一类的项目,而且开发可能更加偏向于传统型的开发,希望今后能够在新的项目中能够用得上vuejs吧! 接手项目的时候,就是一个后台管理系统,而且采用了Bootstrap进行搭建,页面大致模型也基本搭建成功了.然后看到页面上有一个侧边栏,之前是他们从别的地方找出来的一个侧边栏,给人的感觉总是差那么点意思.所以重构了一下.具体的效果,请移步bootstrap-sidebar . 其实主要就解决了两个问题: 1.与内容等高,最小高度为一屏的高

ios UINavigationController 导航栏

1.关于导航栏左右两边的按钮 1.隐藏导航栏上的返回字体 //Swift UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), forBarMetrics: .Default) //OC [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarM

一次性解决导航栏的所有问题

系统默认导航栏的返回按钮和返回方式 在默认情况下,导航栏返回按钮长这个样子 导航栏默认返回按钮 导航栏左上角的返回按钮,其文本默认为上一个ViewController的标题,如果上一个ViewController没有标题,则为Back(中文环境下为"返回"). 在默认情况下,导航栏返回的点击交互和滑动交互如下 默认导航栏交互 这些东西不需要任何设置和操作,因此也没有其他需要说明的地方. 自定义左上角的返回按钮 绝大多数情况下,我们都需要根据产品需求自定义左上角的返回按钮,虽然这对大多数

iOS开发UINavigation系列一——导航栏UINavigtionBar

iOS开发UINavigation系列一--导航栏UINavigtionBar 一.导航栏的使用 在iOS开发中,我们通常会使用导航控制器,导航控制器中封装了一个UINavigationBar,实际上,我们也可以在不使用导航控制器的前提下,单独使用导航栏,在UINavigationBar中,也有许多我们可以定制的属性,用起来十分方便. 二.UINavigationBar的创建和风格类型 导航栏继承于UIView,所以我们可以像创建普通视图那样创建导航栏,比如我们创建一个高度为80的导航栏,将其放

iOS开发项目篇—04添加导航栏的按钮

iOS开发项目篇—04添加导航栏的按钮 一.设置导航栏的按钮 要求实现的效果:             说明:默认状态下和高亮状态下的图片是不一样的. 按钮的图片需要设置默认状态和高亮状态时的显示,系统了提供的下面方法 viewController.navigationItem.leftBarButtonItem=[UIBarButtonItem alloc]initWithImage:<#(UIImage *)#> style:<#(UIBarButtonItemStyle)#>

iOS开发项目—04添加导航栏的按钮

iOS开发项目—04添加导航栏的按钮 一.设置导航栏的按钮 要求实现的效果:             说明:默认状态下和高亮状态下的图片是不一样的. 按钮的图片需要设置默认状态和高亮状态时的显示,系统了提供的下面方法 viewController.navigationItem.leftBarButtonItem=[UIBarButtonItem alloc]initWithImage:<#(UIImage *)#> style:<#(UIBarButtonItemStyle)#>