Putting together image pan, zoom and rotation (C#, XAML) - image

I want to display images that the user has provided. These images are likely to be larger than the screen resolution (so need zoom and pan capability) plus the image may not be orientated correctly for the screen (so need to be able to rotate).
Implementing pan and zoom seems to be somewhat straightforward:
<ScrollViewer HorizontalSnapPointsType="None" HorizontalScrollBarVisibility="Auto" VerticalSnapPointsType="None" ZoomSnapPointsType="None" IsHorizontalRailEnabled="False" IsVerticalRailEnabled="False" ManipulationMode="All" VerticalScrollBarVisibility="Auto">
<Image x:Name="pannableImage" Source="{Binding FullSizedImage}" AutomationProperties.Name="{Binding Title}" />
</ScrollViewer>
This works well and meets my needs, although I would like to be able to set the initial zoom factor so that if the image is larger than the screen, the zoom factor is set so that it fills the screen and if the image isn't larger than the screen, the zoom factor is set so that the image is shown at its full size, i.e. not zoomed in.
However, I'm struggling to get rotation to work acceptably. I've tried this:
<ScrollViewer HorizontalSnapPointsType="None" HorizontalScrollBarVisibility="Auto" VerticalSnapPointsType="None" ZoomSnapPointsType="None" IsHorizontalRailEnabled="False" IsVerticalRailEnabled="False" ManipulationMode="All" VerticalScrollBarVisibility="Auto">
<Image x:Name="pannableImage" Source="{Binding FullSizedImage}" AutomationProperties.Name="{Binding Title}" >
<Image.Projection>
<PlaneProjection RotationZ="{Binding ImageRotation}"/>
</Image.Projection>
</Image>
</ScrollViewer>
Although this does rotate the image, the problem is that the ScrollViewer then gets the scrolling wrong. I've also tried putting the Projection onto the ScrollViewer instead of the Image and that is even worse.
Putting the project onto the image seems to make the most sense since the ScrollViewer should then get the dimensions of the projected image but that doesn't quite seem to be the case.
What am I misunderstanding here, please?
Thanks.
Philip

The solution was to use a RenderTransform instead of a Projection:
<Image x:Name="pannableImage" Source="{Binding FullSizedImage}" ManipulationMode="All" Loaded="pannableImage_Loaded" IsDoubleTapEnabled="False" IsHitTestVisible="False" IsHoldingEnabled="False" IsRightTapEnabled="False" IsTapEnabled="False" ScrollViewer.VerticalScrollBarVisibility="Disabled" LayoutUpdated="pannableImage_LayoutUpdated">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="Scale" />
<RotateTransform x:Name="Rotate" />
<TranslateTransform x:Name="Translate" />
</TransformGroup>
</Image.RenderTransform>
</Image>

Related

Xamarin Forms Shapes inside SwipeView not working consistently

I created a solution (see code here) from a blank Xamarin Forms template, running the latest stable version of Xamarin Forms. I added the experimental Shapes and SwipeView as required into my native projects, and I have a list of rows just saying "Hello" inside a Collection View.
I attempted to add a semicircle shape to the right swipe item's Grid, so it looks like the row has a rounded edge instead of rectangular shape.
But as you can see in the image below, the Shape just disappears after swiping to the right the second time. And occasionally the shape won't even appear in the row's swipe item.
Please note that the label always displays though, its just the shape going away. Also tested in Android & noticed the same behaviour. Do you know what the issue might be and if there's a work around?
Edit: Posted this and got a response to create an issue. Still looking for a workaround though
You can use Frame with CornerRadius to achieve the result:
<StackLayout Orientation="Horizontal" Padding="0" Margin="0" Spacing="0">
<Label
Text="Left"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand" />
<!--<Path HorizontalOptions="EndAndExpand" Fill="White" Stroke="White" Aspect="Fill" Data="m0.19956,-0.20844l14.43749,0l0,0c7.97347,0 14.43748,6.51981 14.43748,14.56254c0,8.04265 -6.464,14.5625 -14.43748,14.5625l-14.43749,0l0,-29.12504z" >
<Path.RenderTransform>
<RotateTransform CenterX="14.637"
CenterY="14.3541"
Angle="180" />
</Path.RenderTransform>
</Path>-->
<Frame BackgroundColor="Yellow" CornerRadius="30" IsClippedToBounds="True" HeightRequest="30" WidthRequest="30" HorizontalOptions="End" Margin="0,0,-51,0">
</Frame>
</StackLayout>

Align View to bottom and top in RelativeLayout XamarinForms

I want to align one image to the top and one image to the bottom of a RelativeLayout in Xamarin.Forms.
How can I do this?
<RelativeLayout>
<Image
Aspect="Fill"
Source = "header_login.png"></Image>
<Image
Aspect="Fill"
Source = "login_footer_2.png"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width,
Factor=0}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=1}" ></Image>
</RelativeLayout>
I found something may be useful for you. Even if it is not done by using RelativeLayout, you can still have what you want by using StackLayout.
The idea is :
<StackLayout>
<StackLayout VerticalOptions="Start">
<Image/> <!--top image-->
</StackLayout>
<StackLayout VerticalOptions="CenterAndExpand">
<!-- middle controls -->
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="End">
<Image/> <!--bottom image-->
</StackLayout>
</StackLayout>
By Expanding the Middle StackLayout take al the remained spaces pushing the other one on top and on bottom respectively. It was very useful to me to have a fixed bottom.
https://stackoverflow.com/a/30143144/3324840
The relative layout provides a very easy way to do this.
You should use the constraint type "relative to parent" and use factors to position the element.
Relative layout can include the control size when positioning with factors. What that means is that if you put a factor of 0, the top of the image will be at the top of the container.
If you put a factor of 1, the bottom of the image will be at the bottom of the container.
Likewise, a factor of 0.5 will center the center of your image on the center of the container
So, relative layout by default takes care of your control dimensions when calculating factored positions.
You can find a lot more info and samples on the relative container in the official documentation. There are also code samples included in the sample projects to help you out.

arrange variable sized images in listbox in windows phone

i have used wrappanel to arrange images within a listbox but in my picture collection some images have different sizes. Some are horizontal and some are vertical. Due to different orientation, there is some spaces between the images which is not so good in vision. Can any body suggest me any way to remove these spaces?
thanks
i am using following code but still the problem is same...
<ListBox Name="lstBoxMyRecentPhotos"
MaxHeight="650"
Margin="0,8,0,0"
SelectionChanged="lstImageList_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit1:VariableSizedWrapGrid ItemHeight="200" ItemWidth="230" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Name="brdr"
Margin="5"
BorderBrush="White"
BorderThickness="3">
<Border.Background>
<ImageBrush ImageSource="Images/capsule_image_holder.png" Stretch="Uniform" />
</Border.Background>
<Image Width="{Binding width}"
Height="{Binding height}"
Hold="imgRecent_Hold"
Source="{Binding photoUrl}"
Stretch="UniformToFill">
</Image>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Two ways
Make the image always stretch UniformToFill and use hardcoded size - that way it will uniformly fill the space that it's been given and all the photos will use the given space nicely
Use VariableSizedWrapGrid.
Provides a grid-style layout panel where each tile/cell can be
variable size based on content. Similar to the WinRT
VariableSizedWrapGrid.
I don't know which toolkit you are using for the VariableSizedWrapGrid, but are you sure that you need to set its ItemHeight? What happens if you don't?
I'm personally using Telerik's controls to give me a WrapGrid. If you have access to their controls, I can share an example.
Here's what my implementation looks like:

Overflow Hidden Image inside border

I have this code
<Border BorderBrush="White" BorderThickness="2" Margin="5" Grid.Row="0"
Tap="ContentControl_Tap" Background="Transparent">
<Image x:Name="ImgTop" ManipulationDelta="Top_ManipulationDelta" Stretch="Uniform" >
</Border>
I cannot set width of the image (i can have different images, and images can have different size... I cannot crop the image)
I need to "hide" the excess of the image... the problem is that when image is too big the excess go ON the border, not under.... Any idea how can i solve the problem?
Thanx
I realize this question was from awhile ago, but I just ran into a similar issue and I think I've got a solution.
I have a Grid that is 340x162 and I'm planning to create an image rotator of some sort inside of it. I'm considering animating the image into a negative top margin to have the image pan out slightly before it goes to the next slide. However, when the image moves up it goes outside the border.
My solution is to create a clip on the Border, as follows:
<Border Width="340" Height="162">
<Border.Clip>
<RectangleGeometry Rect="0,0,340,162" />
</Border.Clip>
<Image Name="Image1" Source="Assets/my-image.jpg" Stretch="UniformToFill" Margin="0 -20 0 0"/>
</Border>
That clips the border starting at the point 0,0 and it uses a rectangle that is 340x162, which is the same size as the border. As soon as I added that, the negative margin on the image didn't pull the image out of the border.
Hope that helps someone...

ScrollViewer Zoom problems

I'm trying to implement zoom in/out functionality in a ScrollViewer in WP7. Inside my scrollviewer is a usercontrol, which consists of a grid and some ellipsis in variaous cells.
Implementing no zoom, I am able to run the app in the emulator and scroll the scrollviewer up/down, left/right.
My initial thought was to use a scale transform on the scrollviewer:
<ScrollViewer x:Name="svScale"
Margin="0"
Grid.Row="1"
HorizontalScrollBarVisibility="Visible">
<ScrollViewer.RenderTransform>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</ScrollViewer.RenderTransform>
<ScrollViewer.RenderTransformOrigin>
<Point X=".5" Y=".5"/>
</ScrollViewer.RenderTransformOrigin>
<local:MyControl x:Name="test"
Width="486"
Height="56">
</local:MyControl>
</ScrollViewer>
The problem is that when I scroll around, the scrollviewer always scrolls the contents back to the vertical and horizontal center.
So I tried applying the scale transform to the user control:
<ScrollViewer x:Name="svScale"
Margin="0"
Grid.Row="1"
HorizontalScrollBarVisibility="Visible">
<local:MyControl x:Name="test"
Width="486"
Height="56"
SelectedKey="{Binding SelectedKey}"
SelectedScale="{Binding SelectedScale}">
<local:MyControl.RenderTransform>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</local:MyControl.RenderTransform>
<local:MyControl.RenderTransformOrigin>
<Point X=".5" Y=".5"/>
</local:MyControl.RenderTransformOrigin>
</local:MyControl>
</ScrollViewer>
But when I apply the scale transform to the user control, it doesn't appear any larger than it normally does, regardless of what the ScaleX and ScaleY values are. What is going on here?

Resources