在WP8.1应用程序中滚动和缩放图像的问题

时间:2015-03-05 20:22:14

标签: windows-runtime windows-phone-8.1 crop scrollviewer fileopenpicker

我正在努力使用Windows Phone 8.1(WinRT)应用中的ScrollViewer。基本上,我想要实现的是使用FileOpenPicker检索图像,将图像裁剪为固定比例(方形)格式,同时让用户选择图像的一部分和缩放级别,然后使用我的应用中的图像。 完美将是“人物”应用程序中的功能,您可以在其中添加图像到联系人,但如果我能以某种方式让它在没有ScrollView表现得太不稳定的情况下工作,我会满足于此。 / p>

以下是我尝试的其中一个变体:

<ScrollViewer x:Name="SelectedImageScrollViewer"
    ZoomMode="Enabled"
    HorizontalScrollBarVisibility="Auto"
    VerticalScrollBarVisibility="Auto"
    Height="300"
    Width="300" >
    <Image x:Name="SelectedImage"
        Source="{Binding SelectedImage}"
        MinHeight="300"
        MinWidth="300" />
</ScrollViewer>

并在代码隐藏中(在构造函数中):

if (SelectedImage.ActualHeight > SelectedImage.ActualWidth) {
    SelectedImage.Width = SelectedImageScrollViewer.ViewportWidth;
}
else {
    SelectedImage.Height = SelectedImageScrollViewer.ViewportHeight;
}

就像我说的那样,这并没有真正起作用,并且有几个问题:

  1. ScrollView内置了这种“橡皮筋”过度滚动功能。虽然我可以就平台一致性达成一致,但这里没有用,而且提到的“人物”应用程序也没有
  2. 当用户缩放到MaxZoomLevel以外时,缩放不会停止,但图像会在发布后漂移并快速恢复 - 这不是一个良好的用户体验。
  3. 可以使图像小于裁剪框。不应该将缩放级别降低到图像未填充视口的位置。
  4. ScrollView未显示图像的中心。
  5. 如何解决这些问题,以及裁剪和缩放图像的最佳方法是什么?如果它作为SDK的一部分在Silverlight(照片选择器)中可用,那就太好了。

1 个答案:

答案 0 :(得分:1)

以下解决方案提供了相当不错的用户体验。关于问题清单:

  1. 显然无法使用基本ScrollViewer解决。
  2. 将MaxZoomFactor增加到足够大的值使得用户不太可能看到问题。
  3. 将图像的较小尺寸设置为裁剪框尺寸后,MinZoomFactor为1可确保图像始终填充框架。
  4. ScrollView的偏移量可以在后面的代码中设置。
  5. IsScrollInertiaEnabledIsZoomInertiaEnabled设置为false可以消除滚动缩放时的一些不稳定行为。图像宽度和高度在SelectedImage_SizeChanged中设置,因为初始实际尺寸在构造函数中不可用(在呈现页面之前)。

    <ScrollViewer Grid.Row="1"
                  x:Name="SelectedImageScrollViewer"
                  ZoomMode="Enabled"
                  IsScrollInertiaEnabled="False"
                  IsZoomInertiaEnabled="False"
                  HorizontalScrollBarVisibility="Auto"
                  VerticalScrollBarVisibility="Auto"
                  Height="300"
                  Width="300"
                  MinZoomFactor="1.0"
                  MaxZoomFactor="10.0">
        <Image x:Name="SelectedImage"
               Source="{Binding SelectedImage}"
               HorizontalAlignment="Center"
               SizeChanged="SelectedImage_SizeChanged" />
    </ScrollViewer>
    

    private void SelectedImage_SizeChanged(object sender, SizeChangedEventArgs e) {
        // Here the proportions of the image are known and the initial size can be set
        // to fill the cropping frame depending on the orientation of the image.
    
        if (!_imageProportionsSet) {
            if (SelectedImage.ActualWidth != 0) {
    
                double actualHeight = SelectedImage.ActualHeight;
                double actualWidth = SelectedImage.ActualWidth;
                double viewPortWidth = SelectedImageScrollViewer.ViewportWidth;
                double viewPortHeight = SelectedImageScrollViewer.ViewportHeight;
    
                if (actualHeight > actualWidth) {
                    SelectedImage.Width = viewPortWidth;
                    double yOffset = (actualHeight - actualWidth) * viewPortWidth / actualHeight;
                    SelectedImageScrollViewer.ChangeView(0, yOffset, 1);
                }
                else {
                    SelectedImage.Height = viewPortHeight;
                    double xOffset = (actualWidth - actualHeight) * viewPortHeight / actualWidth;
                    SelectedImageScrollViewer.ChangeView(xOffset, 0, 1);
                }
    
                // Do this only once.
                _imageProportionsSet = true;
            }
        }
    }
    

    这是可行的。如果您发现任何问题,请不要犹豫,发表评论或提供更好的答案。