在 WP8.1 应用程序中滚动和缩放图像时出现问题
Problems Scrolling and Zooming an Image in an WP8.1 App
我在 Windows Phone 8.1 (WinRT) 应用程序中遇到 ScrollViewer
问题。基本上,我想要实现的是使用 FileOpenPicker
检索图像,将图像裁剪为固定比例(正方形)格式,同时让用户 select 图像的一部分和缩放级别,然后在我的应用程序中使用该图像。 与 "People" 应用程序中的功能一样完美,您可以在其中向联系人添加图像,但如果我能以某种方式让它在没有 ScrollView 的情况下工作,我会接受更少太古怪了
这是我尝试过的变体之一:
<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;
}
就像我说的,这不是真的有效,而且有几个问题:
ScrollView
s 内置了这种 "rubber band" 过度滚动功能。虽然我同意平台统一性,但在这里它没有帮助,而且提到的 "People" 应用程序没有也没有。
- 当用户缩放超过
MaxZoomLevel
时,缩放不仅会停止,而且图像会漂移并在释放后快速返回 - 这不是很好的用户体验。
- 图片可以小于裁剪框。应该不可能将缩放级别降低到图像未填满视口的程度。
ScrollView
没有显示图片的中心。
如何解决这些问题,裁剪和缩放图像的最佳方法是什么?如果它像在 Silverlight(照片选择器)中一样作为 SDK 的一部分提供,那就太好了。
以下解决方案提供了相当不错的用户体验。关于问题列表:
- 显然无法使用基本的
ScrollViewer
. 解决
- 将 MaxZoomFactor 增加到足够大可以让用户不太可能发现问题。
- 将图像的较小尺寸设置为裁剪框大小后,
MinZoomFactor
为 1 可确保图像始终填满框架。
ScrollView
的偏移量可以在后面的代码中设置。
将 IsScrollInertiaEnabled
和 IsZoomInertiaEnabled
设置为 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;
}
}
}
这是可行的。如果您发现任何问题,请不要犹豫发表评论或提供改进的答案。
我在 Windows Phone 8.1 (WinRT) 应用程序中遇到 ScrollViewer
问题。基本上,我想要实现的是使用 FileOpenPicker
检索图像,将图像裁剪为固定比例(正方形)格式,同时让用户 select 图像的一部分和缩放级别,然后在我的应用程序中使用该图像。 与 "People" 应用程序中的功能一样完美,您可以在其中向联系人添加图像,但如果我能以某种方式让它在没有 ScrollView 的情况下工作,我会接受更少太古怪了
这是我尝试过的变体之一:
<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;
}
就像我说的,这不是真的有效,而且有几个问题:
ScrollView
s 内置了这种 "rubber band" 过度滚动功能。虽然我同意平台统一性,但在这里它没有帮助,而且提到的 "People" 应用程序没有也没有。- 当用户缩放超过
MaxZoomLevel
时,缩放不仅会停止,而且图像会漂移并在释放后快速返回 - 这不是很好的用户体验。 - 图片可以小于裁剪框。应该不可能将缩放级别降低到图像未填满视口的程度。
ScrollView
没有显示图片的中心。
如何解决这些问题,裁剪和缩放图像的最佳方法是什么?如果它像在 Silverlight(照片选择器)中一样作为 SDK 的一部分提供,那就太好了。
以下解决方案提供了相当不错的用户体验。关于问题列表:
- 显然无法使用基本的
ScrollViewer
. 解决
- 将 MaxZoomFactor 增加到足够大可以让用户不太可能发现问题。
- 将图像的较小尺寸设置为裁剪框大小后,
MinZoomFactor
为 1 可确保图像始终填满框架。 ScrollView
的偏移量可以在后面的代码中设置。
将 IsScrollInertiaEnabled
和 IsZoomInertiaEnabled
设置为 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;
}
}
}
这是可行的。如果您发现任何问题,请不要犹豫发表评论或提供改进的答案。