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

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

蓝条下压产生问题的本质原因是,热点出现时系统状态栏高度增加了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)

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

当因为没有适配首次出现黄条的初始位置时,当测试那4个测试用例时出现的异常页面:

按照以上方案当热点共享显示和消失时,仍有低概率出现底部按钮错乱的问题。主要是xib和手写带frame的控件难以控制。

可以统一使用SDAutoLayout这个第三方库写页面,请看我的新的完美解决方案:热点共享蓝条下压,导致页面底部按钮显示不全完美解决方案(http://blog.csdn.net/jia12216/article/details/53171647

目录
相关文章
|
6天前
|
Web App开发 XML 开发框架
技术心得记录:在IE浏览器中的奇怪页面表现
技术心得记录:在IE浏览器中的奇怪页面表现
|
小程序 开发者 异构计算
小程序真机调试反应很慢卡顿,界面跳转之后,页面出现空白,无法点击等问题解决方案
小程序真机调试反应很慢卡顿,界面跳转之后,页面出现空白,无法点击等问题解决方案
1064 0
小程序真机调试反应很慢卡顿,界面跳转之后,页面出现空白,无法点击等问题解决方案
|
6天前
|
小程序 API
技术心得记录:微信小程序之图片频繁变化,几秒之后输出结果(适用于抽奖)
技术心得记录:微信小程序之图片频繁变化,几秒之后输出结果(适用于抽奖)
10 0
|
2月前
|
Android开发
个人热点蓝条出现和消失时,页面下压和恢复导致页面混乱及蓝条下压页面底部控件看不到的问题
个人热点蓝条出现和消失时,页面下压和恢复导致页面混乱及蓝条下压页面底部控件看不到的问题
35 0
|
7月前
|
存储 JavaScript 小程序
刷新网页后先前浏览位置不变的解决方案
我重新加载网页,刷新之后,滚动条依然定位在我刚刚浏览的位置,这个小功能感觉还不错,挺方便的。 具体是怎么实现的呢,去网上大概查了一下。 这个是使用滚动条属性scrollTop来实现的。
51 0
|
12月前
|
Web App开发 JavaScript 前端开发
浏览器页面卡住定位分析
有童鞋在xxx系统页面反馈,遇到在弹出框后整个页面卡住无法使用的情况,属于必现问题。因此需要跟踪定位问题。
402 0
浏览器页面卡住定位分析
|
人工智能 JavaScript 前端开发
小程序实现页面多级来回切换支持滑动和点击操作
想留住粉丝,就必须安排演示: [审核中…]然后开摆!!!!首先通过swiper创建一个简单的多tab页面 通过触发pagechange1方法中的事件对currentIndex来进行赋值,又通过currentIndex的改变使前端wxml对应更改,这个部分对滑动和点击的操作都一样,无非就是使currentIndex对应到各自的位置,通过数字来决定位置 这个部分完整代码如下: wxml wxss js 上一步完成后,下级页面再加一个滑动页面,当内切换结束后,在做切换就是父级的切换操作 在“内容1”的vie
245 0
小程序实现页面多级来回切换支持滑动和点击操作
|
小程序 前端开发 iOS开发
小程序页面左右滑动如何解决
小程序页面左右滑动如何解决
|
Java Android开发
安卓跳转到新活动时加载视图,再加载数据。预防崩
安卓跳转到新活动时加载视图,再加载数据。预防崩
99 0
|
缓存 数据处理 异构计算
屏幕刷新机制简单问(没有代码,请放心享用)
周一好呀,今天给大家带来一点轻松简单的内容,没有代码,请享用~
246 0
屏幕刷新机制简单问(没有代码,请放心享用)