UIScrollView与地图页面嵌套效果的实现。

经常使用美团或饿了的朋友都会在订单页看到一个效果,上面是个地图,下面是订单的详情。向上滑动的时候地图被覆盖掉,滑下来地图出现,而且滑动地图时只有地图的mapview在动。这种效果怎么实现呢?今天来做一下这个demo。

先放效果图,两种实现方式,两种效果:

1:地图随着scroll的滑动而滑动

“gif有点大,CSDN不让传,请点击查看原图链接”

 

2,地图不动。scroll自己滑动

 

“这个gif也有点大,CSDN不让传,请点击查看原图链接”

先说下第一种实现,上代码

@interface MapScrollViewController ()

@property (nonatomic, strong) UIScrollView *mapScv;

@end

@implementation MapScrollViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _mapScv = [[UIScrollView alloc] init];
    _mapScv.alwaysBounceVertical = YES;
    _mapScv.scrollEnabled = YES;
    _mapScv.contentInset = UIEdgeInsetsMake(300, 0, 0, 0);
    [self.view addSubview:_mapScv];
    
    [_mapScv mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view);
    }];
    
    UIGestureRecognizer *mainScrollVTap = [[UIGestureRecognizer alloc]init];
    mainScrollVTap.delegate=self;
    [_mapScv addGestureRecognizer:mainScrollVTap];
    
    UIView *contentView = [UIView new];
    [_mapScv addSubview:contentView];
    
    [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.width.mas_equalTo(_mapScv);
    }];
    
    UIView *view = [UIView new];
    view.backgroundColor = [UIColor redColor];
    [contentView addSubview:view];
    
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(kScreenWidth, 2000));
        make.left.top.equalTo(contentView);
    }];
    
    [contentView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.bottom.mas_equalTo(view);
    }];
    
    MKMapView *map1 = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 300)];
    map1.delegate = self;
    map1.mapType = MKMapTypeStandard;
    [contentView addSubview:map1];
}

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
    //判断如果是百度地图的view 既可以实现手势拖动 scrollview 的滚动关闭
    if ([gestureRecognizer.view isKindOfClass:[MKMapView class]] ){
        _mapScv.scrollEnabled = NO;
        return YES;
    }else{
        _mapScv.scrollEnabled = YES;
        return NO;
    }
}

这样就能实现图1的效果,实现的手段主要是在self.view上添加一个全屏的UIScrollView,把地图的view作为它的子视图,然后给scroll添加一个手势,在滑动的时候去手势的代理里面判断让scroll可不可以滚动即可,当scroll滚动时。会推着地图view向上走,当滑动地图时,scroll就会不可滚动,很简单的一个实现。

第二种比较通用,看起来也比较好看,实现起来比第一种还要简单,代码:

@interface MapScrollView : UIScrollView

@end

@implementation MapScrollView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    UIView *hitView = [super hitTest:point withEvent:event];
    if ([hitView isKindOfClass:[self class]]) {
        return nil;
    }
    return hitView;
}

@end

@interface MapScrollViewController ()

@property (nonatomic, strong) MapScrollView *mapScv;

@end

@implementation MapScrollViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    MKMapView *map1 = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 300)];
    map1.delegate = self;
    map1.mapType = MKMapTypeStandard;
    [self.view addSubview:map1];
    
    _mapScv = [[MapScrollView alloc] init];
    _mapScv.alwaysBounceVertical = YES;
    _mapScv.scrollEnabled = YES;
    _mapScv.contentInset = UIEdgeInsetsMake(300, 0, 0, 0);
    [self.view addSubview:_mapScv];
    
    [_mapScv mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view);
    }];

    UIView *contentView = [UIView new];
    [_mapScv addSubview:contentView];
    
    [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.width.mas_equalTo(_mapScv);
    }];
    
    UIView *view = [UIView new];
    view.backgroundColor = [UIColor redColor];
    [contentView addSubview:view];
    
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(kScreenWidth, 2000));
        make.left.top.equalTo(contentView);
    }];
    
    [contentView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.bottom.mas_equalTo(view);
    }];
}


@end

首先我们写一个继承UIScrollView父类的MapScrollView,实现hitTest方法。

这个hitTest方法的意思就是当滑动和点击时需要处理的事件的响应链,该处理哪个view。比如我在Aview点击时,系统需要知道该处理Aview了,这时你说不要去处理A,系统就说那你告诉我该处理谁,然后然你用这个方法告诉系统该去处理Bview。就是这么个意思。默认的就是哪个view发生的事件就会处理哪个view。

UIView *hitView = [super hitTest:point withEvent:event];
if ([hitView isKindOfClass:[self class]]) {
return nil;
}
return hitView;

这段代码就是说如果当前滑动点击的视图是scroll的话,那么就不要处理了。只滑动即可,这样就不会触发地图的事件。地图也就不会跟着滑动。

在这个例子里,mapview在视图的最底部,scroll在它上面,然后scroll滑动范围是全屏的,但是展示的范围不能全屏,需要设置contentinset。

这样就实现了这个简单的需求,怎么样,一点也不复杂吧。

 

原文链接:http://zhangqq166.cn/archives/ios/scroll-map/,希望大家多多关注

 

本人创建了一个公众号,里面每天发一些教程进阶知识,有的是本人总结所得,有的是转载大神的文章,大家一起分享看。

你可能感兴趣的:(iOS技术文档)