UIScrollView ImageView 顶部有针脚

发布于 2024-10-29 03:57:54 字数 1604 浏览 1 评论 0原文

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

因此,我选择将 Pins 添加到另一个视图,该视图位于 ImageView 之上,也是 UIScrollView 的子视图。如果您能想象,这里的想法是有一个图层悬停在地图上,并且不会缩放,但会在我绘制它们的位置显示图钉。

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

基本上,这是带有图钉的地点的自定义地图。我试图让 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];

我一直在尝试弄清楚如何让我的图钉在比例发生时悬停在地图上而不移动。

I have a UIScrollView which has a UIImageView. I want to show pins on this imageView. When I add pins as subviews of the ImageView, everything is great except for when you zoom the scale transform happens on the pins also. I don't want this behavior and want my pins to stay the same.

So I choose to add the Pins to another view which sits on top of the ImageView and is also a subview of the UIScrollView. The idea here if you will imagine is to have a layer which hovers over the map and won't scale yet show pins over where I plot them.

The pin when added to the layer view don't cale if the ImageView scales. However, the issue then becomes the position of the pins doesn't match the original origin x/y as the ImageView has had a scale transform.

Basically this is a custom map of a place with Pins. I am trying to have the Pins float over and not zoom in and out over my ImageView yet remember where I placed them when the zoom happens.

Some code:

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];

Code to add Pin later on some event.

[iconsView addSubview:pinIcon];

I am stuck in trying tp figure out how to to get my pins to hover on the map without moving when the scale happens.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

や莫失莫忘 2024-11-05 03:57:54

我喜欢您将所有引脚保留在专用于引脚的视图(iconsView)中的想法,但我决定将它们添加为您所谓的 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 中,将 pin 视图添加为 imageView 的子视图。将 imageView 作为子视图添加到滚动视图中。设置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;
}

I like your idea of keeping all the pins in a view dedicated to pins (iconsView), but I decided to just add them as subviews of what you called imageViewMap.

Import the QuartzCore.framework file to your project.

Call your view controller MyViewController.

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

// and so on

@implementation MyViewController

@synthesize scrollView;
@synthesize imageView;

I'll assume you have a pin view or a view controller called DropPinViewController. If you're just using an image, it can be a UIImageView, but my pins have labels, so I used a xib. The pin should point to the bottom center of the xib because we're going to put an anchor point there.

In your viewDidLoad of your MyViewController, add your pin views as subviews of imageView. Add the imageView as a subview to the scrollView. Set the content size of scrollView.

scrollView.delegate = self;

Use these delegate methods:

- (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;
}
冷弦 2024-11-05 03:57:54

因此,我已经实现的一件事并没有解决我的问题,但我认为它是正确的,来自这篇文章。

锚定 UIView

我的视图层次结构如下。

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

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

我有一个 for 循环,它遍历了所有作为 IconsView 的子视图的引脚,并更新了它们的原点 X 和 Y。这是在 UIScrollView 代表的 scrollViewDidScroll< /代码> 方法。

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

So one thing I have implemented which hasn't solved my issue but I think it's down the right path is from this article.

Anchor a UIView

I have my view hierarchy as follows.

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

The next step I need to solve is to keep my pins added to IconsView anchored in the same spot when the UIImageView is being zoomed in and out.

I had a for loop that went through all of my pins which are Subviews of IconsView and updated their Origin X and Y. This was in the UIScrollView delegates's scrollViewDidScroll method.

The problem was this technique has horrible performance on the device as when there are a lot of pins on the map there is too much processing that needs to happen.

淡淡的优雅 2024-11-05 03:57:54

一些建议:

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

巴尼

A few recommendations:

1) You will notice in the Google Maps application that it limits the number of pins that it tries to display by default. It will only display the results closest the the center point even if there are more possible matches.

2) You could briefly hide the pins during any scroll or pinch action so that the interface remains responsive and redraw them the moment the image view stops moving.

3) If you must display a large number of pins and animate them, you might also look into using CABasicAnimations to animate the pins and the backdrop at the same time, transforming the pins position using the same math that transforms the backdrops scale. This might smooth the display by spreading animations more smoothly and running them at a fairly low level, but introduces other challenges and limitations.

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

Barney

掩于岁月 2024-11-05 03:57:54

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

然而,它让我烦恼,这在 Google 地图应用程序中是可能的,但我无法重新创建它。

还有一件事:
当我向 UIScrollView 添加不是“viewForZoomingInScrollView”的子视图时,任何人都可以解释一下行为表现吗?例如:

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

这对于初始视图和平移时似乎效果很好。缩放时,这些子视图不会调整大小,这实际上是我们的目标,但问题是 UIView 框架原点以某种相当奇怪的方式在滚动视图上移动。看起来,如果放大,marker.frame.size.origin 总是向左上角(超级视图的 (0,0))移动,给人一种我们实际上正在缩小的印象。这也很奇怪,因为“缩放中心”应该始终位于屏幕的中心,不是吗?嗯,我暂时不明白。

撞。 ;)

I have the same problem and I find the idea of manually correcting the pin's location not very pretty. Then, I rather draw my pins onto the view returned in the delegate function viewForZoomingInScrollView: and update the subview (markers) size after zooming has finished.

However, it nags me that this is possible in the Google Maps App, but I can't recreate it.

One more thing:
Can anyone explain me the behaviour exhibitet when I add subviews to the UIScrollView that are not the 'viewForZoomingInScrollView'..? For example:

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

This seems to work fine for the initial view and when panning. When zooming, those subviews are not resized, which is actually what we are aiming for, but the problem is that the UIView frame origin is moved across the scroll view in some rather weird way. It appears that if one zooms in, the marker.frame.size.origin is always moving towards the upper left corner (superview's (0,0)), creating the impression that we are actually zooming out. This is also weird, because the "zoom center" should always be at the center of the screen, no? Well, I don't get it for now.

bump. ;)

嘿哥们儿 2024-11-05 03:57:54

感谢大卫·布劳恩。除了我必须注释掉的一行之外,您的代码可以正常工作。我的项目涉及有一个 UIScrollView,然后是顶部的 UIImageView,显示地图,最后,在感应到双击手势后固定代码所在的位置(按钮)。您的代码帮助我解释了缩放比例。但限制是,当我捏​​合缩放时,每个引脚不会“粘”到我双击的绘图的特定部分。当我注释掉这一行时,我偶然发现了解决方案:

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

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

Thanks to David Braun. Your code works except for one line that I had to comment out. My project involved having a UIScrollView, then a UIImageView on top that shows a map, then lastly, pins (buttons) that the code positions after sensing a double tap gesture. Your code helped me account for the zoom scale. The limitation though was that when I pinch to zoom, each pin does not "stick" to the specific part of the drawing where I double tapped. I stumbled on the solution when I commented out this line:

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

I don't have the complete understanding but my code now works! I hope others will benefit from my experience. Thanks David!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文