Sub*_*ion 10 silverlight layout xaml stackpanel windows-phone-7
我遇到了一些问题,创建了一个非常类似于相机应用程序中的照片条的效果.
我想要做的就是显示一行网格,每个网格都有与屏幕相同的尺寸(无论是纵向还是横向).我必须做一些hacky并创建依赖属性,网格宽度和高度属性绑定到这些属性以保持宽高比.
这很好用.但是当我为我的条带创建一个StackPanel并实现我的导航(或者只是使用z-index变换缩放)时,我发现我的StackPanel不能显示大于屏幕尺寸(它被裁剪为只有一个网格的大小) .我以为我找到了一篇描述这个问题的帖子,但我现在找不到了 - 如果您知道我正在考虑哪个帖子,或者您对此限制有更多了解,请发帖.
我发现的唯一解决方法是使用ScrollViewer,这绝对不是我想要的行为,但它允许StackPanel比屏幕宽.
我真正的问题是ScrollViewer的行为 - 因为我需要从网格跳到网格(就像照片条那样)而不是自由滚动,据我所知,HorizontalOffset不是一个可动画的属性.我可以通过每15毫秒调用ScrollToHorizontalOffset强制它动画,基本上手动实现我自己的缓动效果.这看起来像是一个巨大的黑客,而且行为非常微不足道(要么我每次都没有得到ManipulationCompleted事件 - 在每次滑动操作结束时 - 或者ScrollViewer的内置惯性物理干扰我的效果).
有没有人知道我遇到的问题的更好的解决方法,或者在Silverlight中获得相机照片条的体验的完全不同的方式?
我考虑过使用Pivot控件,但它并不是我想要的(如果我希望每个项目在下一个项目进入之前完全动画化,而不是看起来全部附加到一个条带上,那么应该有更少的约束实现这一目标的方法).更重要的是,条带只是我希望能够动态执行的众多效果之一.我想交替使用类似CoolIris的3D倾斜或FlipPad风格的翻页.我相信如果我能够很好地使我当前的设置工作,那么很容易实现这些其他效果(作为可变转换).致力于像Pivot这样的控制不会让我更接近这个愿景.
这是我的XAML:
<Grid x:Name="LayoutRoot" Background="Transparent" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" HorizontalAlignment="Left" VerticalAlignment="Top">
<ScrollViewer x:Name="SlideScroller" VerticalScrollBarVisibility="Disabled" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" Margin="0,0,0,-31" ScrollViewer.HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Left" VerticalAlignment="Top">
<StackPanel x:Name="SlidePanel" Orientation="Horizontal" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" VerticalAlignment="Top" HorizontalAlignment="Left">
<Grid x:Name="Slide0" Margin="0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" Background="#FFCCCCCC">
<Image x:Name="Photo0" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" VerticalAlignment="Top" HorizontalAlignment="Left" Stretch="UniformToFill"/>
</Grid>
<Grid x:Name="Slide1" Margin="0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" Background="#FFCCCCCC">
<Image x:Name="Photo1" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" VerticalAlignment="Top" HorizontalAlignment="Left" Stretch="UniformToFill"/>
</Grid>
<Grid x:Name="Slide2" Margin="0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" Background="#FFCCCCCC">
<Image x:Name="Photo2" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" VerticalAlignment="Top" HorizontalAlignment="Left" Stretch="UniformToFill"/>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
Run Code Online (Sandbox Code Playgroud)
事实证明,如果我只是防止 ScrollViewer 被用户直接操作并手动定位它,我描述的设置效果很好。这消除了导致我提到的大部分故障的物理效应。
XAML
<ScrollViewer x:Name="SlideScroller" VerticalScrollBarVisibility="Disabled" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" ScrollViewer.HorizontalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Visible" HorizontalAlignment="Left" VerticalAlignment="Top">
<StackPanel x:Name="SlidePanel" Orientation="Horizontal" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" VerticalAlignment="Top" HorizontalAlignment="Left">
</StackPanel>
</ScrollViewer>
<Rectangle x:Name="ScrollInterceptRect" Margin="0,0,0,-31" Width="{Binding RealWidth, ElementName=phoneApplicationPage}" Height="{Binding RealHeight, ElementName=phoneApplicationPage}" HorizontalAlignment="Left" VerticalAlignment="Top">
Run Code Online (Sandbox Code Playgroud)
代码隐藏
public MainPage()
{
InitializeComponent();
ScrollInterceptRect.MouseLeftButtonUp += new MouseButtonEventHandler(ScrollInterceptRect_MouseLeftButtonUp);
ScrollInterceptRect.MouseLeftButtonDown += new MouseButtonEventHandler(ScrollInterceptRect_MouseLeftButtonDown);
ScrollInterceptRect.MouseMove += new MouseEventHandler(ScrollInterceptRect_MouseMove);
}
//...
NavigationIndices navigationIndices = new NavigationIndices();
readonly double swipeThreshold = 80.0;
SwipeDirection swipeDirection;
bool tapCancelled;
Point swipeDelta;
Point swipeStartPosition;
double startScrollOffsetX;
void SlideScroller_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
swipeStartPosition = e.GetPosition(this);
startScrollOffsetX = SlideScroller.HorizontalOffset;
}
void ScrollInterceptRect_MouseMove(object sender, MouseEventArgs e)
{
Point touchPosition = e.GetPosition(this);
swipeDelta = new Point() { X = swipeStartPosition.X - touchPosition.X, Y = swipeStartPosition.Y - touchPosition.Y };
SlideScroller.ScrollToHorizontalOffset(startScrollOffsetX + swipeDelta.X);
// swipe right
if (swipeDelta.X > swipeThreshold)
{
swipeDirection = SwipeDirection.Left;
tapCancelled = true;
}
// swipe left
else if (swipeDelta.X < -swipeThreshold)
{
swipeDirection = SwipeDirection.Right;
tapCancelled = true;
}
}
void ScrollInterceptRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (swipeDirection == SwipeDirection.Left && navigationIndices.X < photos.Count - 1 && photos[navigationIndices.X] != null)
{
navigationIndices.X++;
}
// only go back when you aren't already at the beginning
else if (swipeDirection == SwipeDirection.Right && navigationIndices.X > 0)
{
navigationIndices.X--;
}
if (!tapCancelled)
{
// handle tap
}
else
{
animateScrollViewerToCurrentPhoto();
}
}
Run Code Online (Sandbox Code Playgroud)
为了清楚起见,这被简化了一点(我还在我的应用程序中使用垂直滑动,并且我省略了如何对 ScrollViewer 进行动画处理 - 可能值得它自己的帖子)。
我很想听听您对此可以提供的任何改进,或者关于更好的实施方法的建议。也许扩展面板类或作为自定义行为。想法?
| 归档时间: |
|
| 查看次数: |
400 次 |
| 最近记录: |