The following forum(s) have migrated to Microsoft Q&A (Preview): Developing Universal Windows apps!
Visit Microsoft Q&A (Preview) to post new questions.

Learn More

 locked
ScrollViewer Snapping RRS feed

  • Question

  • I have this ScrollViewer, on a Windows Phone 8 project

    <ScrollViewer Name="MediaScroll" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" Background="#7FD13E3E" Tap="ScrollViewer_Tap" VerticalAlignment="Top" LayoutUpdated="MediaScroll_LayoutUpdated">
                <ItemsControl ItemTemplate="{StaticResource ItemTemplate2}" ItemsPanel="{StaticResource ItemsPanelTemplate1}" ItemsSource="{Binding listaMedia}">
    
                </ItemsControl>
            </ScrollViewer>

    that uses these templates

        <phone:PhoneApplicationPage.Resources>
    
        <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
            <StackPanel Orientation="Horizontal" Margin="0,0,0,0"/>
        </ItemsPanelTemplate>
    
        <DataTemplate x:Key="ItemTemplate2">
    
            <StackPanel Width="480">
                <Image Source="/Assets/play@2x.png" Width="75" Canvas.ZIndex="10" Margin="203,85,202,0"  />
                <Image Source="{Binding snapshot.path}" Stretch="Fill" VerticalAlignment="Top" Margin="0,-160,0,0" />
            </StackPanel>
            <!--<Image Tag="{Binding id}"  Source="{Binding snapshot.path}" Width="150" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="-10,0,-9,0" Tap="Image_Tap" />-->
            <!--Your other code-->
        </DataTemplate>
    
    </phone:PhoneApplicationPage.Resources>

    i get a list with images and the scroll shows them horizontally. When i scroll i want to ScrollViewer to Snap to the nearest image, meaning that if the scroll is showing parts of 2 images, it Scrolls automatically to the nearest image and shows that one. I dont want the scroll to show 2 halfs of 2 images basically

    not sure if i can do that with the LayoutUpdated event.

    Wednesday, January 29, 2014 4:36 PM

Answers

  • You can do this if you know the exact sizes of the images and how many you have.  Here's a proof-of-concept:
    <ScrollViewer Height="500" Width="400" x:Name="MyScrollViewer" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Hidden"  LayoutUpdated="MyScrollViewer_LayoutUpdated">
      <StackPanel HorizontalAlignment="Left">
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
      </StackPanel>
    </ScrollViewer>

    private void MyScrollViewer_LayoutUpdated(object sender, EventArgs e)
    {
      int TotalHeight = (int) MyScrollViewer.ExtentHeight;
      int HeightOfImage = 250;
      int Remainder = ((int)MyScrollViewer.VerticalOffset) % HeightOfImage;
      if ( Remainder != 0)
      {
      if (Remainder < 125 && MyScrollViewer.VerticalOffset < 2500) MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.VerticalOffset - Remainder);
      else if (Remainder > 125 && MyScrollViewer.VerticalOffset < 2500) MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.VerticalOffset + Remainder);
      else MyScrollViewer.ScrollToVerticalOffset(2500);
      }
    }


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, January 30, 2014 2:05 PM

All replies

  • Consider using Panorama instead.

    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Thursday, January 30, 2014 1:54 PM
  • You can do this if you know the exact sizes of the images and how many you have.  Here's a proof-of-concept:
    <ScrollViewer Height="500" Width="400" x:Name="MyScrollViewer" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Hidden"  LayoutUpdated="MyScrollViewer_LayoutUpdated">
      <StackPanel HorizontalAlignment="Left">
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
      </StackPanel>
    </ScrollViewer>

    private void MyScrollViewer_LayoutUpdated(object sender, EventArgs e)
    {
      int TotalHeight = (int) MyScrollViewer.ExtentHeight;
      int HeightOfImage = 250;
      int Remainder = ((int)MyScrollViewer.VerticalOffset) % HeightOfImage;
      if ( Remainder != 0)
      {
      if (Remainder < 125 && MyScrollViewer.VerticalOffset < 2500) MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.VerticalOffset - Remainder);
      else if (Remainder > 125 && MyScrollViewer.VerticalOffset < 2500) MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.VerticalOffset + Remainder);
      else MyScrollViewer.ScrollToVerticalOffset(2500);
      }
    }


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, January 30, 2014 2:05 PM
  • LoopingSelector snaps its items. It is in the Windows Phone Toolkit and is the basis for TimePicker and DatePicker. It can be customized to horizontal orientation.

    http://www.geekchamp.com/articles/wp7-loopingselector-in-depth--part1-visual-structure-and-api

    Thursday, January 30, 2014 4:47 PM
  • You can do this if you know the exact sizes of the images and how many you have.  Here's a proof-of-concept:
    <ScrollViewer Height="500" Width="400" x:Name="MyScrollViewer" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Hidden"  LayoutUpdated="MyScrollViewer_LayoutUpdated">
      <StackPanel HorizontalAlignment="Left">
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
        <Image Source="Assets/ApplicationIcon.png" Width="246" Height="246" Margin="2"/>
      </StackPanel>
    </ScrollViewer>

    private void MyScrollViewer_LayoutUpdated(object sender, EventArgs e)
    {
      int TotalHeight = (int) MyScrollViewer.ExtentHeight;
      int HeightOfImage = 250;
      int Remainder = ((int)MyScrollViewer.VerticalOffset) % HeightOfImage;
      if ( Remainder != 0)
      {
      if (Remainder < 125 && MyScrollViewer.VerticalOffset < 2500) MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.VerticalOffset - Remainder);
      else if (Remainder > 125 && MyScrollViewer.VerticalOffset < 2500) MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.VerticalOffset + Remainder);
      else MyScrollViewer.ScrollToVerticalOffset(2500);
      }
    }


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Hi I tried implementing your method, but instead of going vertical I set it to horizontal.  Problem is that it always tends to go back to the original state. This is what I did. 

           <ScrollViewer Name="myScrollViewer" Width="960" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="0,150,0,0" LayoutUpdated="LineupSV_LayoutUpdated">
                    </ScrollViewer>

    private void myScrollViewer_LayoutUpdated(object sender, EventArgs e)
            {
                int TotalWidth = (int)myScrollViewer.ExtentWidth;
                int WidthOfGrid = 480;
                int Remainder = ((int)myScrollViewer.HorizontalOffset) % WidthOfGrid;
               if (Remainder != 0)
                {
                    if (Remainder < 240 && myScrollViewer.HorizontalOffset < 960) myScrollViewer.ScrollToHorizontalOffset(myScrollViewer.HorizontalOffset - Remainder);
                    else if (Remainder > 240 && myScrollViewer.HorizontalOffset < 960) myScrollViewer.ScrollToHorizontalOffset(myScrollViewer.HorizontalOffset + Remainder);
                    else myScrollViewer.ScrollToHorizontalOffset(960);
                }
            }

    Tuesday, April 8, 2014 6:10 AM