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)];
У меня нет полного понимания, но теперь мой код работает! Я надеюсь, что другие извлекут выгоду из моего опыта. Спасибо Дэвиду!