我面临着一个非常奇怪的问题 - 至少对我来说 - 而且看起来我快要疯了:) 我有一个 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)。
有什么想法吗? 如果您需要更多说明,请告诉我。
编辑: UIView
和 UIImageView
都是同一父级 UIView
的子级 - 它们是在我创建其布局的 .xib 文件中,未相互“连接”。
最佳答案
就您的情况而言,我们确定 AutoLayout 是罪魁祸首。
要禁用它,请取消选中此框:
自动布局破坏框架更改的原因很大程度上是由于它使用 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/