【问题标题】:Transforming a subview of UIScrollView转换 UIScrollView 的子视图
【发布时间】:2014-04-02 18:44:08
【问题描述】:

我正在尝试重现像 iOS 7 应用切换器这样的效果,我可以在其中滚动更小的、已转换的视图。我目前的障碍是获取 contentOffset

为了做到这一点,我在视图中添加了一个滚动视图,并将其调整到视图的边界。然后,我创建一个包含所有“卡片”的容器视图——我应用转换的正是这个容器视图。

无论如何,我遇到的问题是调整 where 特定卡片在应用了转换后出现 - 现在,我无法在转换期间以如下方式调整 contentOffset是光滑的。

无论如何,代码会有所帮助!这里是:

NSInteger idx = selectedCardIndex;

if (TransformApplied)
{        
    [UIView animateWithDuration:0.5 animations:^{
        [self.container setTransform:CGAffineTransformIdentity];
        [self.container setFrame:CGRectOffset(self.container.frame, (1-ScaleFactor)/2 * NumCards * ScreenWidth, 0)];
        [self.scrollView setContentSize:self.container.frame.size];
        [self.scrollView setContentOffset:CGPointMake(ScreenWidth * idx, 0) animated:NO];

        [self.scrollView setPagingEnabled:YES];

    } completion:^(BOOL finished) {
        TransformApplied = NO;
    }];
}
else
{
    [UIView animateWithDuration:0.5 animations:^{
        [self.container setTransform:CGAffineTransformMakeScale(ScaleFactor, ScaleFactor)];
        [self.container setFrame:CGRectOffset(self.container.frame, (-1)*((1-ScaleFactor)/2) * NumCards * ScreenWidth, 0)];
        [self.scrollView setContentSize:CGSizeMake(ScreenWidth * ScaleFactor * NumCards, ScreenHeight * ScaleFactor)];
        [self.scrollView setContentOffset:CGPointMake(ScaleFactor * ScreenWidth * idx, 0) animated:NO];


        [self.scrollView setPagingEnabled:NO];

    } completion:^(BOOL finished) {
        TransformApplied = YES;
    }];
}

更多 我注意到在应用恒等变换时一切都很顺利,但在应用较小的变换时,我在动画之前的帧中得到了一个奇怪的“跳跃”。

如果我注释掉缩放变换(底部块)中的内容偏移调整,那么一切运行顺利,但是缩放变换后的 contentOffset 是错误的。

最后,调用 setContentOffset:animated: 会产生不稳定的动画,所以这是不行的。

非常感谢任何帮助!!!!

更新

我查看了 CALayer 上的锚点/位置属性,我的动画效果与此完美配合:

NSInteger idx = selectedCardIndex;

if (TransformApplied)
{
    [UIView dd_AnimateWithDuration:0.5 animations:^{
        [self.container setTransform:CGAffineTransformIdentity];
        [self.scrollView setContentOffset:CGPointMake(ScreenWidth * idx, 0) animated:NO];

        [self.scrollView setPagingEnabled:YES];

    } completion:^(BOOL finished) {
        TransformApplied = NO;
    }];
}
else
{
    CGPoint anchor      = CGPointMake((idx * ScreenWidth + ScreenWidth/2)/CGRectGetWidth(self.container.frame), 0.5f);
    [self.container.layer setAnchorPoint:anchor];
    CGPoint position    = CGPointMake((anchor.x) * self.container.frame.size.width, self.container.layer.position.y);
    [self.container.layer setPosition:position];

    [UIView dd_AnimateWithDuration:0.5 animations:^{
        [self.container setTransform:CGAffineTransformMakeScale(ScaleFactor, ScaleFactor)];

        [self.scrollView setPagingEnabled:NO];

    } completion:^(BOOL finished) {
        TransformApplied = YES;
    }];
}

但是,现在我必须想办法在不改变容器位置的情况下消除滚动视图中的所有额外空间......

【问题讨论】:

    标签: ios objective-c uiscrollview core-animation


    【解决方案1】:

    很久以前我就遇到过关于视图位置的类似问题。经过长时间的研究,我最终得到了UIView 文档。它说 UIViewtransformframe 属性并带有警告:

    警告如果变换属性不是恒等变换,则该属性的值是未定义的,因此应该被忽略。 更改框架矩形会自动重新显示接收器,而无需调用 drawRect: 方法。如果您希望在框架矩形更改时调用 drawRect: 方法,请将 contentMode 属性设置为 UIViewContentModeRedraw。 对此属性的更改可以设置动画。但是,如果 transform 属性包含非恒等变换,则 frame 属性的值是未定义的,不应修改。在这种情况下,您可以使用 center 属性重新定位视图并使用 bounds 属性调整大小。

    因此,基本思想是,当您的视图的 transform 包含非身份转换时,您不应依赖或更改 frame

    更重要的想法是,在寻找其他地方之前,一定要给官方文档一个机会。

    我希望这会有所帮助。

    【讨论】:

    • 对。因此更改 self.container 的框架可能不是处理滚动视图中视图位置不正确的最佳方法。但是,另一种方法可能是将这个容器本身嵌入到另一个容器中,并相应地偏移该容器的框架。不幸的是,我现在的数学有点困难:(
    • 也许您应该使用CAKeyframeAnimations 为您的container 设置动画,并使用positiontransform.scale 键路径。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多