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

标签 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 仅当前一个位于最远位置且不再移动时才会拉伸(stretch)。如果我注释掉 A 行(看一下上面的代码),那么 B 行就可以正常工作;同样,如果我注释掉 B 行,那么 A 行就可以正常工作。但是当它们都被取消注释时,就像我写的那样:imageArrow 不会像预期那样拉伸(stretch)。

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

编辑: UIViewUIImageView 都是同一父级 UIView 的子级 - 它们是在我创建其布局的 .xib 文件中,未相互“连接”。

最佳答案

就您的情况而言,我们确定 AutoLayout 是罪魁祸首。

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

enter image description here

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

假设您有一个位于顶部/左侧的 View 。如果您添加了一个约束,规定它始终必须为 50pt x 50pt,并且触摸左上角和右下角,那么您最终会遇到破坏约束。

相反,假设您根本不给某个元素任何约束:iOS 必须猜测您想要它在哪里。在您的情况下,您正在翻译控件的框架,但是在“假定”约束到位的情况下,它们告诉控件它位于错误的位置,因此尝试将其移回原处。

调用和更新自动布局的方法有:

[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(创建约束和自动调整元素大小),如果您想要操作框架等,您将面临更复杂的任务。很多时候,您可能会发现为约束创建 IBOutlet 很有帮助 - 通过这种方式,您可以以编程方式更新约束。

关于ios - 设置 View 框架并转换另一个 View - 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24331248/

相关文章:

ios - 估算iOS应用在应用商店中的大小

ios - UIScrollView页面负方向

ios - 应用程序本地化显示键而不是 iOS 中的值

iphone - 从 UITabbarItem 和 Storyboard 创建 UIViewController

objective-c - 以编程方式创建 UIView 和 UIViewController 并链接在一起的正确方法

ios - JSQ消息反馈定制

ios - 由 UITableView 制作的下拉按钮不重叠按钮

ios - 自定义 AppDelegate,添加 ViewController 属性,然后设置该属性 : unrecognized selector sent to instance 0x16574320

ios - 如何将图像旋转 360 度两次?

ios - Swift:表格单元格出现一秒钟然后消失