【问题标题】:Custom UIView layoutSubviews with orientation and animations?具有方向和动画的自定义 UIView layoutSubviews?
【发布时间】:2013-03-14 17:02:29
【问题描述】:

我处于两难境地,使用哪种方法来设置自定义 UIViews 的框架,其中包含许多子视图,并且仍然有动画并自动调整到旋转。创建新视图控制器时,我通常会在 loadView 或 viewDidLoad 中分配我的自定义视图,例如:

-(void)viewDidLoad
{
    [super viewDidLoad];
    detailView = [[DetailView alloc] initWithFrame:CGRectMake(0, 0,      self.view.frame.size.width, self.view.frame.size.height)];
    detailView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
    self.view = detailView;    
}

通常这个宽度和高度对于 iPhone5 屏幕是不正确的(实际的视图框架直到 viewWillAppear 才设置),但由于自动调整掩码,这一切都可以解决。

然后在自定义 UIView DetailView 的 initWithFrame 中,我用 CGRectZero 分配所有子视图,例如:

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        label = [[UILabel alloc] initWithFrame:CGRectZero];
        [self addSubview:label];
    }
 }

然后我覆盖 layoutsubviews 来设置所有子视图的所有框架。这适用于任何屏幕尺寸和任何方向,例如:

-(void)layoutSubviews
{
    [super layoutSubviews];
    label.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
}

但是,我刚发现layoutSubviews在使用动画的时候不是很好,因为当你在animationblock中使用动画时,layoutsubviews在动画中间被调用,它完全破坏了动画,例如:

-(void)animateLabel
{
    [UIView animateWithDuration:0.4f animations:^
    {
        label.transform = CGAffineTransformMakeTranslation(100, 100);
    }];
}

我相信通过为每个动画使用标志和在 layoutsubviews 中使用这些标志来设置动画块的正确开始或结束帧有一些丑陋的解决方法,但我认为我不应该为每个动画创建一个标志想做。

所以我现在的问题是:我应该如何拥有一个带有动画的自定义 UIView,它也会自动调整自身以适应旋转?

我现在能想到的唯一解决方案(我不喜欢): 不要使用 layoutSubviews 而是使用自定义 UIView 的 setFrame/setBounds 方法来设置所有子视图的框架。然后在每次发生旋转时检查viewController,然后使用自定义UIView的setFrame/setBounds方法更改所有子视图的所有帧。我不喜欢这个解决方案,因为 iOS5 和 iOS6 中的旋转方法不同,我不想在每个 UIViewController 中都使用它自己的自定义 UIView 来执行此操作。

有什么建议吗?

【问题讨论】:

  • 我遇到了这个问题。你有其他合适的解决方案吗?
  • 你好声华武,我现在做的是以下。我仍然创建一个不实现布局子视图的自定义子视图。然后我在该视图中使用自定义 setNewFrame 方法,我在加载视图控制器和任何旋转更改时设置该方法。在那个自定义的 setNewFrame 方法中,我为那里的任何子视图设置了所有框架。这样,它在子视图中的任何旋转和动画中看起来都很好:)
  • 感谢您的分享。

标签: iphone ios uiview core-animation layoutsubviews


【解决方案1】:

我最近开始在我的UIViewControllers 中覆盖viewDidLayoutSubviews(很多次而不是viewWillAppear)。

是的 viewDidLayoutSubviews 在轮换时被调用。 (来自评论)

该方法在所有内部布局都已完成后触发,因此应设置所有最终帧,但仍然给您时间在视图可见之前进行调整,并且动画不应该有任何问题,因为你还没有在动画块中。

viewcontroller.m

- (void)viewDidLayoutSubViews {
    // At this point I know if an animation is appropriate or not.
    if (self.shouldRunAnimation)
        [self.fuView runPrettyAnimations];
}

fuView.m

- (void)runPrettyAnimations {
    // My animation blocks for whatever layout I'd like.
}

- (void)layoutSubviews {
    // My animations are not here, but non animated layout changes are.
    // - Here we have no idea if our view is visible to the user or may appear/disappear
    // partway through an animation.
    // - This also might get called far more than we intend since it gets called on
    // any frame updates.
}

【讨论】:

  • 您好 DBD,感谢您的回答。 viewDidLayoutSubviews 是否也调用旋转更改?你建议我如何实现这个?通过在此方法中对我的自定义视图调用 setFrame?
  • 我最倾向于在自定义公共方法中对视图进行动画调用,这些视图根据需要从UIViewController 调用。我一直犹豫是否要在视图上添加自动动画,因为您永远不知道视图是否会在屏幕上+可见。您可能会在动画中途看到一个视图。
  • DBD,您能否再解释一下您最后的评论?你的意思是你不把执行动画的调用放在自定义 UIViews 本身吗?你能从我的第一条评论中回答我的问题吗? :)
猜你喜欢
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多