我试图通过将UILabel
附加到UIPanGestureRecognizer
并随后更改常量来使用户能够在视图中上下移动UILabel
从UILabel
到其视图顶部的约束。所以基本上如果手势识别器检测到它们向下移动12pts,移动约束12pts的常量来移动UILabel
。
但是,我希望它们在达到某个垂直点(太高或太低)时停止进一步移动。我可以检查平移手势的翻译,但我的UILabel
可以是任意数量的行,所以如果它是五行而不是一行,显然它不能被平移下来远,所以我不能依赖平移手势的翻译,我必须考虑到标签的大小。
所以我开始监视它的框架,它运行良好,但在我的实现中有一个令人讨厌的结果,如果它们完全达到最低限度,它们必须在{{1 "赶上"并附带它(虽然当它们到达顶部边界时不存在这样的问题)。基本上,他们平移到最低限度,当他们向后平移时(这一切都是在同一个手势中),它会坚持下去"一会儿,直到它们向上飞得很远,然后用手指跳起来。
以下是我用来完成此操作的代码:
UILabel
我到底做错了什么会导致它"坚持"?是否有更好的方法可以做到这一点?
答案 0 :(得分:2)
您可以完全使用在Interface Builder或代码中定义的约束来完成此操作。诀窍是定义约束,防止标签移出优先级高于设置所需位置的约束的边界。
在我的测试项目中,我完全在故事板中设置了一个视图层次结构,其中1)视图控制器视图2)“容器视图”,它定义了边界3)多行UILabel。从容器中对标签有6个约束:
4'空间到'约束(前导,尾随,顶部,底部)阻止标签定位在其父容器的边界之外。这些优先级在Interface Builder中设置为默认的“1000”值。这些约束的关系是'> =',常数值是'0'。
2'空间到'约束(前导,顶部)驱动标签的实际位置。这些优先级设置较低;我选择'500'。这些约束在视图控制器中有出口,因此可以在代码中进行调整。这些约束的关系是'=',初始值是您想要定位标签的任何值。
标签本身有一个宽度约束,强制它显示多行。
以下是IB中的情况:
所选约束的优先级较低,用于驱动标签的x位置。此约束与视图控制器中的ivar绑定,因此可以在运行时进行调整。
所选约束具有更高的优先级,用于在其父视图中标记标签。
以下是视图控制器中的代码:
@interface TSViewController ()
@end
@implementation TSViewController
{
IBOutlet NSLayoutConstraint* _xLayoutConstraint;
IBOutlet NSLayoutConstraint* _yLayoutConstraint;
}
- (IBAction) pan: (UIGestureRecognizer*) pgr
{
CGPoint p = [pgr locationInView: self.view];
p.x -= pgr.view.frame.size.width / 2.0;
p.y -= pgr.view.frame.size.height / 2.0;
_xLayoutConstraint.constant = p.x;
_yLayoutConstraint.constant = p.y;
}
@end
UIPanGestureRecognizer
与UILabel关联,并将其回调设置为视图控制器中的pan:方法。
答案 1 :(得分:1)
如果您的应用具有最低SDK iOS7,则可以使用UIKit Dynamics而不是UIGestureRecognizer。使用UICollisionBehavoir结合UIAttachmentBehavior可以轻松解决您的问题
你可能想要调查一下。这是UIKit Dynamics上的苹果示例项目: https://developer.apple.com/library/IOS/samplecode/DynamicsCatalog/Introduction/Intro.html
玩弄它,你会惊讶于你能用这么少的代码做什么。
WWDC 2013会议: - UIKit Dynamics入门 - 使用UIKit Dynamics的高级技术