新しいFacebook のUIのような動きを実装する。

#wpdev_jp

新しいFacebook アプリが公開されました。左右にスワイプすると個別のメニューが表示されるUIになってます。こういったUIをどうやって作ったらいいのか?試してみました。

 

7.1のプロジェクトを作ります。

やらなくてもいいけどライトテーマの強制

まずは、ライトテーマの強制をします。自前でやるのは面倒なのでほかのライブラリを使います。

NuGet から ThemeManager を検索してインストールします。

image

App.xaml.cs でライトテーマの強制をします。

public App()
{
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;

    // Standard Silverlight initialization
InitializeComponent();

    // Phone 固有の初期化
InitializePhoneApplication();

    ThemeManager.ToLightTheme();

動的処理なので、デザイン画面には反映されません。ですので、デバイスタブでライトテーマを指定します。

image

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の場合右にはみ出た分は描画してくれないという特性があり、やめました。

image

 

移動するアニメーションを作る

移動するアニメーションです。今回は左にスライド、右にスライド、センターに戻るの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