Ios 转换UIScrollView的子视图

Ios 转换UIScrollView的子视图,ios,objective-c,uiscrollview,core-animation,Ios,Objective C,Uiscrollview,Core Animation,我试图重现一种类似iOS 7应用程序切换器的效果,在这种切换器中,我可以在更小的、经过转换的视图之间滚动。我目前的障碍是得到补偿 为了做到这一点,我在我的视图中添加了一个scrollView,并将其大小调整到视图的边界。然后,我创建一个容器视图来保存所有的“卡片”——我将转换应用到这个容器视图 无论如何,我遇到的问题是在应用转换后调整特定卡的显示位置-现在,我无法以平滑的方式在转换期间调整contentOffset 无论如何,代码会有帮助!这是: NSInteger idx = selected

我试图重现一种类似iOS 7应用程序切换器的效果,在这种切换器中,我可以在更小的、经过转换的视图之间滚动。我目前的障碍是得到补偿

为了做到这一点,我在我的视图中添加了一个scrollView,并将其大小调整到视图的边界。然后,我创建一个容器视图来保存所有的“卡片”——我将转换应用到这个容器视图

无论如何,我遇到的问题是在应用转换后调整特定卡的显示位置-现在,我无法以平滑的方式在转换期间调整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;
    }];
}
更多 我注意到,当应用身份变换时,一切都是平滑的,但当应用较小的变换时,我在动画前的帧中得到一个奇怪的“跳跃”

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

最后,调用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;
    }];
}

但是,现在我必须找到一种方法,在不允许容器位置改变的情况下,消除scrollview中的所有额外空间。…

很久以前,我就遇到了一个关于视图位置的类似问题。经过长时间的研究,我最终得到了UIView文档。它说明了UIView的变换和帧属性,并给出了警告:

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

所以,基本思想是,当视图的变换包含非标识变换时,不应依赖或更改帧

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


我希望这有帮助。

对。因此,更改self.container的框架可能不是处理scrollview中视图的错误位置的最佳方法。但是,另一种方法可能是将该容器本身嵌入到另一个容器中,并相应地偏移该容器的帧。不幸的是,我现在在数学方面有点困难:也许你应该使用CAKeyframeAnimations,以及position和transform.scale关键路径来设置容器的动画。