我有一个有限区域的自定义地图,并将其设置为正确显示用户的位置。这张地图是一张1600像素的正方形图像,位于UIScrollView中。
我有一个十字线图像来显示用户的当前位置,缩放比例1.0是所需的大小。当我捏缩放滚动视图时,十字线会随之缩放。我希望子视图在屏幕上保持不变。
我找不到任何关于这方面的信息,最好的方法是什么?
如果我能为你提供什么帮助,请告诉我。
非常感谢!
编辑-
进一步研究后,我尝试使用一个UIScrollViewDelegate方法- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
来获取标记的当前中心和大小,然后进行调整,但这只会在缩放结束时缩放。我更希望在用户缩放时标记保持不变。
编辑2-
Cake在下面提供了一个很好的答案,但我还没能像我想象的那样实现它
我将UIImageView作为占位符,alpha设置为0。此占位符相对于地图移动以显示用户位置。这是我所期望的操作。不幸的是,它会随着地图而调整大小,因为它是地图的子视图(所以它保持不变(。
根据Cake下面的答案,我创建了非缩放十字线图像,并将其作为同级子视图添加到滚动视图中。一旦Cake指出了这些问题,数学计算就非常简单,可以得到十字准线的新框架:
CGPoint ULPC = userLocationPlaceholder.center;
float zs = scrollView.zoomScale;
CGRect newFrame = CGRectMake(((ULPC.x * zs) - scrollView.contentOffset.x) - 20, ((ULPC.y * zs) - scrollView.contentOffset.y) - 20, 40, 40);
图像宽度为40点。这与中锋完美匹配。
我现在遇到的问题是,我无法将十字线图像锁定到占位符。
我已经尝试过使用这样的自调用动画:
-(void)animeUserLocationAttachment
{
[UIView animateWithDuration:0.05
delay:0
options:(UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear )
animations:^{
userLocationDotContainer.frame = newFrame;
} completion:^(BOOL finished){
// Call self
[self animateUserLocationAttachment];
}];
}
当我开始滚动/缩放时,这会锁定动画,使十字线保持原位,直到我释放滚动/缩放,然后它会正确更新它的位置。
有什么办法可以绕过这一点,或者我可以应用其他方法吗?
非常感谢
编辑3-
我重新接受了Cake的回答,因为它涵盖了90%的问题。除了他的回答之外,我还实现了ScrollViewDelegate方法scrollViewWillBeginDragging:
和scrollViewWillBeginDecelerating:
来缩放占位符以匹配相对于地图的十字线的当前大小,显示占位符(即地图图像的子视图(并隐藏十字线图像。委托方法scrollviewWillBeginZooming:withView:
不显示占位符,因为它随映射而缩放。正如Cake所推荐的,我将为本期提出一个新问题。
对应的方法(scrollViewDidEndZooming:withView:atScale:
、scrollViewDidEndDragging:willDecelerate:
和-scollViewDidEndDecelerating:`(都隐藏占位符,并重新显示十字线。
这个问题很老,但对于未来类似的问题,我最近利用另一篇文章中Andrew Madsen的提示解决了一个类似的问题
我有一个UIScrollView,里面有一个UI图像视图。在UIImageView的附件中,我有很多MKAnnotationView(这些是我的子视图,我不想用超视图缩放(。
我做了UIImageView的子类,并实现了setTransform:
方法,如下所示:
#import "SLImageView.h"
@implementation SLImageView
- (void)setTransform:(CGAffineTransform)transform
{
[super setTransform:transform];
CGAffineTransform invertedTransform = CGAffineTransformInvert(transform);
for (id obj in self.subviews)
{
if ([obj isKindOfClass:[MKAnnotationView class]])
{
[((UIView *)obj) setTransform:invertedTransform];
}
}
}
@end
这非常有效!米克。
创建与包含滚动视图的视图或视图控制器关联的另一个十字线图像。然后让这个始终捕捉到你已经拥有的十字线图像的中心。然后,隐藏原始十字线图像。然后,您可以避免滚动视图缩放已解除关联的十字线,并且它应该保持相同的大小。
相对坐标系
可可触摸中的每个视图都有一个具有原点的框架属性。为了使一个视图所拥有的对象相对于另一个视图正确定位,您所要做的就是找出它们起源的差异。如果一个视图是另一个视图的子视图,那么这并不太难。
- 获取容器视图的原点
- 获取子视图在容器视图中的位置
- 获取子视图的原点
- 计算原点位置的差异
- 获取要重叠的对象的位置(相对于子视图(
- 计算要重叠的对象相对于容器视图的位置
- 将十字准线移动到此位置
Swift等价于Mick的答案:
class MapContainerView:UIView {
@IBOutlet var nonScalingViews: [UIView]!
override var transform: CGAffineTransform {
didSet {
guard let nonScalingViews = nonScalingViews else {
return
}
let invertedTransform = CGAffineTransformInvert(transform)
for view in nonScalingViews {
view.transform = invertedTransform
}
}
}
}