蓝条下压和消失导致页面错乱问题解决方案

蓝条下压产生问题的本质原因是,热点出现时系统状态栏高度增加了20个像素,当热点消失时,系统状态栏高度变为标准的20个高度。
理论上只需捕获到系统状态栏变更通知(UIApplicationWillChangeStatusBarFrameNotification这个通知我找了20多天才无意找到),找到自定义工具栏(手写实现或xib自动布局实现)的中心点上移和下移20个像素就可以解决。至于ios7.0以下的蓝条下压产生的页面布局变化就不再适配了,现在的应用最低支持的都是ios7.0了。
实际上解决起来没有那么简单,这只能保证部分全手写控件的蓝条下压和消失控件位置错乱,自动布局控件会有很多莫明奇妙的问题。
修改的方法:
1. 在系统状态栏改变后,调整自定义手写工具栏的中心点(注意若有热点,用户去设置页面并返回原页面,原页面控制器会收到两次状态栏改变通知,第一次带热点的状态栏消失通知,第二次是带热点的状态栏出现通知)。
2. 在系统状态栏改变后,有些调整自定义xib自动布局实现的工具栏中心点,注意有的自动布局控件的最外层承载view上线留有空白,调整的高度可能大于或小于20个像素。
3. 控件出现时要根据是否有蓝条来,对控件frame进行调整。
4. 对于自定义xib自动布局控件,并且是在控件的代理函数调整高度的,注意要在页面首次加载是根据是否有蓝条,调整默认初始化位置(若是自定义xib自动布局控件在viewDidAppear或viewWillAppear显示的加载一次,在用时才加载,那么在iphone6上会显示不出来。)。
蓝条下压导致控件异常的共有四种类型:
1. 普通代码实现控件,车辆类型选择控件。
2. 代码实现控件通过页面种的滑动事件触发调整控件frame,紫色的滑动工具条。
3. 自定义xib控件通过在主页面的滑动按钮事件调整控件frame,白色费用显示工具条。
4. 自定义xib控件通过控件自身的代理函数调整frame,黄色可下拉新的预约单列表显示页面。
测试用例共有五个,不同的场景测试出来的结果截然不同,只有搞定这四个测试用例才能算修改好。
1, 启动应用时有蓝条,在本页面蓝条消失和再次出现,控件位置不能变。
2, 启动应用时没有蓝条,在本页面蓝条出现和消失,控件位置不能变。
3, 启动应用时有蓝条,经过本页面条道其它页面,蓝条消失,再回到本页面,控件位置不能变。
4, 启动应用时没有蓝条,经过本页面条道其它页面,蓝条出现后跳到本页面,控件位置不能变。
5,启动应用时没有蓝条,启动成功,出现蓝条,然后又新的自定义的工具条(xib实现的工具条)出现在顶部。
6,启动应用时有蓝条,控件位置根据是否有蓝条自动调整。
对于车辆类型选择控件,是标准的手写控件,当点击是修改控件的中心点来实现类型的选择按钮的出现和消失。这个控件对栏条下压的适配很简单。
注意若是启动应用时有蓝条,那么你就不能立刻收到状态栏改变通知,需要在加载控件时根据是否有蓝条直接调整控件的初始高度。

- (void)initSelectView
{
    selectView.frame = CGRectMake(0, kControlHeight - 26 - [self handleUIApplicationStatusBarFrame], kControlWidth, 100);
    [self.view addSubview:selectView];

}

-(NSInteger)handleUIApplicationStatusBarFrame
{
    FLDDLogDebug(@"函数");
    // 根据系统状态栏高判断热点栏的变动
    BOOL bPersonalHotspotConnected = ([UIApplication sharedApplication].statusBarFrame.size.height==(SYS_STATUSBAR_HEIGHT+HOTSPOT_STATUSBAR_HEIGHT)?YES:NO);
    if(bPersonalHotspotConnected)
    {
        return HOTSPOT_STATUSBAR_HEIGHT;
    }
    else
    {
        return 0;
    }
}

只需要处理当控件是调整控件的初始位置,处理当收到系统状态改变通知时太哦正控件的中心点就可以,对点击按钮时改变控件位置时适配蓝条就可以。
代码:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleUIApplicationWillChangeStatusBarFrameNotification:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil]; //清除车辆选择信息通知

  • (void)ShowBottomSlideView:(UIButton *)sender
    {
    FLDDLogDebug(@”函数”);
    if (NO == _isShow)
    {

    [UIView animateWithDuration:0.5 animations:^{
        CGRect rectView = _slideView.frame;
        if(IS_HOTSPOT_CONNECTED)
        {
            rectView.origin.y = kControlHeight - 110 - HOTSPOT_STATUSBAR_HEIGHT;
            _slideView.frame = rectView;
        }
        else
        {
            rectView.origin.y = kControlHeight - 110;
            _slideView.frame = rectView;
        }
    
    } completion:^(BOOL finished) {
    
          [sender setBackgroundImage:[UIImage imageNamed:@"接单下拉条"] forState:UIControlStateNormal];
    }];
    

    }
    else
    {
    [UIView animateWithDuration:0.5 animations:^{
    CGRect rectView = _slideView.frame;
    if(IS_HOTSPOT_CONNECTED)
    {
    rectView.origin.y = kControlHeight -26 - HOTSPOT_STATUSBAR_HEIGHT;
    _slideView.frame = rectView;
    }
    else
    {
    rectView.origin.y = kControlHeight -26;
    _slideView.frame = rectView;
    }
    } completion:^(BOOL finished) {

        [sender setBackgroundImage:[UIImage imageNamed:@"接单上拉条"] forState:UIControlStateNormal];
    }];
    

    }
    _isShow = !_isShow;
    }

  • (void)handleUIApplicationWillChangeStatusBarFrameNotification:(NSNotification*)notification
    {
    FLDDLogDebug(@”函数”);
    CGRect newStatusBarFrame = [(NSValue*)[notification.userInfo objectForKey:UIApplicationStatusBarFrameUserInfoKey] CGRectValue];
    // 根据系统状态栏高判断热点栏的变动
    BOOL bPersonalHotspotConnected = (CGRectGetHeight(newStatusBarFrame)==(SYS_STATUSBAR_HEIGHT+HOTSPOT_STATUSBAR_HEIGHT)?YES:NO);

    CGPoint newCenter = CGPointZero;
    CGFloat OffsetY = bPersonalHotspotConnected?+HOTSPOT_STATUSBAR_HEIGHT:-HOTSPOT_STATUSBAR_HEIGHT;
    newCenter = _slideView.center;
    if(bPersonalHotspotConnected)
    {
    if(kControlHeight - 26 + 110/2 == newCenter.y)
    {
    OffsetY = HOTSPOT_STATUSBAR_HEIGHT;
    newCenter.y -= OffsetY;
    _slideView.center = newCenter;
    }
    else if(kControlHeight - 110 + 110/2 == newCenter.y)
    {
    OffsetY = HOTSPOT_STATUSBAR_HEIGHT;
    newCenter.y -= OffsetY;
    _slideView.center = newCenter;
    }
    }
    else
    {
    if(kControlHeight - 110 - HOTSPOT_STATUSBAR_HEIGHT + 110/2 == newCenter.y)
    {
    newCenter.y = kControlHeight - 110 + 110/2;
    _slideView.center = newCenter;
    }
    else if(kControlHeight - 26 + 110/2 != newCenter.y)
    {
    newCenter.y = kControlHeight - 26 + 110/2;
    _slideView.center = newCenter;
    }

    }
    }

  • (void)hiddenBottomSlideView:(UIButton *)sender
    {
    FLDDLogDebug(@”函数”);
    if (_isShow)
    {
    CGRect rectView = _slideView.frame;
    rectView.origin.y = kControlHeight -26;
    _slideView.frame = rectView;
    [sender setBackgroundImage:[UIImage imageNamed:@”接单上拉条”] forState:UIControlStateNormal];

// [UIView animateWithDuration:0.5 animations:^{
// CGRect rectView = _slideView.frame;
// rectView.origin.y = kControlHeight -26;
// _slideView.frame = rectView;
// } completion:^(BOOL finished) {
//
// [sender setBackgroundImage:[UIImage imageNamed:@”接单上拉条”] forState:UIControlStateNormal];
// }];
_isShow = !_isShow;
}
}

  • (void)initWithBottomSlideView
    {
    FLDDLogDebug(@”函数”);

    if(IS_HOTSPOT_CONNECTED)
    {
    _slideView = [[UIView alloc] initWithFrame:CGRectMake(0, kControlHeight - 26 - HOTSPOT_STATUSBAR_HEIGHT, kControlWidth, 110)];
    }
    else
    {
    _slideView = [[UIView alloc] initWithFrame:CGRectMake(0, kControlHeight - 26, kControlWidth, 110)];
    }

}

对于自定义xib代理实现控件页面位置改变的控件,对蓝条适配要多一个在加载时的控件初始化位置适配:

  • (void)viewDidAppear:(BOOL)animated
    {
    FLDDLogDebug(@”函数”);
    [super viewDidAppear:YES];

    _mapView.frame = CGRectMake(0, 0, kControlWidth, kControlHeight);
    _mapView.delegate = self;
    _mapView.customizeUserLocationAccuracyCircleRepresentation = NO;
    _mapView.showsUserLocation = YES;

    if (!_viewDidApper)
    {
    _viewDidApper = YES;

    noticecarview.frame = CGRectMake(0, 0, kControlWidth, kControlHeight);
    servicingView.frame=CGRectMake(0, -200, kControlWidth, 178);
    if(IS_HOTSPOT_CONNECTED)
    {
        _bookingButtonView.frame = CGRectMake(0, 0, kControlWidth, 40);
    

    // self.center = CGPointMake(kControlWidth / 2, 84 - HOTSPOT_STATUSBAR_HEIGHT + 20);
    }
    else
    {
    _bookingButtonView.frame = CGRectMake(0, HOTSPOT_STATUSBAR_HEIGHT, kControlWidth, 40);
    // self.center = CGPointMake(kControlWidth / 2, 84);
    }
    _priceView.frame = CGRectMake(0, kControlHeight + 100, kControlWidth, 50);
    }
    }
    其它的自定位手写紫色工具条和自动定义xib自动布局白色费用工具条,黄色预约单工具条对蓝条匹配的代码:
    [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(handleUIApplicationWillChangeStatusBarFrameNotification:)
    name:UIApplicationWillChangeStatusBarFrameNotification
    object:nil];

  • (void)handleUIApplicationWillChangeStatusBarFrameNotification:(NSNotification*)notification
    {
    FLDDLogDebug(@”函数”);
    CGRect newStatusBarFrame = [(NSValue*)[notification.userInfo objectForKey:UIApplicationStatusBarFrameUserInfoKey] CGRectValue];
    // 根据系统状态栏高判断热点栏的变动
    BOOL bPersonalHotspotConnected = (CGRectGetHeight(newStatusBarFrame)==(SYS_STATUSBAR_HEIGHT+HOTSPOT_STATUSBAR_HEIGHT)?YES:NO);

    CGPoint newCenter = CGPointZero;
    CGFloat OffsetY = bPersonalHotspotConnected?+HOTSPOT_STATUSBAR_HEIGHT:-HOTSPOT_STATUSBAR_HEIGHT;
    newCenter = bottomView.center;
    if(bPersonalHotspotConnected)
    {
    if(kControlHeight-27.5 == newCenter.y)
    {
    OffsetY = HOTSPOT_STATUSBAR_HEIGHT;
    newCenter.y -= OffsetY;
    bottomView.center = newCenter;
    }

    newCenter = _priceView.center;
    if(!(_priceView.hidden))
    {
        if(MAP_VIEW_MAIN == [Singleton sharedInstance].mapViewPage)
        {
            newCenter.y = kControlHeight - 75 - HOTSPOT_STATUSBAR_HEIGHT + 14;
        }
        else
        {
            newCenter.y = kControlHeight - 75 - HOTSPOT_STATUSBAR_HEIGHT;
        }
    
        _priceView.center = newCenter;
    }
    

// if(_bookingButtonView.getBookShowFlag)
// {
// if(MAP_VIEW_MAIN == [Singleton sharedInstance].mapViewPage)
// {
// _bookingButtonView.center = CGPointMake(kControlWidth / 2, 84 - HOTSPOT_STATUSBAR_HEIGHT + 20);
// }
// else
// {
// _bookingButtonView.center = CGPointMake(kControlWidth / 2, 84);
// }
// }
}
else
{
if(kControlHeight-27.5 - HOTSPOT_STATUSBAR_HEIGHT == newCenter.y)
{
newCenter.y = kControlHeight-27.5;
bottomView.center = newCenter;
}
newCenter = _priceView.center;
if(!(_priceView.hidden))
{
newCenter.y = kControlHeight-75 - HOTSPOT_STATUSBAR_HEIGHT;
_priceView.center = newCenter;
}

// if(_bookingButtonView.getBookShowFlag)
// {
// _bookingButtonView.center = CGPointMake(kControlWidth / 2, 84);
// }
}
}

//滑动动画
-(void)startSlideAnination
{
FLDDLogDebug(@”函数”);
[UIView animateWithDuration:0.5 animations:^{
// bottomView.frame = CGRectMake(bottomView.frame.origin.x, kControlHeight-100, bottomView.frame.size.width, bottomView.frame.size.height);
if(IS_HOTSPOT_CONNECTED)
{
bottomView.center = CGPointMake(kControlWidth/2,kControlHeight-27.5 - HOTSPOT_STATUSBAR_HEIGHT);
_priceView.center=CGPointMake(kControlWidth/2,kControlHeight-75 - HOTSPOT_STATUSBAR_HEIGHT);
// _priceView.center=CGPointMake(kControlWidth/2,kControlHeight-75);
}
else
{
bottomView.center = CGPointMake(kControlWidth/2,kControlHeight-27.5);
_priceView.center=CGPointMake(kControlWidth/2,kControlHeight-75);
// _priceView.center=CGPointMake(kControlWidth/2,kControlHeight);
}
if((-1 != [GlobalShare getGlobalShare].user.servicingOrderId) && (GETIN == [_orderDict[@”orderStatus”] integerValue]))
{
_priceView.hidden = NO;
}

        bottomView.hidden = NO;

// bottomV iew.center=CGPointMake(kControlWidth/2,kControlHeight-27.5);
// _priceView.center=CGPointMake(kControlWidth/2,kControlHeight-75);

        [slideImageView startAnimating];
    } completion:^(BOOL finished) {

// if(NETWORK_TYPE_WIFI == [self getNetworkTypeFromStatusBar])
// {
// [SVProgressHUD showErrorWithStatus:@”手机自动连接WiFi网络时,会导致行程费用计算不准确,为减少损失,请关闭WiFi”];
// }
// else
// {
// [SVProgressHUD dismiss];
// }

    }];

}

蓝条下压问题相关宏定义:
//系统状态栏相关声明
// iOS系统版本

define SYSTEM_VERSION [[[UIDevice currentDevice] systemVersion] doubleValue]

// 标准系统状态栏高度

define SYS_STATUSBAR_HEIGHT 20

// 热点栏高度

define HOTSPOT_STATUSBAR_HEIGHT 20

// 导航栏(UINavigationController.UINavigationBar)高度

define NAVIGATIONBAR_HEIGHT 44

// 工具栏(UINavigationController.UIToolbar)高度

define TOOLBAR_HEIGHT 44

// 标签栏(UITabBarController.UITabBar)高度

define TABBAR_HEIGHT 44

// APP_STATUSBAR_HEIGHT=SYS_STATUSBAR_HEIGHT+[HOTSPOT_STATUSBAR_HEIGHT]

define APP_STATUSBAR_HEIGHT (CGRectGetHeight([UIApplication sharedApplication].statusBarFrame))

// 根据APP_STATUSBAR_HEIGHT判断是否存在热点栏

define IS_HOTSPOT_CONNECTED (APP_STATUSBAR_HEIGHT==(SYS_STATUSBAR_HEIGHT+HOTSPOT_STATUSBAR_HEIGHT)?YES:NO)

// 无热点栏时,标准系统状态栏高度+导航栏高度

define NORMAL_STATUS_AND_NAV_BAR_HEIGHT (SYS_STATUSBAR_HEIGHT+NAVIGATIONBAR_HEIGHT)

// 实时系统状态栏高度+导航栏高度,如有热点栏,其高度包含在APP_STATUSBAR_HEIGHT中。

define STATUS_AND_NAV_BAR_HEIGHT (APP_STATUSBAR_HEIGHT+NAVIGATIONBAR_HEIGHT)

正常的带预约单黄条页面:

蓝条下压和消失导致页面错乱问题解决方案_第1张图片
当因为没有适配首次出现黄条的初始位置时,当测试那4个测试用例时出现的异常页面:
蓝条下压和消失导致页面错乱问题解决方案_第2张图片

你可能感兴趣的:(页面布局变化,蓝条下压,热点出现)