我有一个有限区域的自定义地图,并将其设置为正确显示用户的位置。地图是UIScrollView中的1600px方形图像。
我有一个十字准线图像来显示用户的当前位置,在zoomScale 1.0处是所需的大小。当我捏合并缩放scrollView时,十字准线会随之缩放。我想让子视图在屏幕上保持相同的大小。
我无法找到关于此的任何信息,最好的方法是什么?
如果我能为您提供帮助,请告知我们。
非常感谢!
编辑 -
进一步研究了这个,我尝试使用UIScrollViewDelegate方法- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
来获取标记的当前中心和大小,然后进行调整,但这仅在缩放结束时进行缩放。我希望在用户缩放时让标记保持相同的大小。
编辑2 -
Cake在下面提供了一个很好的答案,但我无法以我想象的方式实现这一点。
我将UIImageView作为占位符,alpha设置为0.此占位符相对于地图移动以显示用户位置。这正如我所期望的那样运作。不幸的是,这会根据地图调整大小,因为它是地图的子视图(因此它会保留在原位)。
在下面的回答中,我创建了非缩放十字准线图像,并将其作为兄弟子视图添加到滚动视图中。一旦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:
和-scrollViewDidEndDecelerating:`)全部隐藏占位符,并重新显示十字准线。
答案 0 :(得分:3)
问题是陈旧但是对于未来类似的问题,我最近解决了一个类似的问题,应用了另一个帖子的Andrew Madsen的暗示。
我是一个UIScrollView,里面有一个UIImageView。附加到UIImageView我有很多MKAnnotationView(这些是我不想用superview缩放的子视图)。
我做了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
这完美无缺! 米克。
答案 1 :(得分:2)
创建另一个与包含scrollview的视图或视图控制器关联的十字准线图像。然后让这个总是捕捉到你已经拥有的十字准线图像的中心。然后,隐藏原始十字准线图像。然后你可以避免滚动视图缩放分离的十字准线,它应该保持相同的大小。
相对坐标系
cocoa touch中的每个视图都有一个具有原点的frame属性。为了相对于另一个视图正确定位一个视图所拥有的对象,您所要做的就是找出它们起源的差异。如果一个视图是另一个视图的子视图,那么这并不太难。
答案 2 :(得分:1)
斯威夫相当于米克的回答:
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
}
}
}
}