ハンバーガーメニューで画面を遷移させるには?[Windows 10 UWPアプリ開発]:WinRT/Metro TIPS(1/2 ページ)
SplitViewコントロールとFrameコントロールを利用して、UWP内でハンバーガーメニューから画面遷移を行う方法を解説する。
powered by Insider.NET
Windows 10のユニバーサルWindowsプラットフォーム用のアプリ(以降、UWPアプリ)に特徴的なUIといえば、「ハンバーガーメニュー」(=ハンバーガーボタンによって開閉するメニュー)を使った画面遷移が挙げられる(次の画像)。これはどのようにして実装すればよいのだろうか? 複数の画面それぞれにハンバーガーメニューを実装するのだろうか? あるいは、ハンバーガーメニューの部分をユーザーコントロールとして作成し、それぞれの画面に貼り付けて使うのだろうか? 実は、Windows 10で新しく追加されたSplitViewコントロール(Windows.UI.Xaml.Controls名前空間)を使えば、ハンバーガーメニューの中で画面遷移を行えるのである。ASP.NET(Webフォーム)のマスターページとコンテンツページをご存じならば、それと同じような仕掛けだと言えばイメージは分かっていただけるだろう。
本稿では、SplitViewコントロールを使い、ハンバーガーメニューで画面遷移を実装する例を説明する。ハンバーガーボタンの実装と、ハンバーガーボタンでSplitViewコントロールを開閉する方法については、「WinRT/Metro TIPS:ハンバーガーボタンを実装するには?[Windows 10 UWPアプリ開発]」をご覧いただきたい。なお、本稿のサンプルは「Windows Store app samples:MetroTips #112」からダウンロードできる。
ハンバーガーメニューによる画面遷移の例
これはWindows 10に標準の「ニュース」アプリである。それぞれの画像の左側は、デスクトップ用のもの。右側は、Windows 10モバイルエミュレーターで動かしているモバイル用のものである。
上: ハンバーガーメニューが閉じている状態。デスクトップ用では、ハンバーガーメニューを完全に隠さず、アイコンが見えるようにしている。モバイル用では、ハンバーガーメニューを完全に隠している。ここでハンバーガーボタン(左上の赤色のボタン)をタップ/クリックすると、ハンバーガーメニューが開く。
中: ハンバーガーメニューが開いている状態。このアプリでは、ハンバーガーメニューに表示されている項目の中で、現在表示している画面(この画像では[マイニュース]/[My News])に該当する項目の背景色を変えている(暗赤色)。ここで、例えば[カテゴリ]/[Interests]項目をタップ/クリックすると、ハンバーガーメニューは閉じられ、その画面に遷移する。
下: 画面遷移した状態。デスクトップ用では、縮小されたハンバーガーメニューの中で、遷移した画面に該当するアイコンの背景色が変わっている(モバイル用も同様なのだが、ハンバーガーメニューが完全に隠されているため、この画像では分からない)。
事前準備
デスクトップ用とモバイル(=Windows 10を搭載したスマートフォン)用のUWPアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Community 2015を使っている。
- SLAT対応のPC*1
- 64bit版*2 Windows 10 Pro*3
- Visual Studio 2015(以降、VS 2015)*4
- Windows SDK for Windows 10*5
本稿では、「WinRT/Metro TIPS:ハンバーガーボタンを実装するには?[Windows 10 UWPアプリ開発]」を前提とする。ハンバーガーボタンのタップ/クリックでハンバーガーメニューを開閉する実装については、そちらをご覧いただきたい。
*1 SLAT対応ハードウエアは、モバイルエミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドと実機でのデバッグは可能である。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウエアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。
*2 Windows 10モバイルエミュレーターを使用しないのであれば、32bit版でもよい。
*3 開発に使うWindows 10は「開発者モード」を有効にしておくこと(「設定アプリ」の[更新とセキュリティ]−[開発者向け]で、[開発者モード]ラジオボタンを選択)。そうしないと、VS 2015のXAMLエディターがエラーになる。また、本稿の内容が適用できるのは、Windowsのライフサイクル管理の上では「Windows 10, released in July 2015」と呼ばれるリリース、またはそれ以降。WinVerコマンドで表示されるバージョンは「10.0 (ビルド 10240)」。UWPアプリ開発におけるデバイスファミリーのバージョン指定としては「10.0.0.0」(Package.appxmanifestファイルのTargetDeviceFamily)である。なお、モバイルエミュレーターを使用しないのであれば、Home版でもよい。
*4 本稿に掲載したコードを試すだけなら、無償のExpressエディションやCommunityエディションで構わない。Visual Studio Express 2015 for Windows 10(製品版)はマイクロソフトのページから無償で入手できる(ページの左側で[Visual Studio 2015]−[Express 2015 for Windows 10]と選ぶ)。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、UWPアプリの開発には「for Windows 10」を使う(「for Desktop」はWPF/Windowsフォーム/Win32 APIのアプリ開発用)。また、Visual Studio Community 2015(製品版)もマイクロソフトのページから無償で入手できる。なお、英語版がインストールされた場合には、Microsoft Visual Studio 2015 Language Packの日本語版を追加インストールし、[オプション]ダイアログで言語を切り替える。
*5 使用しているVS 2015に含まれていない場合は、Windows SDK for Windows 10のページからダウンロードできる。本稿の内容が適用できるのは、作成したプロジェクトのプロパティに表示されるターゲットバージョンが「10.0; ビルド 10240」またはそれ以降。
これから実装するUIの構造
最初に、ハンバーガーメニュー(SplitViewコントロール)と遷移する画面との関係を説明しておこう。
本稿で実装するUIは、次の画像のようなものだ。
本稿で実装するUI(デスクトップ)
左側のハンバーガーメニューで[ページ【1】]/[ページ【2】]/[ページ【3】]を選ぶと、右側がそれぞれの画面に遷移する。
なお、ハンバーガーメニューの下端にある[About]は、タップ/クリックするとフライアウトを表示する。これについては本稿では解説しないので、別途公開のサンプルコードをご覧いただきたい。
このUIの構造は、その概略を示すと次の図のようになっている。
本稿で実装するUIの構造(概略)
先の画像と見比べていただきたい。「MainPage.xaml」の中にSplitViewコントロールがあって、そのPaneプロパティにハンバーガーメニューが実装されている。ContentプロパティにはFrameコントロール(Windows.UI.Xaml.Controls名前空間)を入れておき、そのFrameコントロールのNavigateメソッドを使って各ページ(「Page1.xaml」/「Page2.xaml」/「Page3.xaml」)を表示する。先の画像で「ページ【1】」と表示されている赤色の部分は「Page1.xaml」である。
重要な点は、SplitViewコントロールのContentプロパティにFrameコントロール(Windows.UI.Xaml.Controls名前空間)を配置でき、そのFrameコントロールの中で通常のページをナビゲートできることである。
コンテンツに表示するページを作成する
先に、上の図の「Page1.xaml」/「Page2.xaml」/「Page3.xaml」を作成しておこう(次のコード)。テキストブロックの他に、今回は[戻る]ボタンも実装しておく(ただし、これには問題がある。後述する)。
<Page
……省略……
mc:Ignorable="d">
<Grid RequestedTheme="Light" Background="#fff0f0">
<!-- [戻る]ボタン -->
<Button x:Name="BackButton" Click="BackButton_Click"
Width="48" VerticalAlignment="Top" Background="Transparent">
<Button.Content>
<SymbolIcon Symbol="Back" />
</Button.Content>
</Button>
<!-- テキストブロック -->
<TextBlock FontFamily="Yu Gothic" FontSize="40"
HorizontalAlignment="Center" VerticalAlignment="Center">
ページ【1】
</TextBlock>
</Grid>
</Page>
これは「Page1.xaml」である。残りの「Page2.xaml」/「Page3.xaml」も同様に、ただし区別が付くように実装しておく。
今回はここに[戻る]ボタンも配置しているが、あまりよろしくない(後述)。より良い方法は、回をあらためて説明したい。
public sealed partial class Page1 : Page
{
public Page1()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
BackButton.Visibility
= Frame.CanGoBack ? Visibility.Visible : Visibility.Collapsed;
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
Frame.GoBack();
}
}
Public NotInheritable Class Page1
Inherits Page
Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs)
MyBase.OnNavigatedTo(e)
BackButton.Visibility _
= If(Frame.CanGoBack, Visibility.Visible, Visibility.Collapsed)
End Sub
Private Sub BackButton_Click(sender As Object, e As RoutedEventArgs)
Frame.GoBack()
End Sub
End Class
これは「Page1.xaml」のコードビハインドである。[戻る]ボタンのハンドリングだけを行っている。残りの「Page2.xaml」/「Page3.xaml」も同様に実装しておく。
このC#のコードは、冒頭のusing句と名前空間宣言を省略している。
画面遷移用の項目をハンバーガーメニューに実装するには?
ハンバーガーメニューに表示する項目の実装は、さまざまな方法が考えられる。画面遷移を伴わない機能、例えばフライアウトを出すといった用途では、通常のボタンでよいだろう。しかし、画面遷移をさせる場合は項目の選択状態を維持する必要がある。そうしないと、現在どの画面を表示しているのか(=どの項目を選択しているのか)が分からなくなってしまうからだ。すると、画面遷移を伴う機能を実装するときには、トグルボタンが使えそうである。ただし、もう一つ課題がある。同じ項目を2回タップ/クリックしても選択状態が解除されてはいけないのだ(同じ画面が表示されているのであるから)。トグルボタンを使う場合には、その対処が必要になる。
ここでは、ラジオボタンを利用してみよう。選択状態は維持してくれるし、選択された状態の項目をさらにタップ/クリックしてもイベントは発生しない。画面遷移用の項目にはぴったりだ。外観には問題があるが、それは後からスタイルを変更しよう。
すると、「MainPage.xaml」のSplitViewコントロールの部分は、次のコードのようになる。
<SplitView x:Name="Splitter" DisplayMode="CompactOverlay"
CompactPaneLength="48" OpenPaneLength="320"
……省略……
PaneBackground="DarkSeaGreen">
<!-- Paneプロパティにはメニューを入れる -->
<SplitView.Pane>
<Grid RequestedTheme="Dark">
<Grid.RowDefinitions>
……省略……
</Grid.RowDefinitions>
<!-- 上部のナビゲーションボタン -->
<StackPanel Margin="0,32,0,0">
<RadioButton x:Name="RadioButton1"
Checked="RadioButton1_Checked"
GroupName="Navi"
>ページ【1】</RadioButton>
<RadioButton x:Name="RadioButton2"
Checked="RadioButton2_Checked"
GroupName="Navi"
>ページ【2】</RadioButton>
<RadioButton x:Name="RadioButton3"
Checked="RadioButton3_Checked"
GroupName="Navi"
>ページ【3】</RadioButton>
</StackPanel>
<!-- 下端の[About]ボタン -->
……省略……
</Grid>
</SplitView.Pane>
<!-- ContentプロパティにはFrameコントロールを入れる -->
<SplitView.Content>
<Frame x:Name="MainContentFrame" />
</SplitView.Content>
</SplitView>
画面遷移のために必要な部分のみを示す。 ハンバーガーボタンの実装と、ハンバーガーボタンでSplitViewコントロールを開閉する方法については、「WinRT/Metro TIPS:ハンバーガーボタンを実装するには?[Windows 10 UWPアプリ開発]」をご覧いただきたい。
下端の[About]ボタンについては、別途公開のサンプルコードをご覧いただきたい。 なお、冒頭の画像で紹介した「ニュース」アプリは、モバイルデバイスではハンバーガーメニューを完全に隠している。本稿では解説しないが、そうするにはAdaptiveTriggerクラス(Windows.UI.Xaml名前空間)を使ってSplitViewコントロールのDisplayModeプロパティを「Inline」または「Overlay」に切り替える。
そして、画面遷移の項目がタップ/クリックされたときのイベントハンドラーは、次のコードのようになる。実にシンプルである。
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
……省略……
// アプリ開始時には、ページ【1】を表示する
RadioButton1.IsChecked = true;
}
// ハンバーガーメニューで[ページ【1】]が新たに選択された
private void RadioButton1_Checked(object sender, RoutedEventArgs e)
{
MainContentFrame.Navigate(typeof(Page1));
Splitter.IsPaneOpen = false;
}
// ハンバーガーメニューで[ページ【2】]が新たに選択された
private void RadioButton2_Checked(object sender, RoutedEventArgs e)
{
MainContentFrame.Navigate(typeof(Page2));
Splitter.IsPaneOpen = false;
}
// ハンバーガーメニューで[ページ【3】]が新たに選択された
private void RadioButton3_Checked(object sender, RoutedEventArgs e)
{
MainContentFrame.Navigate(typeof(Page3));
Splitter.IsPaneOpen = false;
}
}
Public NotInheritable Class MainPage
Inherits Page
Protected Overrides Async Sub OnNavigatedTo(e As NavigationEventArgs)
……省略……
' アプリ開始時には、ページ【1】を表示する
RadioButton1.IsChecked = True
End Sub
' ハンバーガーメニューで[ページ【1】]が新たに選択された
Private Sub RadioButton1_Checked(sender As Object, e As RoutedEventArgs)
MainContentFrame.Navigate(GetType(Page1))
Splitter.IsPaneOpen = False
End Sub
' ハンバーガーメニューで[ページ【2】]が新たに選択された
Private Sub RadioButton2_Checked(sender As Object, e As RoutedEventArgs)
MainContentFrame.Navigate(GetType(Page2))
Splitter.IsPaneOpen = False
End Sub
' ハンバーガーメニューで[ページ【3】]が新たに選択された
Private Sub RadioButton3_Checked(sender As Object, e As RoutedEventArgs)
MainContentFrame.Navigate(GetType(Page3))
Splitter.IsPaneOpen = False
End Sub
End Class
ラジオボタンが選択されたとき、Frameコントロール(=「MainContentFrame」変数)のNavigateメソッドを使ってそれぞれの画面にナビゲートするだけである。ただし、ハンバーガーメニューは開いたままなので、SplitViewコントロール(=「Splitter」変数)のIsPaneOpenプロパティをFalseにすることでハンバーガーメニューを閉じる。
なお、このC#のコードは、冒頭のusing句と名前空間宣言を省略している。
Copyright© Digital Advantage Corp. All Rights Reserved.