分页 UIScrollView 中的干净自动旋转转换

发布于 2024-09-11 04:40:25 字数 337 浏览 3 评论 0原文

我有一个分页 UIScrollView,用户可以在其中水平翻阅图像,例如 Apple 的 Photos.app。这可行,但现在我正在尝试添加旋转支持。

我已经让视图旋转正常,并设法正确设置 contentSize、边界和子视图的框架以适应不同的方向。所以旋转之前和之后,一切都OK。

然而,过渡本身很尴尬。第一个图像完美旋转,就好像旋转轴位于图像的死点(滚动视图框架)。第二张图像“摆动”,因为旋转轴位于同一位置:第一张图像的中心。距离第一张图像越远,“摆动”越快。

我可以通过在旋转之前覆盖不透明的 UIView 并在旋转之后隐藏它来掩盖这一点。但这是一个黑客行为。必须有一种优雅的方法来做到这一点......

I have a paging UIScrollView in which the user pages horizontally through images, like Apple's Photos.app. That works, but now I'm trying to add rotation support.

I've got the view rotating OK and have managed to set the contentSize, bounds, and subviews' frames properly to adapt to the different orientations. So before and after the rotation, everything is OK.

However, the transitions themselves are awkward. The first image rotates perfectly, as if the axis of rotation is in the dead center of the image (scrollview frame). The second image "swings" in because the axis of rotation is in the same place: the center of the first image. The farther away I get from the first image, the faster the "swing."

I can probably mask this by overlaying an opaque UIView before rotation and hiding it after. But that's a hack. There must be an elegant way to do this...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情何以堪。 2024-09-18 04:40:26

听起来您正在应用魔法,需要以错误的方式将旋转版本显示在屏幕上的正确位置。

由于您没有分享任何代码,因此以下内容只是猜测。据推测,您应用了旋转和平移。 听起来就像您正在旋转 UIScrollView内容。做到这一点将很棘手。如果没有代码,很难说出任何结论,但如果您只有 1 次旋转和 1 次平移,那么您的做法是错误的。您需要将当前视图平移到枢轴点,旋转,然后平移回来。否则,平移将成为旋转的一部分(因此会有大摆动)。

您最好旋转 UIScrollView 本身。它将始终位于具有定义中心的定义位置(即:屏幕)。然后内容将随之旋转。

It sounds like you are applying the magic, needed to get the rotated version on screen at the right place, the wrong way.

Since you didn't share any code, the following is just guesswork. Presumably, you apply a rotation and a translation. It sounds like you are rotating the contents of the UIScrollView. Getting this right will be tricky. It's hard to say anything conclusive without code, but if you only have 1 rotation and 1 translation, you're doing it the wrong way. You need to translate the current view to the pivot point, rotate, and translate back. Otherwise the translation will be part of the rotation (hence the big swing).

You'd better rotate the UIScrollView itself. It will always be in a defined location (namely: the screen) with a defined center. The content will then rotate with it.

雨轻弹 2024-09-18 04:40:26

一个有效的简单解决方案是在 UIScrollView 的 contentSize 更改时注册通知,然后更新 contentOffset。

在您的视图加载方法中添加此行:

[self addObserver:theScrollView forKeyPath:@"contentSize" options:0 context:nil];

在您的视图卸载方法中添加此行:

[self removeObserver:self forKeyPath:@"contentSize"];

捕获通知:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    theScrollView.contentOffset = page * theScrollView.bounds.width;
}

A simple solution that works well is to register for notifications when the contentSize of the UIScrollView is changed and then update the contentOffset at that moment.

In your view loading method add this line:

[self addObserver:theScrollView forKeyPath:@"contentSize" options:0 context:nil];

In your view unloading method add this line:

[self removeObserver:self forKeyPath:@"contentSize"];

Catch the notification:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    theScrollView.contentOffset = page * theScrollView.bounds.width;
}
执笏见 2024-09-18 04:40:25

坦白说,我不知道你在做什么,因为你根本没有向我们展示太多。

但!

我创建了一个示例项目,在滚动视图中包含一些视图,并且工作正常。请随意按照您的意愿将其拆开。它的工作原理是创建 5 个视图,并将它们添加到滚动视图中。然后,在第一次设置这些视图后,每次应用程序旋转时,它都会调用我的方法 alignSubviews 将它们放置在正确的页面位置,并使它们与滚动视图的大小相同,同时更新滚动视图的 contentSize。在旋转发生之前,它会跟踪滚动视图当前所在的页面,然后在旋转期间将其重置到该页面(因为页面大小必须更改)。

下载“Rotolling”!

screenshot

Frankly, I don't know what you're doing, since you haven't shown us much at all.

But!

I created a sample project with a few views in a scroll view, and it works fine. Feel free to pick it apart as you wish. It works by creating 5 views, and adding them to the scroll view. Then after these views are set up for the first time, and every time the application rotates, it calls my method alignSubviews to lay them out at the right page locations and make them the same size as the scroll view, while updating the scroll view's contentSize. Before the rotation occurs, it keeps track of what page the scroll view is currently on, and then resets it to that page during the rotation (because the page size has to change).

Download "Rotolling"!

screenshot

单身情人 2024-09-18 04:40:25

我记下这些附加信息以供以后参考。
我用 @jtvandes' 解决方案的想法解决了这个问题。
然而,就我而言,这些实现就足够了。再次强制布局打破了我的看法。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{
    currentPageOffset = [hostingScrollView contentOffset].x / [hostingScrollView bounds].size.width;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration 
{
    //  Layout changed instantly at this time.
    //  So we have to force to set offset instantly by setting animation to NO.
    [hostingScrollView setContentOffset:CGPointMake([hostingScrollView bounds].size.width * currentPageOffset, 0.0f) animated:NO];
}

I note this additional information for later reference myself.
I solved this with idea from @jtvandes' solution.
However, in my case, it was enough with these implementations. Forcing layout again broke my view.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{
    currentPageOffset = [hostingScrollView contentOffset].x / [hostingScrollView bounds].size.width;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration 
{
    //  Layout changed instantly at this time.
    //  So we have to force to set offset instantly by setting animation to NO.
    [hostingScrollView setContentOffset:CGPointMake([hostingScrollView bounds].size.width * currentPageOffset, 0.0f) animated:NO];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文