地図の操作自体は公式でしっかり解説されてて、移行することはいっぱいあるけど、そんなに大変じゃない感じ。
Pinの外観を変えたい
これは公式に書いてないが、下記のやり方でいけました!ありがたや!
https://vladislavantonyuk.github.io/articles/Customize-map-pins-in-.NET-MAUI/
あと、CreateMauiAppの修正でちょっとはまった。
UseMauiMaps→ConfigureMauiHandlersの順が大事っぽい。
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
// Mapを利用する
.UseMauiMaps()
// カスタム用レンダラーを利用する
.UseMauiCompatibility()
#if ANDROID
// Android用クラスインスタンスで生成
.UseMauiApp<Droid.HogeAppDroid>()
// Activityインスタンスを渡す
.ConfigureLifecycleEvents(events =>
{
events.AddAndroid(android => android
.OnCreate((activity, bundle) => Droid.HogeAppDroid.OnCreate(activity, bundle))
);
})
// Android用カスタムコントロールのレンダラーを登録
.ConfigureMauiHandlers((handlers) =>
{
handlers.AddHandler(typeof(Microsoft.Maui.Controls.Maps.Map), typeof(Droid.CustomMapHandler));
})
#elif IOS
// iOS用クラスインスタンスで生成
.UseMauiApp<iOS.HogeAppIOS>()
// iOS用カスタムコントロールのレンダラーを登録
.ConfigureMauiHandlers((handlers) =>
{
handlers.AddHandler(typeof(Microsoft.Maui.Controls.Maps.Map), typeof(iOS.CustomMapHandler));
})
#endif
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
ただ、後からラベルだけ変えるとかはできないっぽい?
変えたきゃPinのインスタンスごと作り直せばいける。
移動は表示してから?
位置の移動処理を実装しておいても、エラーにはならないけど、map.IsVisible = Falseの状態だとAndroidは効果がなかった。
プロパティの変更イベントハンドラを実装して、map.IsVisibleがTrueに変更されたら、別スレッドで1秒ほど待機→移動って処理にして回避。なんでや。
住所情報
以前は文字列で1発でとれたけど、Placemarkクラスの各プロパティを連結する必要がある。
これがAndroidとiOSでもかなり取れ方が違うっぽい。
Androidは同じ情報が複数プロパティに反映されがち。
分けて実装する必要がありそうだった。
/// <summary>
/// 住所更新(ラベル)
/// </summary>
private async Task UpdateAddress( Location pos)
{
string address = "";
// 住所文字処理
try
{
// 住所文字列の取得
IEnumerable<Placemark> addresses = await Geocoding.Default.GetPlacemarksAsync(pos.Latitude, pos.Longitude);
Placemark placemark = addresses?.FirstOrDefault();
// 結果をとる。
if (placemark != null)
{
// AndroidとiOSで結果が異なるので作り方もわける
// 郵便番号はいらない
if (!string.IsNullOrEmpty(placemark.CountryName))
{
// 国名はつける(日本だけ削除)
address = placemark.CountryName.Replace("日本", "");
}
OID
// 郵便番号はいらない
address += placemark.AdminArea // 都道府県
+ placemark.Locality // 市区町村
+ placemark.SubLocality // サブの局所性
+ placemark.Thoroughfare; // 町名
// 丁目
// 四国の海だとCountryNameとFeatureNameに"日本"が設定されて、他のプロパティは空なので
// AdminAreanoの空チェックも行う
if (!string.IsNullOrEmpty(placemark.AdminArea) && !string.IsNullOrEmpty(placemark.SubThoroughfare))
{
// 数字が連結されるならハイフンを挟む
if (IsIntParseOneChar(address, false) && IsIntParseOneChar(placemark.SubThoroughfare, true))
{
address += "‐";
}
address += placemark.SubThoroughfare;
}
// 号
if (!string.IsNullOrEmpty(placemark.AdminArea) && !string.IsNullOrEmpty(placemark.FeatureName))
{
// 数字が連結されるならハイフンを挟む
if (IsIntParseOneChar(address, false) && IsIntParseOneChar(placemark.FeatureName, true))
{
address += "‐";
}
address += placemark.FeatureName;
}
address += placemark.AdminArea // 都道府県
+ placemark.Locality // 市区町村
+ placemark.Thoroughfare; // 町名&丁目
// 番地以降
// 四国の海だとCountryNameとFeatureNameに"日本"が設定されて、他のプロパティは空なので
// AdminAreanoの空チェックも行う
if (!string.IsNullOrEmpty(placemark.AdminArea) && !string.IsNullOrEmpty(placemark.SubThoroughfare))
{
// 数字が連結されるならハイフンを挟む
if (IsIntParseOneChar(address, false) && IsIntParseOneChar(placemark.SubThoroughfare, true))
{
address += "‐";
}
address += placemark.SubThoroughfare;
}
// FeatureNameはSubLocality、Thoroughfare、SubThoroughfareがnullの場合
if (string.IsNullOrEmpty(placemark.SubLocality) && string.IsNullOrEmpty(placemark.Thoroughfare) &&
string.IsNullOrEmpty(placemark.SubThoroughfare) && !string.IsNullOrEmpty(placemark.FeatureName))
{
// 数字が連結されるならハイフンを挟む
if (IsIntParseOneChar(address, false) && IsIntParseOneChar(placemark.FeatureName, true))
{
address += "‐";
}
address += placemark.FeatureName;
}
}
}
catch (Exception ex)
{
DebugLog.Log(ex.Message);
address = "";
}
// ピンを作り直してラベルに住所反映したり・・・
}
/// <summary>
/// 数字始まりまたは数字終わりかチェック
/// </summary>
/// <param name="str">チェックする文字列</param>
/// <param name="isFirst">先頭をチェックするならtrue、末尾ならfalse</param>
/// <returns>数字であればtrue</returns>
private bool IsIntParseOneChar(string str, bool isFirst)
{
// 空ならfalse
if (string.IsNullOrEmpty(str))
{
return false;
}
// 先頭または末尾1文字をチェック
string check = "";
if (isFirst)
{
check = str.Substring(0, 1);
}
else
{
check = str.Substring(str.Length - 1, 1);
}
// Strings.StrConv(check, VbStrConv.Narrow, 0)は使えないので半角に置き換えは手作業で行う
check = check.Replace("0", "0").Replace("1", "1").Replace("2", "2").Replace("3", "3").Replace("4", "4")
.Replace("5", "5").Replace("6", "6").Replace("7", "7").Replace("8", "8").Replace("9", "9");
// 判定
return int.TryParse(check, out _);
}
他にもニッチなIT関連要素をまとめていますので、よければ一覧記事もご覧ください。