UIScrollView ImageView顶部有引脚

时间:2009-06-27 01:34:08

标签: iphone mapping uiscrollview zooming

我的UIScrollView有一个UIImageView。我想在此imageView上显示引脚。当我将引脚添加为ImageView的子视图时,一切都很棒,除了缩放时,引脚上的比例变换也会发生。我不希望这种行为,并希望我的引脚保持不变。

所以我选择将Pins添加到位于ImageView顶部的另一个视图,也是UIScrollView的子视图。如果你想象的话,这里的想法是有一个悬浮在地图上的图层,并且不会缩放,而是在我绘制它们的地方显示引脚。

如果ImageView缩放,则添加到图层视图中的图钉不会进行裁剪。然而,问题变成了引脚的位置与原始原点x / y不匹配,因为ImageView已经进行了比例变换。

基本上这是一个带有Pins的地方的自定义地图。我试图让Pins漂浮而不是放大和缩小我的ImageView,还记得我在放大时放置它们的位置。

一些代码:

scrollView = [[UIScrollView alloc] initWithFrame:viewRect];

scrollView.delegate = self;
scrollView.pagingEnabled = NO;
scrollView.scrollsToTop = NO;
[scrollView setBackgroundColor:[UIColor clearColor]];
scrollView.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollView.bounces = YES;
scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;

imageViewMap = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image.png"]];

imageViewMap.userInteractionEnabled = YES;

viewRect = CGRectMake(0,0,imageViewMap.image.size.width,imageViewMap.image.size.height);

//viewRect = CGRectMake(0,0,2976,3928);

[scrollView addSubview:imageViewMap];

[scrollView setContentSize:CGSizeMake(viewRect.size.width, viewRect.size.height)];

iconsView = [[UIView alloc] initWithFrame:imageViewMap.frame];

[scrollView addSubview:iconsView];

稍后在某些事件上添加Pin的代码。

[iconsView addSubview:pinIcon];

我陷入困境,试图弄明白如何让我的别针悬停在地图上,而不会在尺度发生时移动。

5 个答案:

答案 0 :(得分:9)

我喜欢你将所有引脚保存在专用于引脚(iconView)的视图中的想法,但我决定将它们添加为你所谓的imageViewMap的子视图。

将QuartzCore.framework文件导入项目。

调用视图控制器MyViewController。

#import <QuartzCore/QuartzCore.h>
@interface MyViewController : UIViewController <UIScrollViewDelegate>
@property (retain) UIScrollView *scrollView;
@property (retain) UIImageView *imageView;

//等等

@implementation MyViewController

@synthesize scrollView;
@synthesize imageView;

我假设你有一个pin视图或一个名为DropPinViewController的视图控制器。如果您只是使用图像,它可以是UIImageView,但我的图钉有标签,所以我使用了一个xib。引脚应该指向xib的底部中心,因为我们要在那里放置一个锚点。

在MyViewController的viewDidLoad中,将引脚视图添加为imageView的子视图。将imageView作为子视图添加到scrollView。设置scrollView的内容大小。

scrollView.delegate = self;

使用这些委托方法:

- (void)scrollViewDidZoom:(UIScrollView *)aScrollView
{   
    for (UIView *dropPinView in imageView.subviews) {       
    CGRect oldFrame = dropPinView.frame;
    // 0.5 means the anchor is centered on the x axis. 1 means the anchor is at the bottom of the view. If you comment out this line, the pin's center will stay where it is regardless of how much you zoom. I have it so that the bottom of the pin stays fixed. This should help user RomeoF.
   [dropPinView.layer setAnchorPoint:CGPointMake(0.5, 1)];
    dropPinView.frame = oldFrame;
    // When you zoom in on scrollView, it gets a larger zoom scale value.
    // You transform the pin by scaling it by the inverse of this value.
    dropPinView.transform = CGAffineTransformMakeScale(1.0/scrollView.zoomScale, 1.0/scrollView.zoomScale);
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return imageView;
}

答案 1 :(得分:3)

所以我实施的一件事并没有解决我的问题,但我认为这是正确的道路来自本文。

Anchor a UIView

我的视图层次结构如下。

UIScrollView
 - UIImageView (map image)
 - IconsView (layer image to hold icons)

我需要解决的下一步是在IconsView放大和缩小时,将我的引脚添加到UIImageView锚定在同一位置。

我有一个for循环遍历我的所有引脚,这些引脚是IconsView的子视图并更新了它们的原点X和Y.这是在UIScrollView代理人的scrollViewDidScroll方法中。 / p>

问题是这种技术在设备上的性能很糟糕,因为地图上有很多引脚需要进行太多的处理。

答案 2 :(得分:0)

一些建议:

1)您将在Google地图应用程序中注意到它默认限制了它尝试显示的引脚数。即使有更多可能的匹配,它也只会显示最接近中心点的结果。

2)您可以在任何滚动或捏合动作期间短暂隐藏引脚,以便界面保持响应并在图像视图停止移动时重绘它们。

3)如果你必须显示大量的引脚并为它们设置动画,你可能还会考虑使用CABasicAnimations同时为引脚和背景设置动画,使用相同的数学运算来转换引脚位置以转换背景比例。这可以通过更平滑地传播动画并以相当低的水平运行它们来平滑显示,但是引入了其他挑战和限制。

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Animation_Types_Timing/Articles/PropertyAnimations.html#//apple_ref/doc/uid/TP40006672-SW1

巴尼

答案 3 :(得分:0)

我有同样的问题,我发现手动修正引脚位置的想法不是很漂亮。然后,我宁愿将我的引脚绘制到委托函数viewForZoomingInScrollView:中返回的视图上,并在缩放完成后更新子视图(标记)大小。

但是,我觉得这可以在谷歌地图应用程序中使用,但我无法重新创建它。

还有一件事: 当我向UIScrollView添加不是'viewForZoomingInScrollView'的子视图时,有人能解释我的行为展示吗?例如:

UIImageView* marker = [[UIImageView alloc] initWithImage: myMarkerImage];
[marker setCenter: CGPointMake(250,150)];
[myScrollView addSubview: marker];

这似乎适用于初始视图和平移时。缩放时,这些子视图不会调整大小,这实际上是我们的目标,但问题是UIView框架原点以某种相当奇怪的方式在滚动视图中移动。似乎如果放大,marker.frame.size.origin总是向左上角移动(超视图的(0,0)),从而产生我们实际缩小的印象。这也很奇怪,因为“变焦中心”应该始终位于屏幕的中心,不是吗?好吧,我现在还不知道。

磕碰。 ;)

答案 4 :(得分:0)

感谢David Braun。你的代码工作,除了我必须注释掉的一行。我的项目包括一个UIScrollView,然后在顶部显示一个地图的UIImageView,最后是感知双击手势后代码定位的引脚(按钮)。您的代码帮我解释了缩放比例。但是限制是当我捏缩放时,每个引脚都不会“粘住”我双击的图形的特定部分。当我评论这一行时,我偶然发现了解决方案:

// [dropPinView.layer setAnchorPoint:CGPointMake(0.5,1)];

我没有完全理解,但我的代码现在有效!我希望其他人能从我的经验中受益。谢谢大卫!