Xamarin.Forms から MAUI への移行するときに踏んだ罠集
Xamarin.Forms.Visual.Material の代替が無い。
これは Xamarin.Forms.Visual.Material が依存していた Material Components for iOS がメンテナンスモードに移行したため。
Android 版くらいはあってもよい気もするが、Backlog 行きにされているため望み薄。
初期の Style をすべて剝がしたら Android のバージョンに対応した Material Design になっているような気がする。
Xamarin.CommunityToolkit の後継ライブラリ、CommunityToolkit.Maui に ImageResourceExtension が実装されていない。
これは MAUI で追加されたビルドアクション MauiImage で代替できる。
どうしても必要な場合は↓に実装がある。
DependencyService<T>.Get()
時に例外。
Dependency
属性による自動登録が MAUI では実装されていない?ため。
MauiApplication.CreateMauiApp()
や MauiUIApplicationDelegate.CreateMauiApp()
内で DependencyService.Register<T>()
などを使用して手動登録することで解決。
Application
属性がどうのこうのでビルド失敗。
MauiApplication
を継承したクラスとは別に [assembly: Application]
属性が付いているから。
[assembly: Application]
を削除すれば解決。
6.0.547 (SR7) 現在、Android で Frame や BoxView の透明度が反映されない。
VS2022 17.4.2 現在、以下のような XAML を書くと Environment は MAUI プロジェクトでサポートされていません。
というような警告が出る。
ビルドは通るし実行も問題なくできるのでおそらく VS のバグ。
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="A" />
<Span Text="{Static x:Environment.NewLine}" />
<Span Text="B" />
</FormattedString>
</Label.FormattedText>
</Label>
この例の場合 

で改行しろと言われると、それはそうとしか言えない。
6.0.547 (SR7) 現在、XAML の ResourceDictionary に同じ TargetType が指定された暗黙のスタイルが複数存在すると、実行時に無言でクラッシュする?要調査&バグ報告。
6.0.547 (SR7) 現在、Android で CollectionView が信じられないくらい遅い。2桁件数でも平気で数秒プチフリーズする。
CollectionView.ItemSizingStrategy を MeasureFirstItem に設定してもまだ重い。
BindableLayout でも同程度フリーズするので CollectionView だけの問題ではなさそう。
またプチフリーズ中何度も GC が走っているのも気になる。
回避策は無いが ObservableColection に 1 件 Add しては await Task.Yield()
すれば一応そういうアニメーションみたいに見えるので、それでお茶を濁す必要があるか。
MAUI では StartAndExpand, CenterAndExpand, EndAndExpand, FillAndExpand は非推奨な上、Xamarin.Forms と異なる挙動をする場合がある。
これらは StackLayout でしか効果がない割にほとんどのコントロールが持っていて混乱を招いていたとのこと。
Grid で代替して欲しいそう。
6.0.547 (SR7) 現在、Android で Picker に任意の文字を入力できてしまう。
ソフトキーボードだとよほどの低スぺ端末でないと再現が難しいが、物理キーボードを繋げると簡単に再現できる。
6.0.547 (SR7) 現在、Android で Image を含む Page を表示すると稀に Java.Lanf.RuntimeException
が発生する。
再現方法はよく理解できてないが、.NET で言う Dispose 済みのインスタンスを使おうとしたみたいなことが起きている模様。
6.0.547 (SR7) 現在、Android で通知から PendingIntent を使って Activity を起動しようとした場合、Shell の内部でぬるぽが発生する。
7.0.0 RC2 では修正済だが何故か 6.0.x にバックポートされていない。
しかも修正済の 7.0.0 RC2 でも今度は Java.Lang.IllegalStateException
で落ちる。
どちらも MainActivity の Activity 属性に LaunchMode = LaunchMode.SingleTop
を加えると直る模様。
[Activity(
Theme = "@style/Maui.SplashTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize
| ConfigChanges.Orientation
| ConfigChanges.UiMode
| ConfigChanges.ScreenLayout
| ConfigChanges.SmallestScreenSize
| ConfigChanges.Density,
+ LaunchMode = LaunchMode.SingleTop
)]
public class MainActivity : MauiAppCompatActivity
{
}
Intent 受信時の挙動が変わるので注意。
Application.Properties が削除されている。
代わりに Microsoft.Maui.Storage.Preferences を使用してほしいとのことだが、既に保存されているデータを移行する方法は用意されていない。
また、Preferences はサポートされている型が限られているため、System.Text.Json などでシリアライズしてから保存する必要がある。
データ移行が必要な場合、Xamarin.Forms の以下のソースを参考に実装できるはず
Application.OnAppLinkRequestReceived のデフォルト実装が削除され、空実装になっている。
Xamarin.Forms での実装をコピペすれば一応動くはずだが、削除に至った経緯などは不明。
Platforms/Android/values/colors.xml
で定義した color を AndroidManifest.xml や MetaDataAttribute で参照しようとするとビルドエラー?
原因がよくわからないので要調査
6.0.548 (SR8) / VS2022 17.4.3 で Mac とペアリングした状態でリモートデバイスに対してデバッグ実行を行うと Type x:String not found in xmlns http://schemas.microsoft.com/winfx/2009/xaml
で実行時例外。
7.0.52 (SR 1.1) に上げると問題なく実行できる。
Visual Studio の Mac とペアリング機能はかなりの頻度で壊れるため依存し過ぎないこと。
どうしても使いたい場合は以下を試す。
- Mac 側の
~/Library/Caches/Xamarin/XMA
をディレクトリごと削除する。 - Windows 側の
%TEMP%\Xamarin\XMA
をディレクトリごと削除する。 - Preview 版 Visual Studio を使ってみる。
- Visual Studio をダウングレードしてみる。
代わりに Mac 版 VSCode に MAUI 拡張機能 をインストールしてデバッグできる。
デバッグ実行時にビルドエラーとなる場合、通常の .NET アプリケーションとしてデバッグ実行しようとしている場合がある。.launch.json
を作成すると間違いに気づきやすい。
また iOS 版デバッグ実行でアプリが立ち上がった直後にアプリがクラッシュしてしまう場合がある。この場合は手動でアプリを起動すると、ブレークポイントは効かないが一応立ち上がるようだ。
7.0.52 (SR1.1) 現在、iOS で Shell アプリの戻るボタンの表示が変。
戻るボタンはタイトルの長さに応じて Back (戻る) またはページのタイトルが表示されるが、タイトルが表示された場合、タイトルが二つ並ぶ不思議な光景になる。
また iOS 14 から戻るボタン長押しで複数ページまとめて戻ることができるが、MAUI の Shell アプリで見るとすべて空白に見える。
以下の PR で再修正された模様。
2023-03-23 時点では .NET 7 へバックポートされていないが、PureWeen.Maui.FixesAndWorkarounds を使用することで対策版のレンダラーに差し替えることができる。
ただし戻るボタン長押しで戻った場合に NavigationStack と不整合が起きてしまっているような気がする。(要調査)
I have a workaround renderer that I've put here
Let me know if you hit any issues and I'll fix
引用元: https://github.com/dotnet/maui/issues/8335#issuecomment-1433488854
7.0.52 (SR1.1) 現在、iOS で Shell.TitleView を設定した場合、一度表示したページをタブ切り替えや戻るなどでもう一度表示させたときに表示が消えてしまう。
以下の PR で再修正された模様。
2023-03-23 時点では .NET 7 へバックポートされていないが、PureWeen.Maui.FixesAndWorkarounds を使用することで対策版のレンダラーに差し替えることができる。
I have a workaround renderer that I've put here
Let me know if you hit any issues and I'll fix
引用元: https://github.com/dotnet/maui/issues/8335#issuecomment-1433488854
7.0.52 (SR1.1) 現在、iOS で ScrollView.Content 内の要素を後から一部変更などして縦幅が伸びる場合、ScrollView も一緒に縦幅が伸びてスクロールできなくなる。
ScrollView.Content 内の要素を後から一部変更する後 HeightRequest を設定し直すと、縦幅が縮んでスクロールできるようになる。
ScrollArea.HeightRequest = 0;
ScrollArea.HeightRequest = -1d;
7.0.52 (SR1.1) 現在、LinearItemsLayout.ItemSpacing の挙動が Android と iOS で微妙に異なる。
Android: CollectionView.Header
と CollectionView.Items
の間にも LinearItemsLayout.ItemSpacing
が適用される。
iOS: CollectionView.Header
と CollectionView.Items
の間には LinearItemsLayout.ItemSpacing
が適用されない。
CollectionView.ScrollTo(0)
の挙動も異なる。
Android: CollectionView.Items[0]
までスクロール (CollectionView.Header
は表示されない)
iOS: CollectionView.Header
までスクロール
7.0.52 (SR1.1) 現在、iOS で CollectionView.Header 内の要素を後から一部変更などして縦幅が伸びる場合、項目と重なって表示される。
CollectionView.Header 直下の要素を変更後 HeightRequest を設定し直すと、縦幅が再計算され重ならなくなる。
((VisualElement)Collection.Header).HeightRequest = 0;
((VisualElement)Collection.Header).HeightRequest = -1d;
修正 PR が Open されているが難航している模様。
7.0.52 (SR1.1) 現在、Android で Border 内に Label を入れ、改行されないギリギリの横幅になるように Label.Text を設定すると、末尾数文字が表示されない場合がある。
Label.Height に連動して Border.Height も伸びるはずが正しく再計算されない場合がある模様。
Label.Text の末尾にスペースを入れると正しく再計算される。
7.0.52 (SR1.1) 現在、Android で RadioButton の〇の色を変えるプロパティが存在しない。
MAUI で追加された Mapper 機能で変更できる。
RadioButtonHandler.Mapper.AppendToMapping("ButtonColor", (handler, element) => {
var view = (AndroidX.AppCompat.Widget.AppCompatRadioButton)handler.PlatformView;
var color = element.TextColor.ToPlatform(); // 暫定的に文字色と同じ色に変化させる
view.ButtonTintList = Android.Content.Res.ColorStateList.ValueOf(color);
});
iOS 版の場合、ControlTemplate が使用されるため、Resources に以下を追加することで RadioButton の〇の色を変えることができる模様。
<SolidColorBrush x:Key="RadioButtonOuterEllipseStrokeLight" Color="Red" />
<SolidColorBrush x:Key="RadioButtonOuterEllipseStrokeDark" Color="Red" />
<SolidColorBrush x:Key="RadioButtonCheckGlyphStrokeLight" Color="Red" />
<SolidColorBrush x:Key="RadioButtonCheckGlyphStrokeDark" Color="Red" />
<SolidColorBrush x:Key="RadioButtonCheckGlyphFillLight" Color="Red" />
<SolidColorBrush x:Key="RadioButtonCheckGlyphFillDark" Color="Red" />
あえてダークテーマに対応しない場合、各 OS 向けのダークモード無効設定に加えて VisualElement.BackgroundColor などの初期値を上書きする必要があるらしい。
MAUI は特に何も指定しなければ .NET のバージョンに対応した最新バージョンが使用される。
この挙動が望ましくない場合は csproj に <MauiVersion>
を追加することでバージョンを固定できるらしい。
7.0.86 (SR6) 現在、いつの間にか <MauiVersion>
が再び機能するようになっていた。
7.0.86 (SR6) 現在、iOS で ScrollView を含むレイアウトが崩れる場合がある。
筆者の環境では Shell の TabBer 下まで ScrollView が拡大してしまう現象が多発していた。
現状回避策はなさそうだが、前述の <MauiVersion>
で 7.0.58 に戻すととりあえずは大丈夫。
8.0.70 (SR7) 現在、CollectionView.Header や ScrollView.Content などに Label を一つだけ配置した場合、iOS 版でのみ他要素に被って表示されてしまったり、スクロールできなかったりする。
Border で囲うと発生しない。
内容が可変の場合はこちらの不具合にも注意。
8.0.70 (SR7) 現在 iOS 版でのみ、スクロールビューの最下部がソフトウェアキーボードの裏に隠れてしまうことがある。
一回でもスクロールビューの最下部までスクロールしてからソフトウェアキーボードを表示すると発生する模様。
修正 PR は出ているが、まだ一部が隠れてしまう場合があり修正は難航している模様。