簡體   English   中英

如何在 WP7 上實現相機應用風格的照片條?

[英]How to implement Camera app style photo strip on WP7?

在創建與相機應用程序中的照片條非常相似的效果時,我遇到了許多問題。

我要做的就是顯示一行網格,每個網格的尺寸都與屏幕相同(無論是縱向還是橫向)。 已經,我不得不做一些 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>

事實證明,如果我只是防止 ScrollViewer 被用戶直接操作並手動操作 position,那么我描述的設置效果很好。 這消除了導致我提到的大部分故障的物理效應。

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">

代碼隱藏

    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();
        }
    }

為了清楚起見,這被簡化了一點(我還在我的應用程序中使用了垂直滑動,我省略了我如何為 ScrollViewer 設置動畫 - 可能值得它自己的帖子)。

我很想聽聽您對此提供的任何改進,或者關於更好地實現它的建議。 也許擴展面板 Class 或作為自定義行為。 想法?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM