设置视图的框架并转换另一个视图 - 奇怪的行为

时间:2014-06-20 15:56:25

标签: ios objective-c uiview

我面临一个非常奇怪的问题 - 至少对我而言 - 似乎我疯了:) 我有一个UIView,我添加了一个UIPanGestureRecognizer,以便能够在屏幕上垂直移动它;这是我做的代码:

- (id)init {

    // ...
    UIPanGestureRecognizer *gestureRecognizerPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesturePan:)];
    [self.viewMenuProper addGestureRecognizer:gestureRecognizerPan];

    imageArrowOriginalFrame = self.imageArrow.frame;
    // ...
}

说UIView,self.viewMenuProper,应该可以向屏幕底部拖动​​(并朝向默认位置向后移动)。在屏幕正上方放置一个UIImageView,其顶边的位置和宽度是为了保持它们的值,但它的高度应该根据self.viewMenuProper的位置而改变,这样它似乎连接了那个UIView即使UIView被移动,屏幕顶部还有一些点。

所以这是处理手势的方法:

- (void)handleGesturePan:(UIPanGestureRecognizer *)gestureRecognizerPan {

    if (gestureRecognizerPan.state == UIGestureRecognizerStateBegan) {

        gesturePanPreviousY = [gestureRecognizerPan locationInView:self].y;
    }
    else if (gestureRecognizerPan.state == UIGestureRecognizerStateChanged) {

        float gesturePanCurrentY = [gestureRecognizerPan locationInView:self].y;
        float gesturePanDeltaY = gesturePanCurrentY - gesturePanPreviousY;

        float imageArrowFrameNewHeight = self.imageArrow.frame.size.height + gesturePanDeltaY;

        if (imageArrowFrameNewHeight <= 200 && imageArrowFrameNewHeight >= imageArrowOriginalFrame.size.height) {

            [self.imageArrow setFrame:CGRectMake(imageArrowOriginalFrame.origin.x, imageArrowOriginalFrame.origin.y, imageArrowOriginalFrame.size.width, imageArrowFrameNewHeight)]; // line A
        }

        // Check if the transformed View won't be too far up any way of the screen
        float gesturePanNewY = self.viewMenuProper.transform.ty + gesturePanDeltaY;

        if (gesturePanNewY <= 200 && gesturePanNewY > 0) {

            [self.viewMenuProper setTransform:CGAffineTransformTranslate(self.viewMenuProper.transform, 0, gesturePanDeltaY)]; // line B
        }

        gesturePanPreviousY = gesturePanCurrentY;
    }
    // The below animates the Views back to their default positions
    else if (gestureRecognizerPan.state == UIGestureRecognizerStateEnded || gestureRecognizerPan.state == UIGestureRecognizerStateFailed || gestureRecognizerPan.state == UIGestureRecognizerStateCancelled) {

        [UIView animateWithDuration:1.0 animations:^{

            [self.viewMenuProper setTransform:CGAffineTransformIdentity];
            // NOTE: the below line prevents the animation from jumping wrong way 1st before animating the way it should
            // http://stackoverflow.com/questions/12535647/uiview-animation-jumps-at-beginning
            [self layoutIfNeeded];
        }];

        self.imageArrow.frame = imageArrowOriginalFrame;
    }
}

现在这不起作用:viewMenuProper移动得很好但imageArrow仅在前一个位于其最远位置而不再移动时伸展。如果我注释掉A行(看看上面的代码),那么B行工作正常;同样,如果我注释掉B行,那么A行就可以了。但是当它们都被取消注释时,就像我写的那样:imageArrow并没有像预期的那样延伸。

有什么想法吗? 如果您需要更多说明,请告诉我。

修改UIViewUIImageView都是同一父母UIView的子女 - 他们之间没有“相互关联”我创建布局的.xib文件。

1 个答案:

答案 0 :(得分:1)

在你的情况下,正如我们所确定的,AutoLayout是罪魁祸首。

要禁用它,请取消选中此框:

enter image description here

AutoLayout破坏您的框架更改的原因很大程度上是由于它使用了constraints。当您创建一个开箱即用的控件时,iOS会自动将其当前帧转换为足够的约束,以满足元素的不明确定位。

想象一下,你有一个视图,你已经定位在上/下。如果您添加了一个约束,表示它始终是50pt到50pt,并且触摸左上角和右下角,则最终会出现断裂约束。

相反,想象一下你根本没有赋予元素任何约束:iOS必须猜测你想要它的位置。在你的情况下,你正在翻译控件的框架,但是当“假设”约束到位时,他们告诉控件它在错误的位置,因此试图将其移回。

调用和更新autolayout的方法是:

[myView setNeedsLayout]; // Tells your view that it needs to be laid out again
[self.view layoutIfNeeded]; // Tells the view to update its constraints if they've changed

幸运的是,在您的情况下,您可以禁用AutoLayout并开始一天的活动!不幸的是,如果你决定实际使用 AutoLayout(创建约束和自动调整大小元素),如果你想操纵帧等,你就会遇到更复杂的任务。通常,您可能会发现为约束创建IBOutlet会很有帮助 - 这样您就可以通过编程方式更新约束。