2

名前が正しいかどうかはわかりませんが、写真を並べて表示するアプリがあります。ユーザーが左にスワイプすると全画面表示の前の画像が表示され、右にスワイプすると全画面表示で次の画像が表示されます。両方の動きは、写真アプリまたは PDF リーダーで画像を表示するのとまったく同じです。これに合わせてパノラマ コントロールを操作できると思ったのですが、画像を全画面表示できず、上部にタイトルの場所があります。

どうやってやるの?任意のヒント

注:このスタック オーバーフローのポリシーは面倒です。締めくくりに投票したり、いくつかの文のスニペットを言うことができるタイプの人々がいます:何を試したのか、コードはどこにありますか。いい感じになるように、この質問をベースから閉じてください。

これは、ガイドに表示スタイルを求めることです..実行方法がわからない場合は、どのコードを表示すればよいですか? とにかく、私は自分の答えを見つけました。これは必要ありません。

4

1 に答える 1

4

私が何をしたかをお話しします。おそらくそれで十分だと思います。次の (または前の) 画像にスワイプできるフルスクリーンの画像ビューアーが必要でしたが、通常のスクロールではなく、画像にスナップすることができました。

内部 scrollViewer を無効にしてフルスクリーンの ListBox を使用し (XAML を参照)、添付の依存関係プロパティを使用して、内部 scrollViewer の水平 (および垂直) オフセットのプロパティを取得しました (スクロールを自分でアニメーション化できるようにするため)。画像をズーム (およびパン) したかったので、私の実装はもっと複雑ですが、次の画像に移動するだけの部分は難しくありません。

免責事項: StackOverflow や他のサイトのいくつかのソースからコードを取得しました。どこで手に入れたのかもう覚えていませんが、これらのアイデアはすべて自分で思いついたわけではありません。どこでそれを与えるべきか知っていれば、私は喜んで信用を与えます.

まず、ScrollViewerEx という新しいクラスを作成します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace ImageViewer    
{
    public class ScrollViewerEx
    {
    public static double GetHOffset(ScrollViewer obj)
    {
        return (double)obj.GetValue(ScrollViewer.HorizontalOffsetProperty);
    }

    public static void SetHOffset(ScrollViewer obj, double value)
    {
        obj.SetValue(HOffsetProperty, value);
    }

    // Using a DependencyProperty as the backing store for HOffset.  This enables animation, styling, binding, etc...  
    public static readonly DependencyProperty HOffsetProperty =
        DependencyProperty.RegisterAttached("HOffset", typeof(double), typeof(ScrollViewerEx), new PropertyMetadata(new PropertyChangedCallback(OnHOffsetChanged)));


    private static void OnHOffsetChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var scroll = sender as ScrollViewer;

        scroll.ScrollToHorizontalOffset((double)e.NewValue);
    }

    public static double GetVOffset(ScrollViewer obj)
    {
        return (double)obj.GetValue(ScrollViewer.VerticalOffsetProperty);
    }

    public static void SetVOffset(ScrollViewer obj, double value)
    {
        obj.SetValue(VOffsetProperty, value);
    }

    // Using a DependencyProperty as the backing store for VOffset.  This enables animation, styling, binding, etc...  
    public static readonly DependencyProperty VOffsetProperty =
        DependencyProperty.RegisterAttached("VOffset", typeof(double), typeof(ScrollViewerEx), new PropertyMetadata(new PropertyChangedCallback(OnVOffsetChanged)));


    private static void OnVOffsetChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var scroll = sender as ScrollViewer;

        scroll.ScrollToVerticalOffset((double)e.NewValue);
    }
}  

}

さて、以下のようなリストボックスが用意されているとしましょう。私の場合、Images プロパティは PictureModel というクラスで、内部には ImageSource がありました。私は ItemTemplate を表示していませんが、Image を内部に配置し、Source を ImageSource にバインドするだけです。ListBox の下の Rectangle に注目してください。ズームされた画像を使用していたときに座標系が変化していたため、すべてのタッチコードをそこに置きました。Rectangle オーバーレイを使用すると、すべてのタッチに対して標準の画面座標が得られます。これは必要ないかもしれません。

    <ListBox ItemsSource="{Binding Images}"
             x:Name="listBox"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled"
             ScrollViewer.VerticalScrollBarVisibility="Disabled"
             ScrollViewer.ManipulationMode="Control"
             Loaded="listBox_Loaded_1" 

                  >
        <ListBox.Resources>
            <Storyboard x:Name="ScrollStoryboard">
                <DoubleAnimation x:Name="AnimationH" Duration="0:0:0.5">
                    <DoubleAnimation.EasingFunction>
                        <CubicEase EasingMode="EaseInOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>
                <DoubleAnimation x:Name="AnimationV" Duration="0:0:0.5">
                    <DoubleAnimation.EasingFunction>
                        <CubicEase EasingMode="EaseInOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>
            </Storyboard>
        </ListBox.Resources>
        <ListBox.ItemContainerStyle>
            <StaticResource ResourceKey="ListBoxItemPivotStyle"/>
        </ListBox.ItemContainerStyle>
    </ListBox>
    <Rectangle Fill="Transparent"
               x:Name="TouchRectangle"
               ManipulationCompleted="Rectangle_ManipulationCompleted_1"
               ManipulationDelta="Rectangle_ManipulationDelta_1"
               ManipulationStarted="Rectangle_ManipulationStarted_1"/>

わかりました、別のクリティカル セクションです。ページのコンストラクターに THIS を必ず入れてください。これにより、スクロールビューアのオフセットの変更をアニメーション化できます。

Storyboard.SetTargetProperty(ScrollStoryboard.Children[0], new PropertyPath(ScrollViewerEx.HOffsetProperty));
Storyboard.SetTargetProperty(ScrollStoryboard.Children[1], new PropertyPath(ScrollViewerEx.VOffsetProperty));

ListBox 内の scrollviewer への永続的な参照を取得します。

private void listBox_Loaded_1(object sender, RoutedEventArgs e)
    {
        scrollviewer = GetVisualChild<ScrollViewer>(listBox);
    }

最後に、操作イベントを処理します。リストボックスのスクロールをアニメーション化するために重要なのは、操作完了イベントです。垂直オフセットは使用せず、水平オフセットのみを使用しました。変数 vm.Position は、scrollviewer.horizo​​ntaloffset に沿って計算された位置です。基本的に、5 番目の画像を使用している場合は、画面幅を 4 倍して水平方向のオフセットを取得します。

private void Rectangle_ManipulationCompleted_1(object sender, ManipulationCompletedEventArgs e)
{
    if (e.FinalVelocities.LinearVelocity.X > 2000)
        {

                if (ScrollStoryboard.GetCurrentState() != ClockState.Stopped)
                    ScrollStoryboard.Stop(); // ensure storyboard stopped after previous run  
                AnimationH.SetValue(DoubleAnimation.FromProperty, scrollviewer.HorizontalOffset);
                AnimationH.SetValue(DoubleAnimation.ToProperty, (double)vm.Position);
                Storyboard.SetTarget(ScrollStoryboard, scrollviewer);
                ScrollStoryboard.Begin();


        }
}

これが役立つことを願っています。前述したように、私が作成した完全な実装には、ListBox から得られる組み込みの UI 仮想化に加えて、データ仮想化が含まれています。それとズーム。公開する準備が整っていませんが、これで始めることができます。

于 2013-06-29T00:24:06.867 に答える