
所以我有一个简化的ViewController示例,它重现了这个行为,我似乎不能理解它。我正在使用一个带有一些代码的UIPanGestureRecognizer,这些代码正确地允许UIView在窗口中移动。但是,如果我更新框架,甚至更新到它本身,视图会跳转到一个意外的位置,大概是基于视图的中心。
关于这段代码,我有两个问题。首先,为什么视图的中心是最后一次触摸的位置(基本上anchorPoint映射到视图的边界),而显然与视图框架的中心没有任何关系?
其次,为什么将frame属性更改为当前值时,视图会移动?在我看来,视图的中心和框架只是部分相关,我不确定我错过了什么。
这个例子只是在应用委托中创建了一个基本的测试视图控制器:
TestViewController *vc = [[TestViewController alloc] init];
self.window.rootViewController = vc;TestViewController.m:
#import "TestViewController.h"
#import <QuartzCore/QuartzCore.h>
@implementation TestViewController
- (void)loadView
{
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 748)];
self.view.backgroundColor = UIColor.redColor;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onPan:)];
pan.maximumNumberOfTouches = 1;
[self.view addGestureRecognizer:pan];
}
- (void)onPan:(UIPanGestureRecognizer*)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan) {
UIView *view = recognizer.view;
CGPoint locationInView = [recognizer locationInView:view];
CGPoint locationInSuperview = [recognizer locationInView:view.superview];
view.layer.anchorPoint = CGPointMake(locationInView.x / view.bounds.size.width, locationInView.y / view.bounds.size.height);
view.center = locationInSuperview;
}
if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [recognizer translationInView:[recognizer.view superview]];
[recognizer.view setCenter:CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y+translation.y)];
[recognizer setTranslation:CGPointZero inView:[recognizer.view superview]];
}
if(recognizer.state == UIGestureRecognizerStateEnded) {
NSLog(@"AnchorPoint: %@", NSStringFromCGPoint(self.view.layer.anchorPoint));
NSLog(@"Center: %@", NSStringFromCGPoint(self.view.center));
NSLog(@"Frame: %@", NSStringFromCGRect(self.view.frame));
self.view.frame = self.view.frame;
}
}
@end当平移手势结束时,如果我删除以下行,则平移将按预期工作:
self.view.frame = self.view.frame;我真的不明白这条线怎么会导致视图四处移动,除非之前的center属性没有“完全粘合”或其他什么。此外,我不理解center属性的值,因为它似乎是最后接触到的位置,而根本不是视图的中心。示例日志:
AnchorPoint: {0.204427, 0.748506}
Center: {625, 218.5}
Frame: {{14, -34}, {768, 1004}}从长远来看,我试图在这里实现的是一个可以缩放的视图,但当滚动到边缘之外时,它会弹回(就像UIScrollView一样)。
发布于 2013-05-05 11:05:07
如果您删除这两行
view.layer.anchorPoint = CGPointMake(locationInView.x / view.bounds.size.width, locationInView.y / view.bounds.size.height);
view.center = locationInSuperview;然后,您的视图平移行为如您所期望的那样。你为什么要改变图层的锚点呢?一般来说,对于您试图实现的目标而言,您的代码似乎过于复杂了。请参阅David Rönnqvist,understanding the anchor point,了解更改锚点对视图框架属性的影响(通常是意外的)。
此外,离开顶层视图(视图控制器的self.view)并操作子视图通常是一个好主意。这样,您就可以知道所有内容与viewController的视图之间的关系,而不需要知道UIWindow发生了什么。旋转设备时,会将旋转变换应用于该顶级视图,这在检查帧数据时没有帮助。它的子视图的属性不受该转换的影响。
您的代码在未转换的纵向模式下的行为与您期望的一样,并且只有在横向或纵向颠倒时才会抛出奇怪的结果。以下是应用了旋转变换的视图的情况。Apple说,当转换应用到视图时,框架的原点属性是未定义的,所以当您这样做时:
self.view.frame = self.view.frame您正在分配处于未定义状态的属性。期待意想不到的事情。
您可以更改视图加载代码,如下所示:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView* subview = [[UIView alloc] initWithFrame:
CGRectMake(0, 0
, self.view.bounds.size.width
, self.view.bounds.size.height)];
[self.view addSubview:subview];
subview.backgroundColor = UIColor.redColor;
[subview setAutoresizingMask:UIViewAutoresizingFlexibleWidth
|UIViewAutoresizingFlexibleHeight];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:@selector(onPan:)];
pan.maximumNumberOfTouches = 1;
[subview addGestureRecognizer:pan];
}这里我们没有覆盖-loadView,让它自动创建顶级视图,然后在viewDidLoad中实现一个子视图。现在,您的测试应用程序运行正常。
https://stackoverflow.com/questions/16234631
复制相似问题