具有缩放和平移功能的 Xamarin MVVM 图像查看器

发布于 2025-01-14 03:12:35 字数 3901 浏览 5 评论 0原文

我有一个显示整页图像的 Xamarin MVVM 类。代码如下所示。单击即可关闭视图。我的问题是如何实现平移或缩放。我能找到的唯一东西是为 Xamarin Forms 编写的,我不知道如何使它们适应 MVVM。谢谢。

<?xml version="1.0" encoding="utf-8" ?>
<views:MvxContentPage x:TypeArguments="viewModels:ImageViewModel"
                  xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
                  xmlns:viewModels="clr-namespace:BLE.Client.ViewModels;assembly=BLE.Client"
                  x:Class="BLE.Client.Pages.ImagePage" Title="View Image">
   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height="*"></RowDefinition>
      </Grid.RowDefinitions>
      <StackLayout Grid.Row="0" Orientation="Horizontal" >
         <Image x:Name="WaypointImage" Source="{Binding MyImage}" HorizontalOptions="FillAndExpand">
           <Image.GestureRecognizers>
              <TapGestureRecognizer   Command="{Binding TapCommand}"/>
              <PinchGestureRecognizer Command="{Binding PinchCommand}"/>
              <PanGestureRecognizer   Command="{Binding PanCommand}"/>
           </Image.GestureRecognizers>
         </Image>
      </StackLayout>
  </Grid>
</views:MvxContentPage>


using System;
using System.Windows.Input;
using Xamarin.Forms;
using Acr.UserDialogs;
using MvvmCross;
using MvvmCross.ViewModels;
using MvvmCross.Navigation;
using Plugin.BLE.Abstractions.Contracts;

namespace BLE.Client.ViewModels
{
    public class ImageViewModel : BaseViewModel
    {
       private ImageSource _myImage;
       public ImageSource MyImage
       {
          get => _myImage;
          set
          {
             _myImage = value;
             RaisePropertyChanged(() => MyImage);
          }
       }

   private readonly IUserDialogs _userDialogs;
   private readonly IMvxNavigationService _navigation;

   public String _waypoint;
   public Waypoint waypoint;

   public ICommand tapCommand;
   public ICommand TapCommand {
      get { return tapCommand; }
   }

   public ICommand pinchCommand;
   public ICommand PinchCommand {
      get { return pinchCommand; }
   }

   public ICommand panCommand;
   public ICommand PanCommand {
      get { return panCommand; }
   }

   public ImageViewModel(IAdapter adapter, IUserDialogs userDialogs) : base(adapter)
   {
      _userDialogs = userDialogs;
      _navigation = Mvx.IoCProvider.Resolve<IMvxNavigationService>();

      tapCommand   = new Command (OnTapped);
      pinchCommand = new Command (OnPinched);
      panCommand   = new Command (OnPan);
   }

   void OnTapped (object s)  {
      Console.WriteLine($"OnTapped: {s}");
      _navigation.Close(this);
   }

   void OnPinched (object s)  {
      Console.WriteLine($"OnPinched: {s}");
   }

   void OnPan (object s)  {
      Console.WriteLine($"OnPan: {s}");
   }

   public override async void Prepare(MvxBundle parameters)
   {
      base.Prepare(parameters);

      _waypoint = await GetWaypointFromBundleAsync(parameters);
      string[] tags = _waypoint?.Split(' ');
      char[] trimChars = { 'I', 'D', '=' };
      string id = tags[0].TrimStart(trimChars);
      int ID = System.Convert.ToInt32(id);
      waypoint = await Database.GetWaypointAsync(ID);
      MyImage = ImageSource.FromFile(waypoint.FileName);
      Console.WriteLine($"prepare       ID={waypoint.ID} {waypoint.FileName} ");
   }

    public override void ViewAppeared()
   {
      base.ViewAppeared();
      if (_waypoint != null)
      {
         return;
      }
      _navigation.Close(this);
   }

    public override void ViewDisappearing()
   {
      base.ViewDisappearing();
   }

    public override void ViewDisappeared()
   {
      base.ViewDisappeared();
   }
}

}

I have a Xamarin MVVM class that displays a full page image. The code is shown below. The single tap simply closes the view. My question is how to implement the pan or zoom. The only things that I can find are written for Xamarin Forms and I can't figure out how to adapt them to MVVM. Thanks.

<?xml version="1.0" encoding="utf-8" ?>
<views:MvxContentPage x:TypeArguments="viewModels:ImageViewModel"
                  xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
                  xmlns:viewModels="clr-namespace:BLE.Client.ViewModels;assembly=BLE.Client"
                  x:Class="BLE.Client.Pages.ImagePage" Title="View Image">
   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height="*"></RowDefinition>
      </Grid.RowDefinitions>
      <StackLayout Grid.Row="0" Orientation="Horizontal" >
         <Image x:Name="WaypointImage" Source="{Binding MyImage}" HorizontalOptions="FillAndExpand">
           <Image.GestureRecognizers>
              <TapGestureRecognizer   Command="{Binding TapCommand}"/>
              <PinchGestureRecognizer Command="{Binding PinchCommand}"/>
              <PanGestureRecognizer   Command="{Binding PanCommand}"/>
           </Image.GestureRecognizers>
         </Image>
      </StackLayout>
  </Grid>
</views:MvxContentPage>


using System;
using System.Windows.Input;
using Xamarin.Forms;
using Acr.UserDialogs;
using MvvmCross;
using MvvmCross.ViewModels;
using MvvmCross.Navigation;
using Plugin.BLE.Abstractions.Contracts;

namespace BLE.Client.ViewModels
{
    public class ImageViewModel : BaseViewModel
    {
       private ImageSource _myImage;
       public ImageSource MyImage
       {
          get => _myImage;
          set
          {
             _myImage = value;
             RaisePropertyChanged(() => MyImage);
          }
       }

   private readonly IUserDialogs _userDialogs;
   private readonly IMvxNavigationService _navigation;

   public String _waypoint;
   public Waypoint waypoint;

   public ICommand tapCommand;
   public ICommand TapCommand {
      get { return tapCommand; }
   }

   public ICommand pinchCommand;
   public ICommand PinchCommand {
      get { return pinchCommand; }
   }

   public ICommand panCommand;
   public ICommand PanCommand {
      get { return panCommand; }
   }

   public ImageViewModel(IAdapter adapter, IUserDialogs userDialogs) : base(adapter)
   {
      _userDialogs = userDialogs;
      _navigation = Mvx.IoCProvider.Resolve<IMvxNavigationService>();

      tapCommand   = new Command (OnTapped);
      pinchCommand = new Command (OnPinched);
      panCommand   = new Command (OnPan);
   }

   void OnTapped (object s)  {
      Console.WriteLine(
quot;OnTapped: {s}");
      _navigation.Close(this);
   }

   void OnPinched (object s)  {
      Console.WriteLine(
quot;OnPinched: {s}");
   }

   void OnPan (object s)  {
      Console.WriteLine(
quot;OnPan: {s}");
   }

   public override async void Prepare(MvxBundle parameters)
   {
      base.Prepare(parameters);

      _waypoint = await GetWaypointFromBundleAsync(parameters);
      string[] tags = _waypoint?.Split(' ');
      char[] trimChars = { 'I', 'D', '=' };
      string id = tags[0].TrimStart(trimChars);
      int ID = System.Convert.ToInt32(id);
      waypoint = await Database.GetWaypointAsync(ID);
      MyImage = ImageSource.FromFile(waypoint.FileName);
      Console.WriteLine(
quot;prepare       ID={waypoint.ID} {waypoint.FileName} ");
   }

    public override void ViewAppeared()
   {
      base.ViewAppeared();
      if (_waypoint != null)
      {
         return;
      }
      _navigation.Close(this);
   }

    public override void ViewDisappearing()
   {
      base.ViewDisappearing();
   }

    public override void ViewDisappeared()
   {
      base.ViewDisappeared();
   }
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最丧也最甜 2025-01-21 03:12:35

更新:

我找到了一个更好的解决方案,如下:

我对捏平问题的回答

这是我之前的答案这在一定程度上有效,但我无法触发捏合和平移手势:

我找到了一个 MVVM 解决方案,它利用了可绑定属性图像:TranslationX、TranslationY 和 Scale。以下是相关代码更改。我通过修改 OnTapped 方法中的 MyImageTranslationX 进行了测试,发现图像向右移动。

现在我只需要让 Image.GestureRecognizers(PinchGestureRecognizer 和 PanGestureRecognizer)正常工作,然后添加我在其他地方看到的代码即可平滑平移和缩放。

 <Image x:Name="WaypointImage"
         Source="{Binding MyImage}"
         Scale   = "{Binding MyImageScale}"
         TranslationX = "{Binding MyImageTranslationX}"
         TranslationY = "{Binding MyImageTranslationY}"
         HorizontalOptions="FillAndExpand">
    <Image.GestureRecognizers>
      <TapGestureRecognizer   Command="{Binding TapCommand}"/>
      <PinchGestureRecognizer Command="{Binding PinchCommand}"/>
      <PanGestureRecognizer   Command="{Binding PanCommand}"/>
    </Image.GestureRecognizers>
 </Image>

   public double _myImageScale = 1.0;
   public double MyImageScale
   {
      get => _myImageScale;
      set
      {
         _myImageScale = value;
         RaisePropertyChanged(() => MyImageScale);
      }
   }
   public double _myImageTranslationX = 0;
   public double MyImageTranslationX
   {
      get => _myImageTranslationX;
      set
      {
         _myImageTranslationX = value;
         RaisePropertyChanged(() => MyImageTranslationX);
      }
   }
   public double _myImageTranslationY = 0;
   public double MyImageTranslationY
   {
      get => _myImageTranslationY;
      set
      {
         _myImageTranslationY = value;
         RaisePropertyChanged(() => MyImageTranslationY);
      }
   }
   private ImageSource _myImage;
   public ImageSource MyImage
   {
      get => _myImage;
      set
      {
         _myImage = value;
         RaisePropertyChanged(() => MyImage);
      }
   }

   void OnTapped (object s)  {
      Console.WriteLine($"OnTapped: {MyImage}");
      MyImageTranslationX = MyImageTranslationX + 100;
      // _navigation.Close(this);
   }

Update:

I found an even better solution to the one below:

My answer to a pinch and pan question

This is my previous answer that works to a point but I could not get the pinch and pan gestures to trigger:

I have found an MVVM solution that takes advantage of the bindable properties Image: TranslationX, TranslationY, and Scale. Here are the relevant code changes. I tested this by modifying MyImageTranslationX in the OnTapped method and saw that the image shifts to the right.

Now I just need to get the Image.GestureRecognizers (PinchGestureRecognizer and PanGestureRecognizer) working and then add code that I have seen elsewhere to smoothly pan and zoom.

 <Image x:Name="WaypointImage"
         Source="{Binding MyImage}"
         Scale   = "{Binding MyImageScale}"
         TranslationX = "{Binding MyImageTranslationX}"
         TranslationY = "{Binding MyImageTranslationY}"
         HorizontalOptions="FillAndExpand">
    <Image.GestureRecognizers>
      <TapGestureRecognizer   Command="{Binding TapCommand}"/>
      <PinchGestureRecognizer Command="{Binding PinchCommand}"/>
      <PanGestureRecognizer   Command="{Binding PanCommand}"/>
    </Image.GestureRecognizers>
 </Image>

   public double _myImageScale = 1.0;
   public double MyImageScale
   {
      get => _myImageScale;
      set
      {
         _myImageScale = value;
         RaisePropertyChanged(() => MyImageScale);
      }
   }
   public double _myImageTranslationX = 0;
   public double MyImageTranslationX
   {
      get => _myImageTranslationX;
      set
      {
         _myImageTranslationX = value;
         RaisePropertyChanged(() => MyImageTranslationX);
      }
   }
   public double _myImageTranslationY = 0;
   public double MyImageTranslationY
   {
      get => _myImageTranslationY;
      set
      {
         _myImageTranslationY = value;
         RaisePropertyChanged(() => MyImageTranslationY);
      }
   }
   private ImageSource _myImage;
   public ImageSource MyImage
   {
      get => _myImage;
      set
      {
         _myImage = value;
         RaisePropertyChanged(() => MyImage);
      }
   }

   void OnTapped (object s)  {
      Console.WriteLine(
quot;OnTapped: {MyImage}");
      MyImageTranslationX = MyImageTranslationX + 100;
      // _navigation.Close(this);
   }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文