今天遇到了一个很奇怪的问题,项目采用的是TabbarController+NavigationBarController的模式进行构建,在NavgationBarController只有一个子控制器的时候,如果进行横屏跳转时再回来,会有一个闪动效果。经过一系列调试后,发现在NavgationBar跳转下一页面时,由于设置了hidesBottomBarWhenPushed属性,Tabbar的subviews会发生改变,如下
刚创建时:
跳转时:
可以看到,在跳转时tabbar的SubViews的数组地址和子View的地址都发生了改变。
在layoutSubViews方法中tabbarButton 的frame变了。
解决办法:
@interface DPTabbar : UITabBar
@property (nonatomic, strong) NSMutableArray * tabbars;
@property (nonatomic, strong) NSMutableArray * heightArray;
@end
static CGRect _theFrame;
@implementation DPTabbar
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_tabbars = [NSMutableArray array];
_heightArray = [NSMutableArray array];
self.frame = _theFrame;
}
return self;
}
- (void)layoutSubviews{
[super layoutSubviews];
[self statusReplay];
}
- (void)setFrame:(CGRect)frame{
if (!CGRectEqualToRect(self.frame, _theFrame)) {
frame = _theFrame;
}
[super setFrame:_theFrame];
}
- (void)statusMemory{
NSArray *subViews = self.subviews;
[_tabbars removeAllObjects];
for (UIView * view in subViews) {
if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
[_tabbars addObject:view];
}
}
}
- (void)heightMemory{
[_heightArray removeAllObjects];
for (UIView * view in _tabbars) {
[_heightArray addObject:NSStringFromCGRect(view.frame)];
}
}
- (void)statusReplay{
NSMutableArray *array = [NSMutableArray array];
NSArray *subViews = self.subviews;
for (id view in subViews) {
if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
[array addObject:view];
}
}
NSInteger count = array.count;
NSInteger heightCount = _heightArray.count;
if (count != heightCount) return;
for (NSInteger i = 0; i < count; i++) {
UIView *view = [array objectAtIndex:i];
view.frame = CGRectFromString(self.heightArray[i]);
}
}
@end
然后在tabbarcontroller的ViewDidLoad中设置:
- (void)viewDidLoad{
[super viewDidLoad];
_dpTabbar = [DPTabbar new];
[self setValue:_dpTabbar forKey:@"tabBar"];
self.view.backgroundColor = [UIColor whiteColor];
[self setVCs];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarFrameDidChange)
name:UIApplicationDidChangeStatusBarFrameNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarFramewillChange)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
}
- (void)statusBarFrameDidChange{
[_dpTabbar statusReplay];
}
- (void)statusBarFramewillChange{
- (void)statusBarFramewillChange{
if (_dpTabbar.tabbars.count == 0) {
[_dpTabbar statusMemory];
}
if (_dpTabbar.tabbars.count > 0 && _dpTabbar.heightArray.count > 0){
[_dpTabbar statusReplay];
return;
}
[_dpTabbar heightMemory];
}
这样就可以解决。思路是在push前存储tabbar个Item的高度,并在状态栏改变之前即push到下一页面的时候,将tabbar新创的subViews中的tabbarButtonframe设为对应的tabbarButton的frame。