Как отобразить 2 строки текста для субтитров MKAnnotation и изменить изображение для кнопки справа?
Я рассматриваю пример Apple MapCallouts для аннотаций и выносок карт (== пузыри, которые появляются, когда вы нажимаете на булавку).
Каждая аннотация содержит координаты, название и субтитры.
Я хотел бы отобразить субтитры в 2 строках, я попытался с помощью:
- (NSString *)subtitle
{
return @"Founded: June 29, 1776\nSecond line text";
}
но текст "Текст второй строки" остается в одной строке и делает пузырь шире. Я получаю следующее:
![enter image description here]()
Я также хотел бы изменить изображение кнопки на один из моих, код, который устанавливает кнопку в настоящее время следующим образом:
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
Любые идеи?
EDIT: Я пробовал 7KV7 советов. Изменение кнопки происходит успешно, но я все еще не могу получить субтитры в 2 строках.
Мой код:
MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:BridgeAnnotationIdentifier] autorelease];
customPinView.pinColor = MKPinAnnotationColorPurple;
customPinView.animatesDrop = YES;
// Button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 23, 23);
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
//UIEdgeInsets titleInsets = UIEdgeInsetsMake(7.0, -20.0, 7.0, 7.0);
//button.titleEdgeInsets = titleInsets;
[button setImage:[UIImage imageNamed:@"ic_phone_default.png"] forState:UIControlStateNormal];
//[button setImage:[UIImage imageNamed:@"ic_phone_selected.png"] forState:UIControlStateSelected];
[button setImage:[UIImage imageNamed:@"ic_phone_selected.png"] forState:UIControlStateHighlighted];
[button addTarget:self action:@selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = button;
//two labels
UIView *leftCAV = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,50)];
//[leftCAV addSubview : button];
UILabel *l1=[[UILabel alloc] init];
l1.frame=CGRectMake(0, 15, 50, 50);
[email protected]"First line of subtitle";
l1.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)];
UILabel *l2=[[UILabel alloc] init];
l2.frame=CGRectMake(0, 30, 50, 50);
[email protected]"Second line of subtitle";
l2.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)];
[leftCAV addSubview : l1];
[leftCAV addSubview : l2];
customPinView.leftCalloutAccessoryView = leftCAV;
//customPinView.
customPinView.canShowCallout = YES;
return customPinView;
Я получаю это:
![enter image description here]()
Ответы
Ответ 1
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];
// Button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 23, 23);
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[button setImage:[UIImage imageNamed:yourImageName] forState:UIControlStateNormal];
[advertButton addTarget:self action:@selector(buttonPress:) forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = button;
// Image and two labels
UIView *leftCAV = [[UIView alloc] initWithFrame:CGRectMake(0,0,23,23)];
[leftCAV addSubview : yourImageView];
[leftCAV addSubview : yourFirstLabel];
[leftCAV addSubview : yourSecondLabel];
annotationView.leftCalloutAccessoryView = leftCAV;
annotationView.canShowCallout = YES;
return pin;
}
UPDATE
Стиль аннотаций по умолчанию поддерживает только заголовок и субтитры. Ни заголовок, ни субтитры не могут включать разрывы строк. Вы не можете сделать это без подкласса.
Чтобы использовать пользовательский просмотр обзора Пример кода Apple:
http://developer.apple.com/library/ios/#samplecode/WeatherMap/Introduction/Intro.html
Я также думаю, что в вашем коде есть проблема
UILabel *l1=[[UILabel alloc] init];
l1.frame=CGRectMake(0, 15, 50, 50);
[email protected]"First line of subtitle";
l1.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)];
UILabel *l2=[[UILabel alloc] init];
l2.frame=CGRectMake(0, 30, 50, 50);
[email protected]"Second line of subtitle";
l2.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)];
[leftCAV addSubview : l1];
[leftCAV addSubview : l2];
l1 имеет раму (0, 15, 50, 50), а l2 имеет (0, 30, 50, 50). Не будут ли эти два совпадения? Я имею в виду, что l1 начнется с y = 15, а его высота будет равна 50. Поэтому, когда l2 начинается с 30, он может перекрываться. Можете ли вы проверить PLS, изменив фреймы
Ответ 2
PLZ использовать это
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if ([annotation isKindOfClass:[CustomAnnotation class]]) {
CustomAnnotation *customAnnotation = (CustomAnnotation *) annotation;
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomAnnotation"];
if (annotationView == nil)
annotationView = customAnnotation.annotationView;
else
annotationView.annotation = annotation;
//Adding multiline subtitle code
UILabel *subTitlelbl = [[UILabel alloc]init];
subTitlelbl.text = @"sri ganganagar this is my home twon.sri ganganagar this is my home twon.sri ganganagar this is my home twon. ";
annotationView.detailCalloutAccessoryView = subTitlelbl;
NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:subTitlelbl attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:150];
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:subTitlelbl attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
[subTitlelbl setNumberOfLines:0];
[subTitlelbl addConstraint:width];
[subTitlelbl addConstraint:height];
return annotationView;
} else
return nil;
}
![введите описание изображения здесь]()
Ответ 3
Так я достиг этого без подкласса представления аннотации или использования недокументированных API:
MKAnnotationView* pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
// Add a custom view to the the callout to allow mutli-line text
UIView *calloutView = [[UIView alloc] initWithFrame:CGRectMake(0, 10, 250, 250)];
UIView *calloutViewHeight = [[UIView alloc] initWithFrame:CGRectMake(0, 10, 1, 250)]; // The reason for this will become apparent below
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 250, 21)];
[title setText:<<your single-line title text>>];
[calloutView addSubview:title];
UILabel *subtitle = [[UILabel alloc] initWithFrame:CGRectMake(10, 35, 250, 250)];
[subtitle setNumberOfLines:0];
[subtitle setText:<<your multi-line title text>>];
CGSize subtitleSize = [subtitle sizeThatFits:CGSizeMake(250, 250)];
[subtitle setFrame:CGRectMake(10, 35, 250, subtitleSize.height)];
[calloutView addSubview:subtitle];
[calloutView setFrame:CGRectMake(0, 10, 250, 35+subtitleSize.height+10)];
[calloutViewHeight setFrame:CGRectMake(0, 0, 1, 35+subtitleSize.height+10)];
pinView.leftCalloutAccessoryView = calloutView;
pinView.rightCalloutAccessoryView = calloutViewHeight; // The height of the callout is calculated by the right accessory *not* the left, so this fake view is required
Вы можете настроить шрифт/цвет текста, отрегулировав соответственно title
и subtitle
.
Уверен, это немного взломан, но он добивается желаемых результатов без подкласса и позволяет вам настраивать любые дополнительные кнопки/изображения, которые вы хотите добавить calloutView
(и вы все равно можете поместить кнопки вправо -accessory view, если хотите, до тех пор, пока вы сохраняете высоту).
Ответ 4
Две строки в выноске не могут быть выполнены, не попадая в неподдерживаемые API. Если вы это сделаете, ваше приложение будет отклонено.
Если у вас есть iPad, вы можете увидеть пример настраиваемой выноски. Их выноска преобразуется в всплывающее представление, которое привязывается к местоположению карты так же, как и к выноску. Возможно, в следующей версии iOS Apple расширит API выносок. На данный момент вы застряли в одной строке субтитров.
Если вы действительно хотите это сделать, вам нужно будет создать свой собственный класс выносок и заставить его придерживаться карты по мере ее прокрутки. Это, вероятно, будет сложно.
Другая идея - подделка выноски. Создайте собственный аннотационный вид, содержащий 2 представления. Первый - это вывод карты. Второй - это выноска. Когда штифт получает прикосновение, вы можете отобразить вид выноски. Он будет пропускать анимацию "поп", но вы можете поместить столько строк, сколько хотите.
Я никогда не пробовал это, и кажется, что будет много деталей, чтобы получить право, но это может дать вам начало.
Ответ 5
Для установки кнопки вы можете использовать приведенный ниже код
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *x=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"someIdentifier"];
UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
//set the target, title, image etc.
[x setRightCalloutAccessoryView:button];
return [x autorelease];
}
Ответ 6
Вы не сможете сделать это с помощью общедоступного API и вам придется переопределить свой собственный аннотационный вид.
Вы можете взглянуть на этот код, который обновляет представление аннотации, но имитирует стандартный iOS, и вы можете затем обогатить его для своей собственной потребности:
http://blog.asolutions.com/2010/09/building-custom-map-annotation-callouts-part-1/
Ответ 7
Изображение результатов
Это решение устанавливает "обоснованный" текст, надеюсь, будет полезно:
Swift 3:
import MapKit
extension MKAnnotationView {
func setCustomLines(customLines lines: [String]) {
if lines.count <= 0 {
return
}
// get longest line
var longest = NSString()
if let max = lines.max(by: { $1.characters.count > $0.characters.count }) {
longest = max as NSString
}
else {
fatalError("Can't get longest line.")
}
// get longest text width
let font = UIFont.systemFont(ofSize: 15.0)
let width = (longest.size(attributes: [NSFontAttributeName: font])).width
// get text from lines
var text = lines.first
for i in 1..<lines.count {
text = text! + " " + lines[i]
}
// label
let label = UILabel()
label.text = text
label.font = font
label.numberOfLines = lines.count
label.textAlignment = .justified
// set width of label
let con = NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: width)
label.addConstraint(con)
self.detailCalloutAccessoryView = label
}
}