IOS 8 MKAnnotationView rightCalloutAccessoryView смещен
Я все еще довольно новичок в iOS в целом и нашел проблему при тестировании нашего приложения для совместимости с iOS 8.
В iOS 7 все работало нормально, но в iOS 8 rightCalloutAccessoryView смещается при определенных обстоятельствах.
Первый снимок экрана: Правильно выровненный ![Correctly aligned]()
Вторая скриншот: неправильное выравнивание ![Wrong alignment]()
Как вы можете видеть, проблема возникает, когда InfoWindow имеет длинный заголовок. Но это не относится к iOS 7, и я не мог найти ничего, что могло бы измениться?
Я попытался понять, почему и найти способ решить эту проблему, но ничего не смог найти.
Является ли это решаемым самостоятельно или мы должны подать вопрос Apple?
Любая помощь/идеи будет высоко оценена, поскольку я как-то переусердствовал с этой проблемой.
Код, который добавляет MKAnnotationViews
- (MKAnnotationView *)viewForStation:(id<MKAnnotation>)annotation {
static NSString *stationIdentifier = @"stao";
MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:stationIdentifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:stationIdentifier];
annotationView.image = [UIImage bundleImageNamed:PIN_IMAGE];
annotationView.canShowCallout = YES;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
return annotationView;
}
Как вам может быть интересно, я (сейчас) также добавил этот вопрос в раздел iOS 8 Beta на apple.developer.com: https://devforums.apple.com/thread/242282?tstart=0
Если я получу ответ либо здесь, либо на apple.developer.com, я отражу его, чтобы мы могли найти его на обоих сайтах.
Ответы
Ответ 1
Я решил это, установив маску autoresizing для исправления вертикальной ошибки и frame.size.width для горизонтальной ошибки
UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton setFrame:CGRectMake(0, 0, CGRectGetWidth(infoButton.frame)+10, CGRectGetHeight(infoButton.frame))];
[infoButton setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleTopMargin];
[annotationView setRightCalloutAccessoryView:infoButton];
Ответ 2
Ужасно, как черт, но мне удалось найти обходной путь к этой проблеме.
Установите высоту вид аксессуара равным высоте представления выноски. Я использовал жестко заданные значения:
- для целей iOS 7: 45.0 px
- для целей iOS 8: 54.0 px
(Вероятно, вы заметили, что высота объявления по умолчанию для аннотации больше в iOS 8, чем в iOS 7).
В вашем коде это будет:
- (MKAnnotationView *)viewForStation:(id<MKAnnotation>)annotation {
static NSString *stationIdentifier = @"stao";
MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:stationIdentifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:stationIdentifier];
annotationView.image = [UIImage bundleImageNamed:PIN_IMAGE];
annotationView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
// N.B. In production code, you would need a more generic way to adjust
// height values instead of hard-coding values based on NSFoundationVersionNumber...
CGFloat height = (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) ? 55.f : 45.f;
detailButton.frame = CGRectMake(0.f, 0.f, 32.f, height);
annotationView.rightCalloutAccessoryView = detailButton;
}
return annotationView;
}
Кроме того, из того, что я видел до сих пор, если вы укажете как левый, так и правый аксессуар, вам нужно будет установить их высоту на одно и то же значение, чтобы получить правильное выравнивание. Надеюсь, эта проблема будет исправлена в последующих версиях iOS, чтобы избежать написания такого кода...
Ответ 3
Привет, у меня была такая же проблема, вот что я сделал для ее решения:
Кажется, что проблема с представлением Callout имеет проблемы с отображением текста заголовка MKAnnotation, когда он слишком длинный. Даже с вашего скриншота вы можете видеть, что проблема возникает только тогда, когда заголовок усечен и добавлен многоточие. Таким образом, стандартная MKAnnotation не закладывает взгляды должным образом, и это ошибка в iOS8.
В то же время вы можете создать свою собственную выноску, выполнив следующие шаги здесь.
Я думал, что это слишком много для того, что мне нужно, поэтому я просто подрезал строку заголовка и добавлял многоточие, чтобы он не пытался сделать сам. (Не идеально, но это быстрое решение, и текст будет усечен в любом случае)
if (locTitle.length > 15)
{
locTitle = [NSString stringWithFormat:@"%@...", [locTitle substringToIndex:14]];
}
Ответ 4
Одно любопытство, которое я заметил, это то, что моя первая выверка, которая будет отображаться, правильно выравнивает виды аксессуаров, но последующие выборы не будут. Я добавил вызов [view setNeedsLayout]
до возвращения просмотренного аннотационного представления, и все снова стало правильно выравниваться.
Не тратя больше времени на это, я думаю, что повторная компоновка не запускается для представления, которое было отменено, поскольку иерархия представления не изменилась.
Я настоятельно рекомендую представить радар для этой проблемы. Нет необходимости применять обходные пути для такого стандартного варианта использования.
EDIT:
Хотя во многих случаях это все еще лучше, я все еще сталкиваюсь с этой проблемой с аннотациями, название которых достаточно длинное, чтобы быть усеченным.
Ответ 5
Пока что Im скрывает rightCalloutAccessoryView с
pin.rightCalloutAccessoryView.frame = CGRectZero;
и нажмите "Просмотр аннотаций", все еще работающий, без кнопки справа.
Протестировано на iOS7 и iOS8, не уверен в iOS6.
Ответ 6
Я получил свою работу, установив свой делегат с отображением карты до добавления аннотации и не должен ничего менять в del.
Переход от следующего:
self.mapView = [[MKMapView alloc] init];
NGAAnnotation *annotation = [[NGAAnnotation alloc] init];
annotation.coordinate = coordinates;
annotation.title = self.project.name;
[self.mapView addAnnotation:annotation];
self.mapView.delegate = self;
To:
self.mapView = [[MKMapView alloc] init];
NGAAnnotation *annotation = [[NGAAnnotation alloc] init];
annotation.coordinate = coordinates;
annotation.title = self.project.name;
self.mapView.delegate = self;
[self.mapView addAnnotation:annotation];
Исправлено это для меня. Я заметил, что метод делегата вызывается при добавлении аннотации, поэтому если делегат не задан перед добавлением аннотации, он не будет вызван.
Ответ 7
В Swift 3:
let infoButton = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = infoButton