1

我有一个有限区域的自定义地图,并将其设置为正确显示用户的位置。该地图是 UIScrollView 内的 1600 像素方形图像。

我有一个十字准线图像来显示用户的当前位置,在 zoomScale 1.0 是所需的大小。当我捏和缩放滚动视图时,十字准线会随之缩放。我想让子视图在屏幕上保持相同的大小。

我一直无法找到有关此的任何信息,最好的方法是什么?

如果有什么我可以为您提供帮助的答案,请告诉我。

非常感谢!

编辑 -

进一步研究后,- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale我尝试使用 UIScrollViewDelegate 方法来获取标记的当前中心和大小,然后进行调整,但这只会在缩放结束时缩放。我希望在用户缩放时让标记保持相同的大小。

编辑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:-scrollViewDidEndDecelerating:`)都隐藏占位符,并重新显示十字准线。

4

3 回答 3

4

这个问题很老,但对于未来的类似问题,我最近解决了一个类似的问题,应用了另一篇帖子的 Andrew Madsen 的提示。

我有一个 UIScrollView,里面有一个 UIImageView。附加到 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

这完美!米克。

于 2013-10-17T09:52:47.020 回答
2

创建另一个与包含滚动视图的视图或视图控制器关联的十字准线图像。然后让这个总是捕捉到你已经拥有的十字准线图像的中心。然后,隐藏您的原始十字准线图像。然后你可以避免让滚动视图缩放不相关的十字准线,它应该保持相同的大小。

相对坐标系

可可触摸中的每个视图都有一个具有原点的框架属性。为了相对于另一个视图正确定位一个视图所拥有的对象,您所要做的就是找出它们起源的差异。如果一个视图是另一个视图的子视图,那么这并不太难。

  • 获取容器视图的来源
  • 获取容器视图内子视图的位置
  • 获取子视图的来源
  • 计算原点位置的差异
  • 获取要重叠的对象的位置(相对于子视图)
  • 计算要重叠的对象相对于容器视图的位置
  • 将你的十字准线移动到这个位置
于 2012-06-22T19:25:13.183 回答
1

Mick 的答案的 Swift 等价物:

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
            }
        }
    }
}
于 2016-06-16T11:25:53.393 回答