個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Xamarin に関する事を中心に書いています。 Microsoft MVP for Development Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

macOS Big Sur (Apple M1) 上で、Visual Studio for Mac を軽く試してみました。(2020/11/23速報版)

はじめに

こんにちは、@hiro128_777です。
 
ようやく、Apple M1 Mac が自宅に届きました。というわけで、早速 Apple M1 MacVisual Studio for Mac を一通り軽く試してみました。なお、まだ詳しい検証はできておりませんので、引き続き調査したいと思います。
 
Intel Mac の Big Sur 上の動作状況は以下をご覧ください。
hiro128.hatenablog.jp
 

バージョン

 
Xcode は Universal App です。
f:id:hiro128:20201123213941p:plain
 

Visual StudioIntel App で Rosetta2 を介しての動作となります。
f:id:hiro128:20201123214003p:plain 
 


Visual Studio for Mac のインストールと起動

 
インストールと起動は全く問題ありません。当該の Mac 上で、 なお、Rosetta 2 を利用するアプリの起動が初めての場合は、Rosetta 2 のインストールが走ります。
f:id:hiro128:20201123214132p:plain
 


なお、Visual Studio for Mac Version 8.8 のリリースノートは以下をご参照ください。
docs.microsoft.com
 


アプリごとの動作のまとめ

 

SDK 認識・コード編集 エミュレータ
デバッグ実行
実機
デバッグ実行
備考
ASP.NET(.NET 5) ○ OK --------------- × NG Safari (Universal) 、 Chrome (Universal) ともに同じエラー
iOS ○ OK ○ OK ○ OK(若干不安定) 実機でプロビジョニングプロファイルの設定が不完全な時、
1度 VS がクラッシュ
Android ○ OK × NG × NG エミュレータが起動せず、実機も認識しない
macOS ○ OK --------------- ○ OK Intel App としてビルドされ、Universal App としてビルドできない

 


ASP.NET(.NET 5)


自分の環境では、Intel Mac 同様、ASP.NET で初回のみ開発証明書に関するダイアログが出ましたが、以下のように、画面表示の通り許可すれば、次回以降は聞かれなくなります。
f:id:hiro128:20201113143123p:plain
 
f:id:hiro128:20201113143139p:plain
 
f:id:hiro128:20201113143153p:plain
 
f:id:hiro128:20201113143213p:plain
 

上記は、微妙に発生条件が違いますが、以下の issue が相当しそうです。
docs.microsoft.com
 


ただし、対処後もデバッグ実行に失敗します。
 
f:id:hiro128:20201123214109p:plain


下記のようなエラーメッセージが出ます。

-------------------------------------------------------------------
You may only use the Microsoft .NET Core Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software
to help you develop and test your applications.
-------------------------------------------------------------------
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/5.0.0/System.Private.CoreLib.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Stack overflow.
   at System.Collections.HashHelpers.GetPrime(Int32)
   at System.Collections.Generic.Dictionary`2[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Initialize(Int32)
   at System.Collections.Generic.Dictionary`2[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor(Int32, System.Collections.Generic.IEqualityComparer`1<System.__Canon>)
   at System.AppContext.Setup(Char**, Char**, Int32)

 



iOS アプリ

 

SDK 認識・コード編集

問題ありません。
 

ビルド・デバッグ実行(シミュレータ)

問題ありません。
 

ビルド・デバッグ実行(実機)

問題ありません。
 
プロビジョニングプロファイルの設定が不完全な時、1度だけ Visual Studio がクラッシュしました。その後は、プロビジョニングプロファイルの設定が不完全であることを示すエラーが表示されました。
  


Android アプリ

 

SDK 認識・コード編集

問題ありません。
 

ビルド・デバッグ実行(エミュレータ

エミュレータが起動できず、実行できません。 


ビルド・デバッグ実行(実機)

実機を認識しませんでした。ただし、Intel Mac では、実機をきちんと認識しますので、Visual Studio for Mac 起因の問題ではない可能性もあります。
 


mac アプリ

 

SDK 認識・コード編集

問題ありません。
 

ビルド・デバッグ実行(実機)

 
ビルド、デバッグ実行できますが、Universal App としてビルドさせる設定が見つからず、結果として、Intel App としてビルドされ、Universal App としてはビルドできません。
f:id:hiro128:20201123215611p:plain

まとめ

というわけで、軽く触った感じでは、Apple M1 Mac ではまだ問題が結構ありそうです。エラーの原因も詳しく調べられていないので、もう少し色々試してみたいと思います。
なお、速度的には特に遅いとは感じませんでした。Visual Studio for Mac が M1 ネイティブで動くようになるのが楽しみです。

 
今回は以上です。

macOS Big Sur (Intel) 上で、Visual Studio for Mac を軽く試してみました。

はじめに

こんにちは、@hiro128_777です。

待ちに待った macOS Big Sur がリリースされました。というわけで、早速アップデートし Intel Mac 上で Visual Studio for Mac を一通り軽く試してみました。

f:id:hiro128:20201113133120p:plain
 


なお、Apple M1 チップ Mac 上の検証結果は以下をご覧ください。
hiro128.hatenablog.jp



バージョン

 


Visual Studio for Mac 起動

問題ありません。
f:id:hiro128:20201113133151p:plain
 
なお、Visual Studio for Mac Version 8.8 のリリースノートは以下をご参照ください。
docs.microsoft.com


iOS アプリ

SDK 認識・コード編集

問題ありません。
f:id:hiro128:20201113131721p:plain
 

ビルド・デバッグ実行(シミュレータ)

問題ありません。
f:id:hiro128:20201113140048p:plain
 


Android アプリ

SDK 認識・コード編集

問題ありません。
f:id:hiro128:20201113142030p:plain
 

ビルド・デバッグ実行(シミュレータ)

問題ありません。
f:id:hiro128:20201113140029p:plain
 


.NET 5 ASP.NET アプリ

SDK 認識・コード編集

問題ありません。
f:id:hiro128:20201113142058p:plain
 

ビルド・デバッグ実行

自分の環境では、ASP.NET デバッグ実行時、開発証明書に関するダイアログが出ましたが、以下のように、画面表示の通り許可すれば、問題ありませんでした。

f:id:hiro128:20201113143123p:plain
 
f:id:hiro128:20201113143139p:plain
 
f:id:hiro128:20201113143153p:plain
 
f:id:hiro128:20201113143213p:plain
 

上記は、微妙に発生条件が違いますが、以下の issue が相当しそうです。
docs.microsoft.com
 

なお、対処後は無事デバッグ実行もできました。
f:id:hiro128:20201113133803p:plain
 


まとめ

というわけで、軽く触った感じでは、Intel Mac では問題なさそうです。
 
Apple M1 Mac での挙動は、実機が届き次第確認してみます。
 
今回は以上です。

DualScreen 対応の Xamarin.Forms アプリを作ってみる (3)

はじめに

こんにちは、@hiro128_777です。

とうとう iPhone 12 が発売されましたね。でも、Surface Duo も忘れないでください。Surface Duo 日本での発売はまだですが、すでに、エミュレーターで疑似体験することは可能です。

というわけで、10月27日(火)に、エミュレーターSurface Duo 対応アプリを体験するオンラインハンズオンを開催いたします!

こちらは、簡単な Surface Duo のエミュレーターで動作するマルチスクリーン対応アプリを作って体験していただけるコンテンツになっていますので、ご興味がある方はぜひご参加下さい!


csharp-tokyo.connpass.com
 

この記事は(3)ですので、最初から手順をお試しになる場合は下記の(1)からお願いします。
hiro128.hatenablog.jp

 

(2)は下記からお願いします。
hiro128.hatenablog.jp

 

今回やること

 
ViewModel と Service を紐づけてアプリを完成させます。
 

ViewModel と Service を紐づける

 
ViewModel と Service を紐づけるコードを追記していきます。

なお、このサンプルはコードをシンプルにし、Dual Screen の動作をわかりやすくするために、 DI などコードの量が増える手法はあえて省いています。
 

MasterDetailPage.xaml.cs を修正

 
// 追記の部分を追記してください。
 

        bool IsSpanned => DualScreenInfo.Current.SpanMode != TwoPaneViewMode.SinglePane;

        DetailsPage detailsPagePushed;

        MasterViewModel masterViewModel; // 追記
        DetailsViewModel detailsViewModel; // 追記

        public MasterDetailPage()
        {
            InitializeComponent();

            NavigationPage.SetHasNavigationBar(this, IsSpanned);

            detailsPagePushed = new DetailsPage();

            masterViewModel = masterPage.BindingContext as MasterViewModel; // 追記
            masterViewModel.SetupViewsAction = () => SetupViews(); // 追記

            detailsViewModel = masterViewModel.DetailsViewModel; // 追記
            detailsPagePushed.BindingContext = detailsViewModel; // 追記
            detailsPage.BindingContext = detailsViewModel; // 追記
        }

 

Master.xaml.cs を修正

 
// 追記の部分を追記してください。
 

        public Master()
        {
            InitializeComponent();

            BindingContext = new MasterViewModel(new DetailsViewModel()); // 追記
        }

 

View から確認用の マークアップ を消去

 
<!-- 確認用(後ほど消去する)ここから -->から<!-- 確認用(後ほど消去する)ここまで -->の部分を消去してください。

    <Picker
        Title="路線を選択して下さい"
        Margin="10"
        HeightRequest="60"
        FontSize="Large"
        HorizontalOptions="Fill"
        VerticalOptions="Fill"
        ItemsSource="{Binding LineItems}"
        SelectedItem="{Binding SelectedLineItem, Mode=TwoWay}"
        >
    </Picker>
    <!-- 確認用(後ほど消去する)ここから -->
    <Label FontSize="Title" TextColor="Coral" Text="Master" HorizontalOptions="CenterAndExpand">
    </Label>
    <!-- 確認用(後ほど消去する)ここまで -->
    <CollectionView
        x:Name="Stations"
        ItemsSource="{Binding StationItems}"
        SelectionMode="Single"
        SelectedItem="{Binding SelectedStationItem, Mode=TwoWay}"
        SelectionChangedCommand="{Binding SelectStationCommand}"
        >

 

Details.xaml から確認用の マークアップ を消去

 
<!-- 確認用(後ほど消去する)ここから -->から<!-- 確認用(後ほど消去する)ここまで -->の部分を消去してください。

        <Label
            BackgroundColor="White"
            FontSize="Title"
            Grid.Column="1" Grid.Row="1"
            Text="{Binding Name}"
            VerticalTextAlignment="Center"
            >
        </Label>
    </Grid>
    <!-- 確認用(後ほど消去する)ここから -->
    <Label FontSize="Title" TextColor="Coral" Text="Detail" HorizontalOptions="CenterAndExpand">
    </Label>
    <!-- 確認用(後ほど消去する)ここまで -->
    <StackLayout
        BackgroundColor="White"
        Padding="5">

 

以上でコードは完成です。
 

デバッグ実行し、Dual Screen でアプリが動作するか確認する

 
Dual Screen で表示させるためには以下の動画の手順でアプリをスパンしてください。

Surface Duo Span 操作
youtu.be
 

上記の動画のように、路線と駅が選択でき、時刻が表示されればサンプルアプリは完成です。
 

今回は以上です。

DualScreen 対応の Xamarin.Forms アプリを作ってみる (2)

はじめに

こんにちは、@hiro128_777です。

とうとう iPhone 12 が発表されましたね。でも、Surface Duo も忘れないでください。Surface Duo 日本での発売はまだですが、すでに、エミュレーターで疑似体験することは可能です。

というわけで、10月27日(火)に、エミュレーターSurface Duo 対応アプリを体験するオンラインハンズオンを開催いたします!

こちらは、簡単な Surface Duo のエミュレーターで動作するマルチスクリーン対応アプリを作って体験していただけるコンテンツになっていますので、ご興味がある方はぜひご参加下さい!

csharp-tokyo.connpass.com


なお、この記事は(2)ですので、最初から手順をお試しになる場合は下記の(1)からお願いします。
hiro128.hatenablog.jp



今回やること

TwoPaneViewを作成し、Surface Duo エミュレータ―上で、Master - Detail 構成のページを Dual Screen 表示できるようにします。

TwoPaneViewGridを継承しており、左右または上下に 2 つのビューを配置できるコンテナーです。

TwoPaneViewの詳細については下記公式ドキュメントをご参照ください。

docs.microsoft.com



Dual Screen に対応するには、以下の対応を行うだけであり、非常に簡単です。

  • Single Screen 用と、Dual Screen 用の "ガワ" の ContentPage を別々に用意し、それぞれのコンテンツの配置情報のみ記述する。

  • 具体的なコンテンツ(配置する UI)の XAML を用意する。

  • TwoPaneViewが 画面の表示領域のサイズによって、Single Screen 用または、Dual Screen 用 の画面を表示できるように、MinWideModeWidthMinTallModeHeightを設定します。


TwoPaneViewの Single Screen、Dual Screen の制御の詳細については下記公式ドキュメントをご参照ください。

docs.microsoft.com


これから作成するサンプルアプリの Single Screen、Dual Screen のときの構成を図に表すと以下のようになります。

Single Screen 時の構成

f:id:hiro128:20201018171513p:plain
 

Dual Screen 時の構成

f:id:hiro128:20201018171631p:plain
 

では、次にコードを書いていきましょう。 

TwoPaneView用のコンテンツページとコンテンツビューのファイル追加する

 

  1. View フォルダを追加します。
  2. 以下の4つのコンテンツページを追加します。
    1. MasterDetailPage.xaml コンテンツページ
    2. DetailsPage.xaml コンテンツページ
    3. Master.xaml コンテンツビュー
    4. Details.xaml コンテンツビュー


以下のようになればOKです。
f:id:hiro128:20201018162214p:plain


デフォルトの MainPage に設定されているMainPage.xamlを削除します。

f:id:hiro128:20201018165908p:plain
 

MasterDetailPage を MainPage として設定します。
 

App.xaml.cs
        public App()
        {
            InitializeComponent();
            MainPage = new NavigationPage(new MasterDetailPage());
        }

 

MasterDetailPage.xamlマークアップとコードを記述する

 
Single Screen 時は Master Page のコンテンツのみ表示し、Dual Screen 時は 左に Master Page のコンテンツ、右に Detail Page のコンテンツを表示します。
 

MasterDetailPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:d="http://xamarin.com/schemas/2014/forms/design"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:dualScreen="clr-namespace:Xamarin.Forms.DualScreen;assembly=Xamarin.Forms.DualScreen"
            xmlns:local="clr-namespace:XFSurfaceDuoSample2020"
            mc:Ignorable="d"
            x:Class="XFSurfaceDuoSample2020.MasterDetailPage">
    <dualScreen:TwoPaneView MinWideModeWidth="4000" MinTallModeHeight="4000">
        <dualScreen:TwoPaneView.Pane1>
            <local:Master x:Name="masterPage"></local:Master>
        </dualScreen:TwoPaneView.Pane1>
        <dualScreen:TwoPaneView.Pane2>
            <local:Details x:Name="detailsPage"></local:Details>
        </dualScreen:TwoPaneView.Pane2>
    </dualScreen:TwoPaneView>
</ContentPage>

 

MasterDetailPage.xaml.cs
using System.ComponentModel;
using System.Linq;
using Xamarin.Forms;
using Xamarin.Forms.DualScreen;
using Xamarin.Forms.Xaml;

using XFSurfaceDuoSample2020.Models;
using XFSurfaceDuoSample2020.ViewModels;

namespace XFSurfaceDuoSample2020
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MasterDetailPage
    {
        bool IsSpanned => DualScreenInfo.Current.SpanMode != TwoPaneViewMode.SinglePane;

        DetailsPage detailsPagePushed;

        public MasterDetailPage()
        {
            InitializeComponent();
            NavigationPage.SetHasNavigationBar(this, IsSpanned);
            detailsPagePushed = new DetailsPage();
        }

        async void SetupViews()
        {
            NavigationPage.SetHasNavigationBar(this, !IsSpanned);
            NavigationPage.SetHasNavigationBar(detailsPagePushed, !IsSpanned);
            NavigationPage.SetHasNavigationBar(detailsPage, !IsSpanned);

            if (!IsSpanned)
            {
                if (!Navigation.NavigationStack.Contains(detailsPagePushed))
                    await Navigation.PushAsync(detailsPagePushed);
            }
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            DualScreenInfo.Current.PropertyChanged += OnFormsWindowPropertyChanged;
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            DualScreenInfo.Current.PropertyChanged -= OnFormsWindowPropertyChanged;
        }

        void OnFormsWindowPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(DualScreenInfo.Current.SpanMode) ||
                e.PropertyName == nameof(DualScreenInfo.Current.IsLandscape))
            {
                SetupViews();
            }
        }

    }
}

 

DetailsPage.xamlマークアップとコードを記述する

 
Single Screen 時は Detail Page を表示します。Dual Screen 時は使用されません。
 

DetailsPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:XFSurfaceDuoSample2020"
             mc:Ignorable="d"
             x:Class="XFSurfaceDuoSample2020.DetailsPage"
             Title="Master Details"
             Padding="10,0,0,0"
             >
    <local:Details></local:Details>
</ContentPage>

 

DetailsPage.xaml.cs
using Xamarin.Forms.DualScreen;
using Xamarin.Forms.Xaml;

namespace XFSurfaceDuoSample2020
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class DetailsPage
    {
        bool IsSpanned => DualScreenInfo.Current.SpanMode != TwoPaneViewMode.SinglePane;

        public DetailsPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            DualScreenInfo.Current.PropertyChanged += OnFormsWindowPropertyChanged;
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            DualScreenInfo.Current.PropertyChanged -= OnFormsWindowPropertyChanged;
        }

        async void OnFormsWindowPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if(e.PropertyName == nameof(DualScreenInfo.Current.SpanMode) ||
                e.PropertyName == nameof(DualScreenInfo.Current.IsLandscape))
            {
                if (IsSpanned)
                    await Navigation.PopAsync();
            }
        }
    }
}

 
 

Master.xamlマークアップとコードを記述する

 
Master Page のコンテンツです。
 

Master.xaml
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Class="XFSurfaceDuoSample2020.Master"
    >
    <StackLayout.Resources>
        <ResourceDictionary>
            <Style TargetType="Grid">
                <Setter Property="VisualStateManager.VisualStateGroups">
                    <VisualStateGroupList>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="Selected">
                                <VisualState.Setters>
                                    <Setter
                                        Property="BackgroundColor"
                                        Value="LightSkyBlue"
                                        />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateGroupList>
                </Setter>
            </Style>
        </ResourceDictionary>
    </StackLayout.Resources>
    <Picker
        Title="路線を選択して下さい"
        Margin="10"
        HeightRequest="60"
        FontSize="Large"
        HorizontalOptions="Fill"
        VerticalOptions="Fill"
        ItemsSource="{Binding LineItems}"
        SelectedItem="{Binding SelectedLineItem, Mode=TwoWay}"
        >
    </Picker>
    <!-- 確認用(後ほど消去する)ここから -->
    <Label FontSize="Large" TextColor="Coral" Text="Master Page のコンテンツ" HorizontalOptions="CenterAndExpand">
    </Label>
    <!-- 確認用(後ほど消去する)ここまで -->
    <CollectionView
        x:Name="Stations"
        ItemsSource="{Binding StationItems}"
        SelectionMode="Single"
        SelectedItem="{Binding SelectedStationItem, Mode=TwoWay}"
        SelectionChangedCommand="{Binding SelectStationCommand}"
        >
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid
                    Padding="5"
                    >
                    <Frame Visual="Material" BorderColor="LightGray">
                        <StackLayout
                            Padding="0"
                            >
                            <Label FontSize="Title" Text="{Binding Name}">
                            </Label>
                        </StackLayout>
                    </Frame>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</StackLayout>

 

Master.xaml.cs
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

using XFSurfaceDuoSample2020.ViewModels;

namespace XFSurfaceDuoSample2020
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Master : StackLayout
    {
        public Master()
        {
            InitializeComponent();
        }
    }
}

 

Details.xamlマークアップとコードを記述する

 
Detail Page のコンテンツです。
 

Details.xaml
<?xml version="1.0" encoding="UTF-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="XFSurfaceDuoSample2020.Details"
             BackgroundColor="LightGray"
             Spacing="0"
             >
    <Grid
        BackgroundColor="White"
        RowSpacing="2" ColumnSpacing="2"
        Padding="8,8,8,0"
        VerticalOptions="Center"
        >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Label
            BackgroundColor="White"
            HorizontalTextAlignment="End" VerticalTextAlignment="Center"
            FontSize="Title" Text="ナンバリング :"
            >
        </Label>
        <Label
            BackgroundColor="White"
            Grid.Row="1"
            HorizontalTextAlignment="End" VerticalTextAlignment="Center"
            FontSize="Title" Text="駅名 :"
            >
        </Label>
        <Label
            BackgroundColor="White"
            FontSize="Title"
            Grid.Column="1"
            Text="{Binding SelectedStationItem.ID}"
            VerticalTextAlignment="Center"
            >
        </Label>
        <Label
            BackgroundColor="White"
            FontSize="Title"
            Grid.Column="1" Grid.Row="1"
            Text="{Binding Name}"
            VerticalTextAlignment="Center"
            >
        </Label>
    </Grid>
    <StackLayout
        BackgroundColor="White"
        Padding="5">
        <!-- 確認用(後ほど消去する)ここから -->
        <Label FontSize="Large" TextColor="Coral" Text="Detail Page のコンテンツ" HorizontalOptions="CenterAndExpand">
        </Label>
        <!-- 確認用(後ほど消去する)ここまで -->
        <CollectionView
            Margin="3"
            BackgroundColor="LightGray"
            x:Name="Stations"
            ItemsSource="{Binding TimeTableRowItems}"
            SelectionMode="None"
            >
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout
                        BackgroundColor="LightGray"
                        Padding="1">
                        <Grid
                            BackgroundColor="LightGray"
                            HorizontalOptions="Fill"
                            VerticalOptions="Center"
                            ColumnSpacing="2"
                            Padding="2,1,2,1"
                            >
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"></ColumnDefinition>
                                <ColumnDefinition Width="10*"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <Label
                                BackgroundColor="LightSkyBlue"
                                Padding="8"
                                Grid.Column="0" Grid.Row="0"
                                Text="{Binding Hour}"
                                FontSize="Large"
                                HorizontalTextAlignment="Center" 
                                VerticalTextAlignment="Center"
                                >
                            </Label>
                            <Label
                                BackgroundColor="Beige"
                                Padding="8"
                                Grid.Column="1" Grid.Row="0"
                                Text="{Binding RowText}"
                                FontSize="Large"
                                HorizontalTextAlignment="Start"
                                VerticalTextAlignment="Center"
                                >
                            </Label>
                        </Grid>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>
</StackLayout>

 

Details.xaml.cs
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace XFSurfaceDuoSample2020
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Details : StackLayout
    {
        public Details()
        {
            InitializeComponent();
        }
    }
}

 

デバッグ実行し、Single Screen、Dual Screen で表示されるか確認する。

 
Surface Duo エミュレータ―にデプロイすると、以下のように、Single Screen、Dual Screen で表示が変化します。
 

Single Screen での表示

f:id:hiro128:20201018214953p:plain
 

Dual Screen での表示

f:id:hiro128:20201018215010p:plain

 
  
Dual Screen で表示させるためには以下の動画の手順でアプリをスパンしてください。
なお、アプリのロジックはまだ実装していないので、画面が表示されるだけで、UI は反応しません。
 
Surface Duo Span 操作
youtu.be

 

続きは以下をご覧ください。
hiro128.hatenablog.jp

DualScreen 対応の Xamarin.Forms アプリを作ってみる (1)

はじめに

こんにちは、@hiro128_777です。

とうとう iPhone 12 が発表されましたね。でも、Surface Duo も忘れないでください。Surface Duo 日本での発売はまだですが、すでに、エミュレーターで疑似体験することは可能です。

というわけで、10月27日(火)に、エミュレーターSurface Duo 対応アプリを体験するオンラインハンズオンを開催いたします!

こちらは、簡単な Surface Duo のエミュレーターで動作するマルチスクリーン対応アプリを作って体験していただけるコンテンツになっていますので、ご興味がある方はぜひご参加下さい!


csharp-tokyo.connpass.com


今回から数回 DualScreen 対応の Xamarin.Forms アプリを作る方法をご紹介します。

今回の内容の詳しい手順は、下記公式ドキュメントにもあります。
なお、サンプルのソリューションを準備しましたので、より詳しい手順を追って、実際に触って試していただけるようにしました。


docs.microsoft.com


エミュレーターのインストール

MacWindows それぞれの方法をまとめてありますので、以下の記事をご参照ください。

サンプルのソリューション

以下より取得してください。
github.com


XFSurfaceDuoSample2020/start-long/XFSurfaceDuoSample2020.slnを開ます。


SDK のインストール

NuGet パッケージ マネージャーで Xamarin.Forms.DualScreen を検索し、ソリューションのそれぞれのプロジェクトに、 Xamarin.Forms と同じバージョンの Xamarin.Forms.DualScreen パッケージをインストールします。

f:id:hiro128:20201013230011p:plain


MainActivity クラスの変更

 

属性の変更

Android プロジェクトの MainActivity クラスの ConfigurationChanges 属性を確認し、属性が足りなければ変更します。

ConfigurationChanges を設定することで、構成の変更が発生した場合にシステムによってアクティビティが再起動されなくなります。また、発生時の処理のコードを記述することもできます。

詳しくは、以下の公式ドキュメントをご参照ください。

docs.microsoft.com


以下の属性が設定されていることを確認してください。

ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.UiMode

 

以下のようになります。

    [Activity(Label = "XFSurfaceDuoSample2020", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, 
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize 
    )]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity

 

DualScreenService の初期化

次に、DualScreenService を初期化します。

OnCreate メソッドの LoadApplication(new App()); の直上に以下の初期化メソッド呼び出しを追加します。

// Initialize DualScreen Service
Xamarin.Forms.DualScreen.DualScreenService.Init(this);

 

以下のようになります。

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

            // Initialize DualScreen Service
            Xamarin.Forms.DualScreen.DualScreenService.Init(this);

            LoadApplication(new App());
        }

 


エミュレータ―上でデバッグ実行

ビルドし、 (Android 10.0 - API 29) を選択し、デバッグ実行できれば成功です。

Mac

f:id:hiro128:20201013225904p:plain


Windows

f:id:hiro128:20201013225949p:plain



デプロイが完了し、以下のようになれば成功です。

f:id:hiro128:20201013232449p:plain


続きは以下をご覧ください。
hiro128.hatenablog.jp

Visual Studio 2019 (Windows) で Surface Duo エミュレーターを使用してみる

はじめに

こんにちは、@hiro128_777です。

いよいよ、Surface Duo が発売になりますね。自分も買って試してみたいですが、残念ながらまだ、日本での発売は発表されていません。

でも、とりあえず早く触ってみたいという方は「Surface Duo エミュレーター」なら今すぐ試せます。

というわけで、Visual Studio 2019 で Surface Duo エミュレーターを使用してみました。

Microsoft Docs に手順がありますが、画像が無くわかりにくいので、画像付きでご説明します。


SDK のインストール

以下のように、API 29 の SDK をインストールします。 

f:id:hiro128:20200920211006p:plain


f:id:hiro128:20200920211022p:plain


f:id:hiro128:20200920211039p:plain


Surface Duo エミュレーターのセットアップ

以下のページを開いて、記載の手順通り「Surface Duo SDK プレビューリリース」から、ダウンロードページにアクセスして、インストーラーをダウンロードしてください。

docs.microsoft.com


インストーラーを起動して Surface Duo エミュレーターをインストールします。

f:id:hiro128:20200922161026p:plain


Surface Duo エミュレーター の起動スクリプトの確認

Android SDK のインストールパスをカスタマイズしている場合、以下の手順で、Surface Duo エミュレーターの起動スクリプトの設定を確認します。 (Android SDK のインストールパスがデフォルトの場合、変更の必要はありません。)

docs.microsoft.com


Surface Duo エミュレーターを起動します。

以下のページの手順の通り、スタートメニューから Surface Duo Emulator for Visual Studio を起動します。

docs.microsoft.com

f:id:hiro128:20200920211425p:plain


起動すると以下のようになります。

f:id:hiro128:20200922160530p:plain


早速アプリをビルドして実行してみましょう

以下にビルドしてすぐデプロイできるサンプルアプリを準備しました。

github.com


Visual Studio 2019 で XFSurfaceDuoSample2020/finish/XFSurfaceDuoSample2020.sln を開き、ビルドして、(実行中のデバイスの一覧で) (Android 10.0 - API 29) を選択し、デバッグ実行します。

f:id:hiro128:20200920211443p:plain



以下の動画の通り、デプロイされアプリが動きます。
なお、Dual Screen で表示させるためには以下の動画の手順でアプリをスパンしてください。

youtu.be


今回は、以上です。

.NET MAUI について今わかっている事を整理しました

MAUI とは

.NET Multi-platform App UI
の略称です。

 

MAUI ってどんなもの?

  • マルチプラットフォームのネイティブ UI ライブラリ
  • モバイルとデスクトップの複数のデバイスにデプロイ可能
  • 単一のプロジェクト、単一のコードベースを使用する
  • Xamarin.Forms の進化版
  • .NET MAUI および新しいモバイル SDK は、.NET 6 と一緒にリリースされる予定です。なお、2020年末にプレビューの予定です。

※ つまり、残念ながら .NET 5 での .NET Core と Mono の統合は延期され、.NET 6 での統合になったということになります…

MAUI のゴール

  • アプリのパフォーマンスを向上させる
  • 簡単にコントロールを拡張できるようにする
  • 簡単にコントリビュートできるようにする
  • Model-View-Update(MVU)と Blazor のアプリパターンを提供する

 

マイルストーン

 

対応プラットフォーム

   Xamarin.Forms        .NET MAUI    
Android API 19 以降 API 21 以降
iOS iOS 9 から iOS 15 まで iOS 10 以降
Linux Community Community
macOS Community Microsoft
Tizen Samsung Samsung
Windows UWP Microsoft WPF Community Microsoft

特長

   Xamarin.Forms        .NET MAUI    
Renderers BindableObject に密結合 疎結合
コア依存なし
スリムレンダラー
App Models MVVM
RxUI
MVVM
RxUI
MVU
Blazor
Single Project ×
Multi-targeting ×
Multi-window ×

 

対応 .NET、プロジェクト形式など

   Xamarin.Forms        .NET MAUI    
対応 .NET Xamarin.iOS
Xamarin.Android
Mono
.NET Framework
その他
.NET 6 以降
取得方法 NuGet & Visual Studio Installer dotnet CLI
プロジェクト形式 SDK 形式 SDK 形式
dotnet CLI 対応 ×

 

開発環境

   Xamarin.Forms        .NET MAUI    
Visual Studio 2019
Visual Studio 2019 for Mac
Visual Studio Code ×

 

MVUの採用

MAUI では、新しいアプリパターンである、MVU が採用される予定です。.NET Blog に、コードのサンプルも提示されていましたが、現在、議論中のため、具体的なコードは提示いたしません。
 

MVUの特長

同じく、.NET Blog によると、MVU には以下の特長があるとのことです。

  • データと状態の管理のフローが一方向になる
  • 必要な変更のみを適用することで UI を迅速に更新できる
  • ホットリロードに最適である

 
 

Xamarin.Forms はどうなるの…

  • Xamarin.Forms の次のメジャーバージョンは2020年9月頃になる予定
  • .NET 6 での .NET MAUI のリリースを通じて引き続き更新されます。
  • その後、Xamarin.Forms は 12 か月間は従来同様メンテナンスされます。(つまり 12か月後以降にはメンテナンスが終了し、製品の終焉を迎えることになりりそうです…)

 

 

本日は以上です。