繁体   English   中英

泛码更新中心后,UIView框架和中心是否不相关?

[英]UIView frame and center not correlated after pan code updates center?

在此处输入图片说明

因此,我得到了一个精简的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一样)。

如果删除这两行

    view.layer.anchorPoint = CGPointMake(locationInView.x / view.bounds.size.width, locationInView.y / view.bounds.size.height);
    view.center = locationInSuperview;

然后,您的视图平移将达到您的预期。 为什么仍要更改图层的定位点? 通常,您要实现的代码看起来过于复杂。 请参阅DavidRönnqvist, 了解锚点了解如何更改锚点会对视图的帧属性产生(通常是意外的)影响。

此外,通常最好不要self.view顶级视图(视图控制器的self.view )并操作子视图。 这样,您就知道一切都与viewController的视图相关联,而不必怀疑UIWindow的状况。 旋转设备时,旋转变换将应用于该顶层视图,这在检查框架数据时无济于事。 子视图的属性不受该转换的影响。

您的代码在未转换的纵向模式下的行为与预期的一样,并且仅在横向或纵向倒置时会抛出奇怪的结果。 在这些情况下,视图已应用旋转变换。 苹果公司说,将变换应用于视图后,框架的origin属性是未定义的,因此在执行此操作时:

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实现一个子视图。 现在,您的测试应用程序可以正常运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM