问题 UIScrollView ImageView顶部有针脚


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

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

添加到图层视图时的引脚如果不是cale 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];

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


10109
2018-06-27 01:34


起源



答案:


我喜欢你将所有引脚保存在专用于引脚(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;
}

9
2017-12-02 03:25



这太棒了我有点生病了。我有许多其他复杂的方法来做到这一点......这么简单。我切换到这个并且效果很好。 - malaki1974
好戏。您可以通过在自己的视图上使用引脚并缩放其坐标来执行类似的操作。不知道那是否会有更多或更少的表现。 - Bob Spryn


答案:


我喜欢你将所有引脚保存在专用于引脚(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;
}

9
2017-12-02 03:25



这太棒了我有点生病了。我有许多其他复杂的方法来做到这一点......这么简单。我切换到这个并且效果很好。 - malaki1974
好戏。您可以通过在自己的视图上使用引脚并缩放其坐标来执行类似的操作。不知道那是否会有更多或更少的表现。 - Bob Spryn


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

锚定一个UIView

我的视图层次结构如下。

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

我需要解决的下一步是保持我的引脚添加 IconsView 当时停泊在同一个地方 UIImageView 正在放大和缩小。

我有一个for循环,遍历我的所有引脚,这是Subviews的 IconsView 并更新了他们的Origin X和Y.这是在 UIScrollView 代表的 scrollViewDidScroll 方法。

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


3
2018-06-28 01:27





一些建议:

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

巴尼


0
2017-07-08 11:13





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

但是,它让我觉得这可以在Google Maps App中实现,但我无法重新创建它。

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

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

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

磕碰。 ;)


0
2018-04-13 01:08





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

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

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


0
2018-02-01 16:15