【问题标题】:How to have photo viewer style pages? [closed]如何拥有照片查看器样式页面? [关闭]
【发布时间】:2013-06-28 22:43:50
【问题描述】:

我不知道我是否命名正确,但我有一个显示一排图片的应用程序。如果用户向左滑动会出现全屏的上一张图片,如果向右滑动则会出现全屏的下一张图片,两者的动作与在照片应用程序或 PDF 阅读器中查看图片完全相同。我以为我可以操纵全景控件来适应这个,但我无法全屏显示图片,并且顶部有标题的位置。

我该怎么做?任何提示

注意:有关此 stackoverflow 的政策令人讨厌。有些人可以投票关闭,或者说一句sn-ps:你尝试了什么或者你的代码在哪里。从基础关闭这个问题以获得良好的感觉。

这是关于要求指南有一种查看方式。如果不知道如何执行,我应该显示什么代码?无论如何,我找到了答案,不需要这个。

【问题讨论】:

  • @all,如果您决定投反对票,请考虑在投票后解释!
  • 这是因为尽管您解释了您的问题,但您没有显示任何行为不符合预期的代码或您的任何编码工作。
  • 感谢@TI,但有时没有代码,也不知道如何执行它。我可以添加一个愚蠢的全景代码并说看我无法删除顶部空间,但什么是好处?

标签: c# xaml windows-phone-8 windows-phone


【解决方案1】:

我会告诉你我做了什么,也许你会觉得它足够了。我想要一个全屏图像查看器,它可以让我滑动到下一个(或上一个)图像,但让它捕捉到图像而不是正常滚动。

我使用了一个禁用了内部 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 内的滚动查看器的永久引用:

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 虚拟化之外,我所做的完整实现还包括数据虚拟化。那和缩放。它还没有完全准备好发布,但这会让你开始。

【讨论】:

  • 感谢@lee 的回答并提到“滑动”这个词,我说的是“翻转”?天哪,我要睡觉了。在询问后,我尝试并最终操作了一个枢轴控件。我会检查这个作为答案
  • 是的,在全部输入后,我认为只需摆脱枢轴控件上的标题即可。不过,我认为您无法通过 Pivot 控件获得虚拟化,因此如果您使用许多图像,则可能需要实现手动数据虚拟化。
  • 嗨,李。您能否解释一下 (double)vm.Position 值是什么?
  • vm 是对我的 ViewModel 的引用。在其中,有一个 Position 属性(双精度),我通过将滚动查看器的内容宽度除以每个“窗口”的大小来计算它。这完全取决于你如何做。 (虽然我在我的代码中使用了 MVVM 框架,但我并没有完全遵守 MVVM 原则。)实际上,我记错了。查看代码上方的文字。我描述了如何计算 vm.Position。 vm.Position = scrollviewer 水平偏移量。
  • 这实际上好多了。查看此示例解决方案中的 MediaViewer 项目:code.msdn.microsoft.com/wpapps/Basic-Lens-sample-359fda1b/view/…
猜你喜欢
  • 2011-05-09
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
相关资源
最近更新 更多