UIScrollView ImageView с булавками сверху

У меня есть UIScrollView, у которого есть UIImageView. Я хочу показать контакты на этом imageView. Когда я добавляю булавки в качестве подзонов imageView, все отлично, за исключением того, что при масштабировании масштабное преобразование также происходит на выводах. Я не хочу этого поведения и хочу, чтобы мои контакты остались прежними.

Итак, я решил добавить Pins в другое представление, которое находится поверх ImageView, а также является подзаголовком UIScrollView. Идея здесь, если вы предполагаете, состоит в том, чтобы слой, который нависает над картой и не будет масштабировать, покажет булавки над тем, где я их рисую.

Штырек, добавленный в вид слоя, не заливается, если масштабирование imageView. Тем не менее, проблема тогда становится позицией контактов не соответствует исходному происхождению x/y, поскольку imageView имеет масштабное преобразование.

В основном это настраиваемая карта места с контактами. Я пытаюсь, чтобы булавки плавали и не увеличивали и уменьшали масштаб изображения по сравнению с моим 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];

Я застрял в попытке выяснить, как заставить мои контакты наводить курсор на карте, не двигаясь, когда происходит масштаб.

Ответ 1

Мне нравится ваша идея держать все контакты в представлении, посвященном контактам (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;

Предполагаю, что у вас есть представление с булавкой или контроллер вида, называемый DropPinViewController. Если вы просто используете изображение, это может быть UIImageView, но мои контакты имеют метки, поэтому я использовал xib. Штырь должен указывать на нижний центр xib, потому что мы собираемся разместить там опорную точку.

В вашем viewDidLoad вашего MyViewController добавьте ваши представления булавки в виде подсмотров изображения. Добавьте образViewView в качестве подсмотра в 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 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;
}

Ответ 2

Итак, одна вещь, которую я выполнил, которая не решила мою проблему, но я думаю, что это правильный путь из этой статьи.

Якорь UIView

У меня есть иерархия моего представления следующим образом.

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

Следующий шаг, который мне нужно решить, - сохранить мои контакты в IconsView, закрепленные в том же месте, когда UIImageView будет увеличен и уменьшен.

У меня был цикл for, который прошел через все мои контакты, которые являются Subviews из IconsView, и обновил их Origin X и Y. Это было в методе UIScrollView delegates scrollViewDidScroll.

Проблема заключалась в том, что этот метод имел ужасную производительность на устройстве, так как при наличии большого количества контактов на карте слишком много обработки, которая должна произойти.

Ответ 3

Несколько рекомендаций:

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

Барни

Ответ 4

У меня такая же проблема, и я нахожу идею ручной коррекции местоположения булавки не очень красивой. Затем я скорее нарисую свои контакты на представлении, возвращенном в функции делегата viewForZoomingInScrollView:, и обновит размер subview (markers) после завершения масштабирования.

Однако, мне кажется, что это возможно в приложении Google Maps, но я не могу его воссоздать.

Еще одна вещь: Может ли кто-нибудь объяснить мне поведение, когда я добавляю subviews в UIScrollView, которые не являются "viewForZoomingInScrollView"..? Например:

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

Кажется, что это нормально для начального вида и при панорамировании. При масштабировании эти подпункты не изменяются, что на самом деле является тем, к чему мы стремимся, но проблема в том, что начало кадра UIView перемещается по экрану прокрутки каким-то довольно странным образом. Похоже, что если один масштабируется, marker.frame.size.origin всегда движется в верхний левый угол (супервизор (0,0)), создавая впечатление, что мы фактически уменьшаем масштаб. Это также странно, потому что "центр масштабирования" всегда должен находиться в центре экрана, нет? Ну, я пока не понимаю.

врезаться.;)

Ответ 5

Благодаря Дэвиду Брауну. Ваш код работает, за исключением одной строки, которую я должен был прокомментировать. Мой проект включал в себя UIScrollView, а затем UIImageView сверху, который показывает карту, а затем, булавки (кнопки), которые позиционируют код после распознавания жестов двойного касания. Ваш код помог мне рассчитать масштаб масштабирования. Однако ограничение заключалось в том, что когда я щелкаю, чтобы увеличить, каждый вывод не "прилипает" к определенной части чертежа, где я дважды постучал. Я наткнулся на решение, когда я прокомментировал эту строку:

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

У меня нет полного понимания, но теперь мой код работает! Я надеюсь, что другие извлекут выгоду из моего опыта. Спасибо Дэвиду!