×
Namespaces

Variants
Actions
(Difference between revisions)

Image scrolling synced with large text scrolling

From Nokia Developer Wiki
Jump to: navigation, search
hamishwillee (Talk | contribs)
m (Hamishwillee - Bot update - Fix metadata)
hamishwillee (Talk | contribs)
m (Hamishwillee - Minor subedit)
Line 1: Line 1:
 
[[Category:Windows Phone 8]][[Category:UI on Windows Phone]][[Category:Code Examples]][[Category:XAML]]
 
[[Category:Windows Phone 8]][[Category:UI on Windows Phone]][[Category:Code Examples]][[Category:XAML]]
{{Abstract|This article explains how to auto scroll a large image in sync with a large text }}
+
{{Abstract|This article explains how to auto scroll a large image in sync with large text.}}
  
 
{{ArticleMetaData <!-- v1.3 -->
 
{{ArticleMetaData <!-- v1.3 -->
Line 24: Line 24:
 
== Introduction ==
 
== Introduction ==
  
Sometimes you have a page that will contain a lot of text, but with that text there is also an accompanying image. Putting the image in full height on that page won't give us the needed space for showing enough readable text.
+
Sometimes you have a page that contains both a large image and a lot of text. The best UI would be to display both, but there simply isn't enough room on the screen. The temptation is to crop the image height in order to keep enough text displayed, but this doesn't always work effectively, particularly with larger images.  
So to solve this we will cut off the image height and let it scroll into view while the user is scrolling the readable text.
+
  
It's a small image parallax effect, but the image is kept in the same place on the page.
+
This article outlines another solution to this problem: display part of the image at the top of the page with the text below - then scroll the part of the image that is displayed at the same time as the readable text (the position of the area where the image is displayed does not change).
  
 
<gallery widths="250px" heights="400px">
 
<gallery widths="250px" heights="400px">
Line 34: Line 33:
 
</gallery>
 
</gallery>
  
== Summary ==
+
== Implementation ==
  
To keep enough text readable for the user, we tend to keep our image height low, but this could be a problem with larger images. So to allow the user to view the full image, we track the {{Icode|ScrollViewer}} of the text part and slide the image into view accordingly!
+
To allow the user to view the full image, we track the {{Icode|ScrollViewer}} of the text part and slide the image into view accordingly.
The layout of such a page is very simple, you'll only need an image and some text and we put this inside the '''ContentPanel'''.
+
 
 +
The layout of such a page is very simple, you'll only need an image and some text and we put this inside the {{Icode|ContentPanel}}.
  
 
<code xml>
 
<code xml>
Line 75: Line 75:
 
</code>
 
</code>
  
With this '''xaml''' in place, you've already added the needed image animation! It's done through use of a {{Icode|CompositeTransform}} that will change the Y value representing the vertical axis image offset.
+
With this XAML in place, you've already added the needed image animation. It's done through use of a {{Icode|CompositeTransform}} that will change the Y value representing the vertical axis image offset.
We are hooking up '''TranslateY''' value to the {{Icode|ScrollViewer}} of the text, so that the image animation will be kept in sync with the text scroll movement of the user.
+
  
Only thing left to do, is figure out how much we need to slide the image in reference to the scroll offset of the {{Icode|ScrollViewer}}! Because with a very large text, the image will slide slowly upwards, but with a small text, the animation will be faster.
+
We are hooking up {{Icode|TranslateY}} value to the {{Icode|ScrollViewer}} of the text, so that the image animation will be kept in sync with the text scroll movement of the user.
This calculation is done when the detail page is loaded and passed along to the {{Icode|ScrollViewerOffsetConverter}}, that will a set the offset '''TranslateY''' value.
+
  
In the code behind of the detail page we will do the actual calculation by the '''OnLayoutUpdated''' event of the {{Icode|ContentPanel}}. This is needed to be sure that the '''ScrollableHeight''' of the {{Icode|ScrollViewer } is populated, because it will only be available when the full text has been initialized by the page.
+
Only thing left to do, is figure out how much we need to slide the image in reference to the scroll offset of the {{Icode|ScrollViewer}}. Because with a very large text, the image will slide slowly upwards, but with a small text, the animation will be faster.
 +
 
 +
This calculation is done when the detail page is loaded and passed along to the {{Icode|ScrollViewerOffsetConverter}}, that will a set the offset {{Icode|TranslateY}} value.
 +
 
 +
In the code behind of the detail page we will do the actual calculation using the {{Icode|OnLayoutUpdated}} event of the {{Icode|ContentPanel}}. This is needed to be sure that the {{Icode|ScrollableHeight}} of the {{Icode|ScrollViewer}} is populated, because it will only be available when the full text has been initialized by the page.
  
 
<code csharp>
 
<code csharp>
Line 101: Line 103:
 
</code>
 
</code>
  
This calculation will seek out the slide offset value that is needed inside the {{Icode|ScrollViewerOffsetConverter}}. It's done by looking at the real '''ActualHeight''' of the image and subtracting the viewable part - represented by the '''ActualHeight''' of the  {{Icode|ImageControl}}, giving us the '''Height''' that is missing/not visible.
+
This calculation will seek out the slide offset value that is needed inside the {{Icode|ScrollViewerOffsetConverter}}. It's done by looking at the real {{Icode|ActualHeight}} of the image and subtracting the viewable part - represented by the {{Icode|ActualHeight}} of the  {{Icode|ImageControl}}, giving us the '''Height''' that is missing/not visible.
This value is than divided by the '''ScrollableHeight''' of the  {{Icode|ScrollViewer}} giving us the multiplication value for the image {{Icode|ScrollViewerOffsetConverter}}. The code for the '''Converter''' looks like this
+
 
 +
This value is than divided by the {{Icode|ScrollableHeight}} of the  {{Icode|ScrollViewer}} giving us the multiplication value for the image {{Icode|ScrollViewerOffsetConverter}}. The code for the '''Converter''' looks like this
  
 
<code csharp>
 
<code csharp>
Line 123: Line 126:
 
</code>
 
</code>
  
You can indicate in what direction your image has to scroll... along with your text or the other way around.
+
You can indicate in what direction your image has to scroll - along with your text or the other way around.
  
So with that in place you'll get a nice animation while scrolling through the content of the article!
+
So with that in place you'll get a nice animation while scrolling through the content of the article.
  
 
== Video demo ==  
 
== Video demo ==  
Line 132: Line 135:
  
 
== Downloads ==
 
== Downloads ==
A complete working solution can be downloaded here:
+
A complete working solution can be downloaded here: [[File:ImageParallaxList.zip]]
[[File:ImageParallaxList.zip|ImageParallax]]
+

Revision as of 09:47, 7 October 2013

This article explains how to auto scroll a large image in sync with large text.

WP Metro Icon UI.png
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
Article Metadata
Code ExampleTested with
SDK: Windows Phone 8.0 SDK
Devices(s): Nokia Lumia 820
Compatibility
Platform(s):
Windows Phone 8
Article
Created: Depechie (06 Oct 2013)
Last edited: hamishwillee (07 Oct 2013)

Contents

Introduction

Sometimes you have a page that contains both a large image and a lot of text. The best UI would be to display both, but there simply isn't enough room on the screen. The temptation is to crop the image height in order to keep enough text displayed, but this doesn't always work effectively, particularly with larger images.

This article outlines another solution to this problem: display part of the image at the top of the page with the text below - then scroll the part of the image that is displayed at the same time as the readable text (the position of the area where the image is displayed does not change).

Implementation

To allow the user to view the full image, we track the ScrollViewer of the text part and slide the image into view accordingly.

The layout of such a page is very simple, you'll only need an image and some text and we put this inside the ContentPanel.

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" LayoutUpdated="ContentPanel_OnLayoutUpdated">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ItemsControl Name="ImageControl" Height="175" Grid.Row="0">
<Image Source="{Binding Image}" Name="Image">
<Image.RenderTransform>
<CompositeTransform x:Name="ImageCompositeTransform" TranslateY="{Binding ElementName=ScrollViewer, Path=VerticalOffset, Converter={StaticResource ScrollViewerOffsetConverter}, ConverterParameter='inverse'}" />
</Image.RenderTransform>
</Image>
</ItemsControl>
 
<ScrollViewer Name="ScrollViewer"
Grid.Row="1"
Margin="0,12,0,12"
VerticalAlignment="Top"
VerticalScrollBarVisibility="Visible"
ManipulationMode="Control"
Style="{StaticResource ScrollViewerStyle}">
<RichTextBox Name="Article">
<Paragraph>
<Run FontWeight="Bold" FontSize="22" Text="{Binding Title}" />
</Paragraph>
<Paragraph>
<LineBreak />
<Run Text="{Binding Body}" />
</Paragraph>
</RichTextBox>
</ScrollViewer>
</Grid>
</Grid>

With this XAML in place, you've already added the needed image animation. It's done through use of a CompositeTransform that will change the Y value representing the vertical axis image offset.

We are hooking up TranslateY value to the ScrollViewer of the text, so that the image animation will be kept in sync with the text scroll movement of the user.

Only thing left to do, is figure out how much we need to slide the image in reference to the scroll offset of the ScrollViewer. Because with a very large text, the image will slide slowly upwards, but with a small text, the animation will be faster.

This calculation is done when the detail page is loaded and passed along to the ScrollViewerOffsetConverter, that will a set the offset TranslateY value.

In the code behind of the detail page we will do the actual calculation using the OnLayoutUpdated event of the ContentPanel. This is needed to be sure that the ScrollableHeight of the ScrollViewer is populated, because it will only be available when the full text has been initialized by the page.

private bool _sliderConvertValueSet = false;
private const double ZeroDouble = 0;
 
private void ContentPanel_OnLayoutUpdated(object sender, EventArgs e)
{
if (!_sliderConvertValueSet && !Double.IsInfinity(ScrollViewer.ScrollableHeight) && !ScrollViewer.ScrollableHeight.Equals(ZeroDouble))
{
var slideValue = this.Image.ActualHeight - this.ImageControl.ActualHeight;
var slideConvert = slideValue/this.ScrollViewer.ScrollableHeight;
 
ScrollViewerOffsetConverter.ConvertValue = slideConvert;
 
_sliderConvertValueSet = true;
}
}

This calculation will seek out the slide offset value that is needed inside the ScrollViewerOffsetConverter. It's done by looking at the real ActualHeight of the image and subtracting the viewable part - represented by the ActualHeight of the ImageControl, giving us the Height that is missing/not visible.

This value is than divided by the ScrollableHeight of the ScrollViewer giving us the multiplication value for the image ScrollViewerOffsetConverter. The code for the Converter looks like this

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!Double.IsInfinity(ConvertValue) && !ConvertValue.Equals(ZeroDouble))
{
double targetValue = ((double) value)*ConvertValue;
 
if (((string) parameter).Equals("inverse", StringComparison.OrdinalIgnoreCase))
return 0 - targetValue;
 
return targetValue;
}
else
{
return value;
}
}

You can indicate in what direction your image has to scroll - along with your text or the other way around.

So with that in place you'll get a nice animation while scrolling through the content of the article.

Video demo

The media player is loading...

Downloads

A complete working solution can be downloaded here: File:ImageParallaxList.zip

204 page views in the last 30 days.