最近項(xiàng)目中遇到這樣一個(gè)問題:
生成一張圖片按鈕,然后在圖片父控件中拖拽.給圖片添加一個(gè)pan手勢(shì),但發(fā)現(xiàn)在默認(rèn)拖拽過程中,子控件可以超出父控件范圍
而同事寫的安卓版本子控件不超出父控件范圍,因?yàn)榘沧磕J(rèn)這樣.產(chǎn)品經(jīng)理要求與他保持一致
我的辦法是:
實(shí)時(shí)獲取子控件在父控件的坐標(biāo),并判斷子控件的 x, y 是否超過父控件的范圍,如果超過則讓其停止拖拽
但遇到一個(gè)問題:
當(dāng)拖拽速度比較慢時(shí)可以實(shí)現(xiàn)那個(gè)效果,當(dāng)拖動(dòng)比較快時(shí)會(huì)感覺到拖拽卡頓. 原因是拖拽和 獲取子,控件坐標(biāo)并判斷方法 都是在主線程中執(zhí)行的.后來 把獲取子控件坐標(biāo)并判斷方法放在子線程中執(zhí)行再回到主線程判斷是否停止拖拽
雖然解決了問題,但是感覺太過于麻煩
最近在github上看別人代碼時(shí),無意中發(fā)現(xiàn)了更好的辦法 -- 使用自動(dòng)布局,給子控件添加約束(這里我使用 了Masonry框架),通過約束來改變子控件坐標(biāo)而不是通過仿射變換來實(shí)現(xiàn)
注意:不要通過設(shè)置控件的transform屬性值或者直接設(shè)置子控件的frame屬性值(例如center)來讓空間位移,否則拖動(dòng)時(shí)子控件還是會(huì)超出父控件的
之前在拖拽子控件代碼是
- (void)pan:(UIPanGestureRecognizer *)panGesture{
UIView *button = panGesture.view;
button.transform = CGAffineTransformTranslate(button.transform, [panGesture translationInView:panGesture.view].x, [panGesture translationInView:panGesture.view].y);
[panGesture setTranslation:CGPointZero inView:panGesture.view];
}
或是
- (void)pan:(UIPanGestureRecognizer *)panGesture{
UIView *button = panGesture.view;
CGPoint point = [panGesture translationInView:button];
CGPoint newCenter = CGPointMake(point.x + button.center.x, point.y + button.center.y);
button.center = newCenter;
[panGesture setTranslation:CGPointZero inView:button];
}
只有通過自動(dòng)布局約束才能實(shí)現(xiàn)效果:
1. 先在子控件在創(chuàng)建時(shí)設(shè)置約束來控制其拖拽范圍
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(40, 40));
make.right.lessThanOrEqualTo(button.superview);
make.left.greaterThanOrEqualTo(button.superview);
make.top.greaterThanOrEqualTo(button.superview).offset(64);
make.bottom.right.lessThanOrEqualTo(button.superview);
}];
2. 在拖拽方法里使用約束更新子控件的坐標(biāo)
- (void)pan:(UIPanGestureRecognizer *)panGesture{
UIView *button = panGesture.view;
CGPoint newCenter = CGPointMake([panGesture translationInView:button].x + button.center.x - button.superview.bounds.size.width / 2, + button.center.y + [panGesture translationInView:button].y - button.superview.bounds.size.height / 2);
[button mas_updateConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(newCenter).priorityLow();
}];
[panGesture setTranslation:CGPointZero inView:panGesture.view];
}
運(yùn)行效果:
3.注意: 這種方法還是有局限性,當(dāng)子控件調(diào)用transform屬性放大或縮小時(shí)這種方法失效
- 子控件調(diào)用transform屬性放大時(shí): 子控件拖拽范圍會(huì)超出父控件
- 子控件調(diào)用transform屬性縮小時(shí): 子控件拖拽范圍會(huì)縮小