0

I am new to Xamarin and specially to MVVM. I have a ListView which is showing me Images.

<ListView ItemsSource="{Binding Urls}" IsVisible="True" VerticalScrollBarVisibility="Always" 
          HorizontalScrollBarVisibility="Always" HorizontalOptions="Fill" VerticalOptions="Fill"  
          HasUnevenRows="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Vertical" HorizontalOptions="Fill" VerticalOptions="FillAndExpand" Padding="2">
                    <ffimageloading:CachedImage Source="{Binding .}" Aspect="AspectFill" Margin="15">
                        <ffimageloading:CachedImage.GestureRecognizers>                                        
                            <TapGestureRecognizer Command="{Binding Source={x:Reference ImgListView},Path=BindingContext.ImageDoubleTappedCommand}" />
                        </ffimageloading:CachedImage.GestureRecognizers>
                    </ffimageloading:CachedImage>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Now I want the zoom behavior with double tap and pinch to zoom. I found different links on internet but those don't implement MVVM. For example : https://www.c-sharpcorner.com/article/zoom-in/. How can I get the zoom functionality in MVVM?

M.Waseem
  • 28
  • 1
  • 7
  • 1
    What do you mean by, "*[these tutorials] don't implement MVVM*"? Zoom and gesture support are View-level responsibilities since they don't change the content, only how the user sees the content. They can be implemented directly in your UI and should not have to communicate with the ViewModel at all. – D M Feb 24 '21 at 18:37
  • @DM Thanks for your reply. Actually I am new to MVVM. The problem is I seriously don't know how to get zoom-image functionality in this case? Do I need some custom control some how? – M.Waseem Feb 24 '21 at 18:40
  • 1
    as @DM notes this is purely a UI operation so MVVM shouldn't apply. There are plenty of existing questions on doing this in XF. And the idea of zoom/pan *in a listview* sounds like horrible UX to me – Jason Feb 24 '21 at 18:42
  • Actually I want to zoom images. I found a tricky solution which says that when we tap on the image we should navigate to another page and show image there and implement the zoom functionality there. But in that case the issue is same -> how to zoom images when working in MVVM pattern? – M.Waseem Feb 24 '21 at 18:46
  • 1
    this has nothing to do with MVVM, it's just V, as we have both told you already. https://stackoverflow.com/search?q=xamarin+forms+zoom+image – Jason Feb 24 '21 at 19:04
  • 1
    As Jason has said, zooming in and the like should be handled purely on the View part of Model View View Model. The only time the VM should be invoked is if you are planning doing something with this data or firing a command, pinching and zooming are not commands. Don't get so hung up on the VM part of MVVM where you start thinking that a view should do nothing at all – SomeStudent Feb 24 '21 at 19:07

1 Answers1

0

I just used the code behind to trigger an event and use the Zoom logic over there:

<TapGestureRecognizer Tapped="TapGestureRecognizer_TappedAsync" />

Following logic is from the link : https://www.c-sharpcorner.com/article/zoom-in/

double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
private void TapGestureRecognizer_TappedAsync(object sender, System.EventArgs e)
{
    var Content = ((FFImageLoading.Forms.CachedImage)sender);

    double multiplicator = Math.Pow(2, 1.0 / 10.0);
    startScale = Content.Scale;
    Content.AnchorX = 0;
    Content.AnchorY = 0;

    for (int i = 0; i < 10; i++)
    {
        currentScale *= multiplicator;
        double renderedX = Content.X + xOffset;
        double deltaX = renderedX / Content.Width;
        double deltaWidth = Content.Width / (Content.Width * startScale);
        double originX = (0.5 - deltaX) * deltaWidth;

        double renderedY = Content.Y + yOffset;
        double deltaY = renderedY / Content.Height;
        double deltaHeight = Content.Height / (Content.Height * startScale);
        double originY = (0.5 - deltaY) * deltaHeight;

        double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
        double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);

        Content.TranslationX = Math.Min(0, Math.Max(targetX, -Content.Width * (currentScale - 1)));
        Content.TranslationY = Math.Min(0, Math.Max(targetY, -Content.Height * (currentScale - 1)));

        Content.Scale = currentScale;
        //await Task.Delay(10);
    }

    xOffset = Content.TranslationX;
    yOffset = Content.TranslationY;
}
M.Waseem
  • 28
  • 1
  • 7