マップの注釈とコールアウト(==ピンをクリックすると表示されるバブル)について、AppleのMapCalloutsの例を見ています。そこにあるすべての注釈には、座標、タイトル、サブタイトルがあります。字幕を2行で表示したいのですが、試してみました:
- (NSString *)subtitle
{
return @"Founded: June 29, 1776\nSecond line text";
}
しかし、「2行目のテキスト」というテキストは1行のままで、バブルを広くします。
また、ボタンの画像を自分のものに変更したいのですが、ボタンを設定するコードは現在次のようになっています。
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
何か案は?
編集:私は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);
l1.text=@"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);
l2.text=@"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;
私はこれを得る:
- (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;
}
[〜#〜]更新[〜#〜]
注釈のデフォルトのスタイルは、タイトルとサブタイトルのみをサポートします。タイトルにもサブタイトルにも改行を含めることはできません。サブクラス化せずにこれを行うことはできません。
カスタムビューを使用するには、Appleのサンプルコードを確認してください。
http://developer.Apple.com/library/ios/#samplecode/WeatherMap/Introduction/Intro.html
また、コードに問題があると思います
UILabel *l1=[[UILabel alloc] init];
l1.frame=CGRectMake(0, 15, 50, 50);
l1.text=@"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);
l2.text=@"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)があります。これらの2つは重複しませんか?つまり、l1はy = 15から始まり、その高さは50です。したがって、l2が30から始まると、オーバーラップする可能性があります。フレームを変更して確認できますか?
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;
}
これは、注釈ビューをサブクラス化せずに、または文書化されていない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
を追加したい追加のボタン/画像でカスタマイズできます(ボタンを右側に配置することもできます) -必要に応じて、高さを保持している限り、アクセサリビュー)。
サポートされていないAPIを使用せずに、コールアウトの2行を実行することはできません。これを行うと、アプリは拒否されます。
IPadをお持ちの場合は、カスタマイズされたコールアウトの例を見ることができます。それらのコールアウトはポップアウトビューに変換され、コールアウトと同じ方法でマップの場所に固定されます。したがって、iOSの次のバージョンでは、AppleがコールアウトAPIを拡張する可能性があります。今のところ、1行の字幕で立ち往生しています。
本当にこれを実行したい場合は、独自のコールアウトクラスを作成し、スクロール時にマップに固定する必要があります。これはおそらく難しいでしょう。
別のアイデアは、コールアウトを偽造することです。 2つのビューを含むカスタム注釈ビューを作成します。 1つ目はマップピンです。 2つ目はコールアウトです。ピンがタッチされると、コールアウトビューを再表示できます。 「ポップ」アニメーションはありませんが、好きなだけ行を入れることができます。
私はこれを試したことがなく、正しく理解するための詳細がたくさんあるように思えますが、それはあなたに出発点を与えるかもしれません。
ボタンの設定には、以下のコードを使用できます
- (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];
}
それは9つのステップで行うことができます。
ラベルを作成し、それをannotationView?.detailCalloutAccessoryView
プロパティに追加しました(ステップ5)。また、ラベルのテキストをannotation.subtitle
テキストに設定します(ステップ2とステップ4)。ラベルの.numberOfLines = 0
を設定しました。これにより、必要な行数に応じてサブタイトルが拡張されます(2つだけ必要な場合は2に設定します)。
ボタンのUIButtonを作成し、そのタイプを.detailDisclosure
に設定しました(ステップ7)。次に、ボタンのimageプロパティを使用するカスタム画像に設定します(手順8)。そして最後に、ボタンをannotationViewの.rightCalloutAccessoryView
プロパティに設定しました(ステップ9)。
また、annotationViewの.calloutOffset
プロパティをオフセットします(ステップ6)。 レイ・ヴェンダーリッヒからオフセットを取得しました
手順はコードの上のコメントにあります
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKindOfClass(MKUserLocation) {
return nil
}
let reuseIdentifier = "reuseIdentifier"
var annotationView = mapView.mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
// 1. set the annotationView's canShowCallout property to true
annotationView?.canShowCallout = true
// 2. get the subtitle text from the annontation's subtitle property
let subtitleText = annotation.subtitle ?? "you have no subtitle"
// 3. create a label for the subtitle text
let subtitleLabel = UILabel()
subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
// 4. set the subtitle's text to the label's text property and number of lines to 0
subtitleLabel.text = subtitleText
subtitleLabel.numberOfLines = 0
// 5. set the annotation's detailCalloutAccessoryView property to the subtitleLabel
annotationView?.detailCalloutAccessoryView = subtitleLabel
// 6. offset the annotationView's .calloutOffset property
annotationView?.calloutOffset = CGPoint(x: -5, y: 5)
// 7. create a button and MAKE SURE to set it's type to .detailDisclosure or it won't appear
let button = UIButton(type: .detailDisclosure)
// 8. set the button's image to whatever custom UIImage your using
button.setImage(UIImage(named: "yourCustomImage"), for: .normal)
// 9. set the button to the annotationView's .rightCalloutAccessoryView property
annotationView?.rightCalloutAccessoryView = button
} else {
annotationView!.annotation = annotation
}
return annotationView
}
このソリューションは「正当化された」テキストを設定します。役立つことを願っています。
スウィフト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
}
}
パブリックAPIでそれを行うことはできず、独自のカスタムアノテーションビューを再実装する必要があります。
アノテーションビューを再実装するが、標準のiOSビューを模倣するこのコードを見ることができます。その後、必要に応じてコードを強化できます。
http://blog.asolutions.com/2010/09/building-custom-map-annotation-callouts-part-1/