🐈

MAUI ハンドラーのマップ変更を試したメモ

2022/07/18に公開

Xamarin.Formsのカスタムレンダラーの代わりを習得するために、ひとまずハンドラーを触ってみました。マップをいじることでいろいろ出来るらしいです。

https://docs.microsoft.com/ja-jp/dotnet/maui/user-interface/handlers/customize

試すページ

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiFirst.MainPage">		 
    <ScrollView>
        <VerticalStackLayout 
            Spacing="25" 
            Padding="30,0" 
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />
                
            <Label 
                Text="Hello, World!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                TextColor="Green"
                HorizontalOptions="Center" />
            
            <Label 
                Text="Welcome to .NET Multi-platform App UI"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                FontSize="18"
                HorizontalOptions="Center"
                x:Name="Mainlabel" />

            <Button 
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                Clicked="OnCounterClicked"
                HorizontalOptions="Center" />

            <Button
                x:Name="TestBtn"
                Text="Test"
                HorizontalOptions="Center"
                Clicked="TestBtn_Clicked" />

        </VerticalStackLayout>
    </ScrollView>
</ContentPage>

Testボタンを押すと2行目のラベルが緑に変わるようにしています。

マップを変更

ModifyMapping はマッパーの差し替えっぽい動き。
ドキュメントの表現がややこしいが、マップを変更するというのはこれだけ。

Microsoft.Maui.Handlers.LabelHandler.Mapper.ModifyMapping(nameof(ILabel.TextColor), (handler, view, element) =>
{
#if IOS
    handler.PlatformView.TextColor = UIColor.Red;
#endif
});

この場合Label.TextColorプロパティを変更しても何も起きない。(標準のマップが置き換わっている)

マップの割り込み

これもドキュメントの表現が微妙で分かりにくいですが、差し替えでなく追加です。
PrependとAppendの違いはどこに追加するかというところです。

Prepend

標準のマップの前に追加されるっぽい動き。

Microsoft.Maui.Handlers.LabelHandler.Mapper.PrependToMapping(nameof(ILabel.TextColor), (handler, view) =>
{
#if IOS
    handler.PlatformView.TextColor = UIColor.Red;
#endif
});

この場合はLabel.TextColorプロパティを変更するとその色に変わる。標準マッパーの方が上書きしてる。変更してなくてもデフォルトの黒が優先され見た目上は何も変わらない。

Testボタンタップ

Append

標準のマップの後ろに追加されるっぽい動き。

Microsoft.Maui.Handlers.LabelHandler.Mapper.AppendToMapping(nameof(ILabel.TextColor), (handler, view) =>
{
#if IOS
    handler.PlatformView.TextColor = UIColor.Red;
#endif
});

この場合はLabel.TextColorプロパティを変更しても、追加したマッパーで上書きされるので赤のまま。

新しいマップを追加

既存のマップには無いキーでも追加できる。この場合はAppendToMappingしか意味がない気がします。

Microsoft.Maui.Handlers.LabelHandler.Mapper.AppendToMapping("MyLabel", (handler, view) =>
{
#if IOS
    var subview = new UIView();
    subview.Frame = new CoreGraphics.CGRect(0,0,30,15);
    subview.BackgroundColor = UIColor.Orange;
    handler.PlatformView.AddSubview(subview);
#endif
});

マップ変更の使い所

正直あんまり思いつかないですが、標準のプロパティではいじれないネイティブコントロールの外観などを変更するのに使えそうです。
既存のマップの変更とか前後への割り込みよりも新規キーで追加する最後に紹介したパターンが一番出番がありそうです。
結局既存のマップをいじろうとすると実際に何が起こってるのかソースみないと理解できなかったりするのでなかなか出番は無さそうな気がしています。

実際にハンドラーを作ってみると、使い所がもっと理解できそうなので次はそれを試してみようと思います。

Discussion