在导航控制器上方添加放大镜
目标:获得一个 UIView,它是一个小放大镜,放置在导航控制器上方。它就像 Notes 程序中的放大镜一样。
我使用以下代码部分完成了此任务:
MyAppDelegate *app = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[[[[app navigationController] view] superview] addSubview:_loupe];
这允许放大镜显示在导航控制器上方。注意: _loupe 变量包含一个将放大视图的 UIView 实例。
该代码在纵向模式下完美运行。然而,当我将方向更改为横向时,放大镜的坐标似乎仍处于纵向模式。
经过大量的试验、错误和数小时的敲头,我意识到作为应用程序的 rootViewController 添加的 UINavigationController 在方向改变时永远不会更新其坐标。所有其他视图,包括 RootViewController(在 XCode 中创建新应用程序时创建的默认类)都已更新其坐标。
我试图通过用我自己的控制器子类化 UINavigationController 来纠正这个问题,以便导航控制器而不是 RootViewController 调用 shouldAutorotateToInterfaceOrientation: 。我希望它不旋转的原因是因为它不是控制器请求方向。没有什么。
我还使用以下内容旋转了 _loupe 视图:
CGAffineTransform transform = _loupe.transform;
transform = CGAffineTransformMakeRotation([self degreesToRadians:90.0]);
_loupe.transform = transform;
_loupe.bounds = CGRectMake(0, 0, 480, 320);
_loupe.frame = CGRectMake(0, 0, 80, 80);
这使得触摸下方的 UIView 右侧向上放大。最初,当向左更改方向时,下面的 UIView 旋转了 -90 度。所以我就快到了...但坐标仍然搞砸了。
我还尝试将 _loupe.bounds 更改为 CGRectMake(0, 480, 480, 320) 相信更改原点可能与底层坐标系匹配。没有骰子。
我的最后一招是对实际的 UITouch x/y 点进行转换。
CGPoint point = [touch locationInView:self];
CGAffineTransform transform = CGAffineTransformRotate([_loupe transform], [self degreesToRadians:90.0]);
CGPoint tPoint = CGPointApplyAffineTransform(point, transform);
没有骰子。但是,这确实会使放大镜显示在可见区域附近。我发现在 x 轴上移动触摸会在 y 轴上移动放大镜,在 y 轴上移动触摸会在 x 轴上移动放大镜。所以现在完全颠倒过来了。
简而言之,我只是想要一种简单的方法来在导航控制器上方显示放大镜,而不需要所有这些繁琐的内容。
编辑
通过将点转换为放大镜的视图,我离得更近了一点。
CGPoint tPoint = [self convertPoint:point toView:_loupe];
这使得放大镜闪烁很多...它似乎还同时在 x 和 x 上移动放大镜。 y 轴(垂直),无论我向哪个方向移动触摸。不过越来越近了!
Objective: To get a UIView, which is a small magnifying glass, to be placed above the navigation controller. It's exactly like the loupe in the Notes program.
I have partly accomplished this task with the following code:
MyAppDelegate *app = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[[[[app navigationController] view] superview] addSubview:_loupe];
This allows the loupe to be displayed above the navigation controller. Note: The _loupe variable contains an instance of a UIView that will magnify the view.
This code works perfectly when in Portrait. When I change the orientation to Landscape, however, the coordinates of the _loupe appear to still be in portrait mode.
Through lots of trial and error and hours of head banging I realized that the UINavigationController, which is added as the rootViewController of the application, never updates its coordinates when the orientation changes. ALL other views, including the RootViewController (the default class created when creating a new application in XCode) has their coordinates updated.
I tried to rectify this by subclassing the UINavigationController with my own controller to make it so the shouldAutorotateToInterfaceOrientation: gets called by the navigation controller instead of the RootViewController. I was hoping that the reason it didn't rotate is because it wasn't the controller requesting the orientation. Nothing.
I've also rotated the _loupe view with the following:
CGAffineTransform transform = _loupe.transform;
transform = CGAffineTransformMakeRotation([self degreesToRadians:90.0]);
_loupe.transform = transform;
_loupe.bounds = CGRectMake(0, 0, 480, 320);
_loupe.frame = CGRectMake(0, 0, 80, 80);
This makes the UIView, underneath the touch, magnified right side up. Originally, the UIView underneath was rotated -90 when changing the orientation to the left. So I'm almost there... but the coordinates are still screwed up.
I've also tried changing the _loupe.bounds to CGRectMake(0, 480, 480, 320) believing that changing the origin might match the underlying coordinate system. No dice.
My last resort was doing a transform on the actual UITouch x/y points.
CGPoint point = [touch locationInView:self];
CGAffineTransform transform = CGAffineTransformRotate([_loupe transform], [self degreesToRadians:90.0]);
CGPoint tPoint = CGPointApplyAffineTransform(point, transform);
No dice. However, this does make the loupe displayed near the visible area. What I'm finding is that moving the touch on the x axis moves the loupe on the y axis and moving the touch on the y axis moves the loupe on the x axis. So now it's completely inverted.
In short, I just want an easy way to display a magnifying glass above the navigation controller without all of this rigmarole.
Edit
I got a little closer by converting the point to the loupe's view.
CGPoint tPoint = [self convertPoint:point toView:_loupe];
This makes the loupe flicker a lot... it also appears to move the loupe on both the x & y axis (vertically) no matter the direction I move the touch. Getting much closer though!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
解决方案
就是这样:
我所要做的就是将从 UITouch 事件创建的 CGPoint 转换为导航控制器的超级视图(放大镜属于其中的一部分)的坐标空间。
Resolution
This is it:
All I had to do was convert the CGPoint, created from the UITouch event, to that of the coordinate space of the navigation controller's superview (which the loupe is part of).