2012-04-25 61 views
2

我实现了一个自定义的分割视图控制器,它原则上工作得很好。然而UIToolbar的动画调整大小在iOS上剪裁背景<5.1

还有就是,做工作预计一个方面,这是iOS上的工具栏5.1版本之前的调整大小的动画 - 如果存在的话:

继承后UIToolbar覆盖其layoutSubviews方法,动画更改我的主要内容区域的宽度会导致工具栏项目按预期移动。工具栏的背景 - 但是 - 如预期的那样,不是动画。

相反,其宽度会立即更改为新值,导致在增加宽度时显示背景。

这里是什么,我认为我使用的代码的相关部分 - 都相当标准的东西,如小魔/两轮牛车地:

// From the implementation of my Split Layout View Class: 
- (void)setAuxiliaryViewHidden:(BOOL)hide animated:(BOOL)animated completion:(void (^)(BOOL isFinished))completion 
{ 
auxiliaryViewHidden_ = hide; 
    if (!animated) 
    { 
     [self layoutSubviews]; 
     if (completion) 
      completion(YES); 

     return; 
    } 

    // I've tried it with and without UIViewAnimationOptionsLayoutSubviews -- didn't change anything... 
    UIViewAnimationOptions easedRelayoutStartingFromCurrentState = UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState; 
    [UIView animateWithDuration:M_1_PI delay:0.0 options:easedRelayoutStartingFromCurrentState animations:^{ 
     [self layoutSubviews]; 
    } completion:completion]; 
} 

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    // tedious layout work to calculate the frames for the main- and auxiliary-content views 

    self.mainContentView.frame = mainContentFrame; // <= This currently has the toolbar, but... 
    self.auxiliaryContentView.frame = auxiliaryContentFrame; // ...this one could contain one, as well. 
} 

// The complete implementation of my UIToolbar class: 
@implementation AnimatableToolbar 

static CGFloat sThresholdSelectorMargin = 30.; 

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    // walk the subviews looking for the views that represent toolbar items 
    for (UIView *subview in self.subviews) 
    { 
     NSString *className = NSStringFromClass([subview class]); 
     if (![className hasPrefix:@"UIToolbar"]) // not a toolbar item view 
      continue; 

     if (![subview isKindOfClass:[UIControl class]]) // some other private class we don't want to f**k around with… 
      continue; 

     CGRect frame = [subview frame]; 
     BOOL isLeftmostItem = frame.origin.x <= sThresholdSelectorMargin; 
     if (isLeftmostItem) 
     { 
      subview.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; 
      continue; 
     } 

     BOOL isRightmostItem = (CGRectGetMaxX(self.bounds) - CGRectGetMaxX(frame)) <= sThresholdSelectorMargin; 
     if (!isRightmostItem) 
     { 
      subview.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 

      continue; 
     } 

     subview.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; 
    } 
} 

@end 

我已经设置了类工具栏的InterfaceBuilder下和我知道一个事实,就是这个代码被调用,就像我说的,在iOS 5.1上,一切正常。

我不得不开始支持4.2版本的iOS,但...

任何帮助/提示为我缺少什么,我都非常感谢。

回答

1

就我所见,您的方法只能在iOS SDK> 5上运行。事实上,iOS SDK 5引入了以明确方式操纵背景的可能性(请参阅setBackgroundImage:forToolbarPosition:barMetrics和相对的getter方法)。

在iOS SDK 4中,UIToolbar对象没有_UIToolbarBackground子视图,因此无法在您的layoutSubviews实现中移动它。要验证这一点,请添加这样的跟踪:

for (UIView *subview in self.subviews) 
{ 
    NSLog(@"FOUND SUBVIEW: %@", [subview description]); 

在iOS 4和5上运行代码,您将看到我的意思。

总而言之,解决您的问题的方法是在iOS 4和iOS 5下以两种不同的方式处理背景。具体而言,在iOS 4,你可以给以下方法试试:

  1. 一个子视图添加到您的自定义UIToolbar充当背景视图:

    [toolbar insertSubview:backgroundView atIndex:0];

  2. 集:

    toolbar.backgroundColor = [UIColor clearColor];

    这样UIToolbar背景颜色不会干扰Ë;

  3. 你的layoutSubviews方法在这个背景子视图和其他人一起动画,就像你在做的一样;

当然,没有什么可以阻止您使用此相同的背景子视图还为iOS 5中,只有你应该提防的是,在步骤1中,子视图应该在指数1(即插入,上顶现有背景)。

希望这可以帮助。

+0

拍摄,我忘记评论布局子视图:我正在布局我的工具栏项目视图,否则 - 不会顺利地生成动画,但也跳到他们的新位置。 – danyowdee 2012-05-18 06:36:07

+0

我不确定我完全理解您的评论,对不起...我的提示帮助? – sergio 2012-05-18 08:16:16

+0

我的'layoutSubviews'不是用来移动工具栏的_background_。它只是减轻了设置工具栏框架时的问题 - 即使在UIViewAnimation(块)内 - 工具栏项目也会跳转到它们的新位置。在iOS <5.1中插入一个静态渲染的图像作为子视图将是一个有点可接受的解决方法,尽管我希望这个解决方案不那么黑客。 – danyowdee 2012-05-18 10:01:45

0

因为我认为这会为别人,我只是将我的解决这里的参考是有用的:

每Sergio的建议,我插一个额外UIImageView到视图层次结构。但因为我想这与默认的工具栏样式的工作,我需要跳低谷几个篮球:

  1. 需要动态地生成的图像每当tintColor改变。
  2. 在iOS 5.0.x上,工具栏背景是一个附加视图。

要解决此我结束了......

  1. 实施+load设置我是否需要做任何事情静态BOOL。 (为5.1之前的版本解析-[UIDevice systemVersion])。
  2. 为图像视图stretchableBackground添加(延迟加载)属性。如果我的静态标志是NO,视图将是nil。否则,视图将被创建为具有两倍宽度[UIScreen mainScreen],向左偏移一半宽度并且在高度和右边界处可调整大小,并且插入到索引0处的工具栏中。
  3. 重写setTintColor:。每当发生这种情况,我打电话到super__updateBackground
  4. 实现的方法__updateBackground说:
    • 当工具栏响应backgroundImageForToolbarPosition:barMetrics:得到的第一个子视图,是不是我们的stretchableBackground。使用该视图的图层的contents属性来填充stretchableBackgroundimage属性并返回。
    • 如果工具栏不给回应选择,
      1. 使用CGBitmapContextCreate()获得32位RGBA CGContextRef即一个像素宽和高的工具栏乘以屏幕的规模。 (使用kCGImageAlphaPremultipliedLast处理设备RGB颜色空间...)
      2. 将CTM转换为该高度,然后按比例/比例缩放以从UIKit转换到CG坐标,并将视图的图层绘制到该上下文中。 (如果你没有做到这一点,你的图像将永远是透明的空白...)
      3. 从该上下文创建一个UIImage并将其设置为stretchableBackground的图像。

注意使用肖像不同的背景图像和景观或图像不扩展,当此修复程序适用于iOS 5.0.x的也不会达到预期工作 - 尽管这可以通过进行调整以不同的方式配置图像视图...