2011年5月7日土曜日

pivotでスワイプ操作

WP7 Silverlight で GoogleReader クライアントを作っていますが、その作業中にやったことを紹介していこうと思います


Readerの記事送り操作にスワイプ(フリック?)で前後へ移動できるようにしてみました
具体的にはPivotを使います。

全部の記事リストをpivot itemに突っ込んでしまうのはリソースを食らいすぎると思われるのでcurrentのページと前後のページで 3item をあらかじめ作りました。

こんなイメージ

この3つは繋がっているのでスワイプでぐるぐる回して切り替え表示ができます。



pivo tの xaml
<controls:Pivot Name="pivot1" Title="uGReader" ItemsSource="{Binding items}"
     HeaderTemplate="{StaticResource HeaderTemplate}"
      ItemTemplate="{StaticResource PivotItemTemp}"
      d:DataContext="{d:DesignData SampleData/ContentSampleData.xaml}"
      SelectionChanged="pivot1_SelectionChanged" LoadedPivotItem="pivot1_LoadedPivotItem">
</controls:Pivot>
Header , Item の表示内容はtemplateで指定しています

template定義
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="HeaderTemplate">
    <StackPanel Orientation="Vertical" Width="400" Margin="0">
        <TextBlock Text="{Binding bTitle}" FontSize="22" TextAlignment="Left" HorizontalAlignment="Left" 
                    Width="400"
                    TextWrapping="Wrap" />
        <StackPanel Orientation="Horizontal">
            <ToggleButton Content="ToggleButton" 
                    HorizontalAlignment="Right" 
                            Width="20" 
                            Height="20" 
                    Margin="8,0,8,0"
                    IsChecked="{Binding bStared}"
                    Style="{StaticResource StarButtonStyle}" 
                    VerticalAlignment="Center" 
                            Click="ToggleButton_Click" />
            <TextBlock Text="{Binding bSiteTitle}"  FontSize="20" />
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding bAuthor}" FontSize="20" Margin="0,0,18,0"/>
            <TextBlock Text="{Binding bPublished}" FontSize="20" />
        </StackPanel>
    </StackPanel>
</DataTemplate>
<DataTemplate x:Key="PivotItemTemp">
    <Grid Margin="0,-20,0,0">
        <phone:WebBrowser local:BrowserBehavior.DocumentText="{Binding bContent}" Margin="8,0,8,20" >
        </phone:WebBrowser>
    </Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>

public ObservableCollection<ReaderItem> items { get; set; }
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    items.Add(App.Items[seldIndex]);
    items.Add(App.Items[seldIndex + 1]);
    items.Add(App.Items[seldIndex - 1]);
    pivot1.ItemsSource = items;
}



これでApp.Items リスト(ReaderItemクラス)の プロパティ bTitle,bStar,bAuthor,bPublished 等の内容をヘッダーに、bContentをpivotアイテムパネルに表示します。実際はseldIndexの決定や、リストの範囲チェックなどもします。
ContentsはHtml文字列なので、WebBrowserコンポーネントにbindしました。ただし、直接WebBrowsrコンポーネントにバインドできないので依存プロパティ? BrowserBehavior.DocumentText とやらを作って実現しました。(殆どサンプルソースをコピーしただけですが、後に紹介したいと思います)



スワイプで記事を切り替える処理はLoadedPivotItemイベントでcurrent以外のitemを書き換えて行いました
private void pivot1_LoadedPivotItem(object sender, PivotItemEventArgs e)
{
    seldIndex = App.Items.IndexOf((ReaderItem)pivot1.SelectedItem);
    int i = pivot1.SelectedIndex + 1;
    if (i > 2)
        i -= 3;
    if (seldIndex + 1 < App.Items.Count)
    {
        if (items[i] != App.Items[seldIndex + 1])
            items[i] = App.Items[seldIndex + 1];
    }
    else
        items[i] = FootItem;

    if (++i > 2)
        i -= 3;
    if (seldIndex > 0)
    {
        if (items[i] != App.Items[seldIndex - 1])
            items[i] = App.Items[seldIndex - 1];
    }
    else
        items[i] = HeadItem;

}

ここでも実際は範囲チェックとかもします。
だいたいこんな感じで記事をフリック操作でどんどん送って表示できました。

やってることはPivotItemのロードタイミングでリストを書き換えるだけですが、これだけの事ができるのは面白いですね



ただし問題が2点ほどあります

  1. WebBrowserコンポーネント上でスワイプしても記事送りになりません。Webページの横スクロール操作になります。
  2. Pivotのヘッダに記事タイトルを表示していますが、タイトル文字列が大きいと改行されてヘッダの高さが大きくなってしまいます。しかも一旦大きくなったヘッダはその後タイトル文字が少なくなっても小さくならない


こんな感じ↓で次の記事のタイトルが長いのでヘッダが大きくなってしまい記事とヘッダの間に空白ができるている


さらに一度大きくなったヘッダは小さくならない?

Posted by Picasa

0 件のコメント: