新しいFacebook のUIのような動きを実装する。
#wpdev_jp
新しいFacebook アプリが公開されました。左右にスワイプすると個別のメニューが表示されるUIになってます。こういったUIをどうやって作ったらいいのか?試してみました。
7.1のプロジェクトを作ります。
やらなくてもいいけどライトテーマの強制
まずは、ライトテーマの強制をします。自前でやるのは面倒なのでほかのライブラリを使います。
NuGet から ThemeManager を検索してインストールします。
App.xaml.cs でライトテーマの強制をします。
public App()
{
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;
// Standard Silverlight initialization
InitializeComponent();
// Phone 固有の初期化
InitializePhoneApplication();
ThemeManager.ToLightTheme();
動的処理なので、デザイン画面には反映されません。ですので、デバイスタブでライトテーマを指定します。
UIをつくる
PhoneApplicationPage の SystemTray.IsVisible はFalseにしておきましょう。
さらに、LayoutRoot の中をすべてく削除します。そこに以下のコードを挿入。ポイントはアニメーションするCanvasに変形の設定を入れておくこと。
<Grid x:Name="LayoutRoot" Background="Transparent">
<Canvas x:Name="triPainCanvas" Background="Transparent" Width="1180" Grid.Row="4" HorizontalAlignment="Center" >
<Grid HorizontalAlignment="Left" Height="800" VerticalAlignment="Top" Width="350" Margin="0" RenderTransformOrigin="0.5,0.5" Background="Black">
<Grid.RenderTransform>
<CompositeTransform/>
</Grid.RenderTransform>
</Grid>
<Grid Height="800" Canvas.Left="350" Canvas.Top="17" Width="480">
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="0,0,0,667">
<TextBlock Text="マイ アプリケーション" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="ページ名" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Margin="0,144,12,0"/>
</Grid>
<Grid HorizontalAlignment="Left" Height="800" VerticalAlignment="Top" Width="350" Background="Black" Canvas.Left="830"/>
</Canvas>
</Grid>
こんな感じです。Canvas でなく、Gridでもよさそうなのですが、Gridの場合右にはみ出た分は描画してくれないという特性があり、やめました。
移動するアニメーションを作る
移動するアニメーションです。今回は左にスライド、右にスライド、センターに戻るの3つ。
<phone:PhoneApplicationPage.Resources>
<Storyboard x:Name="RightPage">
<DoubleAnimation Duration="0:0:0.5" To="-350" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="triPainCanvas" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Name="LeftPage">
<DoubleAnimation Duration="0:0:0.5" To="350" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="triPainCanvas" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Name="CenterPage">
<DoubleAnimation Duration="0:0:0.5" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="triPainCanvas" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
< /phone:PhoneApplicationPage.Resources>
ページのスワイプ処理を追加します
MainPage.xaml.cs に実装します。指で移動しているときはそれに合わせて移動して、話した瞬間に右か左か真名に移動するアニメーションを実施します。コメント見ると何をやっているかの参考になるかも。
// コンストラクター
public MainPage()
{
InitializeComponent();
//スワイプのイベントハンドリングは、コンストラクターで実装しました。
triPainCanvas.ManipulationDelta += triPainCanvas_ManipulationDelta;
triPainCanvas.ManipulationCompleted += triPainCanvas_ManipulationCompleted;
}
// 変数は2つ、スライド中の移動量を覚えておく xswipe と、3つのどれかのページに寄った状態の offset。
double xswipe, offset = 0
// 指をスライドしているときはそれに合わせて画面も動かします。
private void triPainCanvas_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
xswipe = e.CumulativeManipulation.Translation.X + offset;
// 左右以上は動かないように
if (xswipe < -350) xswipe = -350;
else if (xswipe > 350) xswipe = 350;
triPainCanvas.RenderTransform = new TranslateTransform() { X = xswipe };
}
// 指を離した瞬間、それまでの移動方向と移動量でどちら側に寄せるか、センターに戻るかのアニメーションを表示します。
private void triPainCanvas_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
{
if (((xswipe - offset) < -100) && (xswipe < 0) && (offset == 0 )) {
//100ドット以上スワイプし、スワイプ方向が左方向の操作を真ん中の画面でしたとき
offset = -350;
RightPage.Begin();
}
else if (((xswipe - offset) > 100) && (xswipe > 0) && (offset == 0 )) {
//100ドット以上スワイプし、スワイプ方向が右方向の操作を真ん中の画面でしたとき
offset = 350;
LeftPage.Begin();
}
else {
//そのほかの場合はセンターに戻るアニメーション
offset = 0;
CenterPage.Begin();
}
}
1つ1つの動きを見てみると、どうやって実装したらよいのか見えてくると思いますよw