在 Xamarin 窗体中平移图像

本文关键字:图像 Xamarin 窗体 | 更新日期: 2023-09-27 17:56:59

我尝试创建一个内容页面,在那里我可以旋转(只有多个图像)进行文章演示,类似于以下解决方案:http://www.360-javascriptviewer.com/index.html。当用户执行平移手势时,需要交换图像。

视图:

<ContentPage.Content>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
  <Image Source="{Binding SelectedArticleImage.ImageSource}"
         VerticalOptions="FillAndExpand"
         HorizontalOptions="FillAndExpand">      
    <Image.GestureRecognizers>
      <PanGestureRecognizer PanUpdated="OnPanUpdated"/>   
  </Image.GestureRecognizers>    
  </Image>
  <Label Text="A simple Label for test purposes"/>
</StackLayout>
</ContentPage.Content>

视图模型/模型:

public partial class RotationPage : ContentPage
{
    public RotationPage()
    {
        InitializeComponent();
        BindingContext = App.Locator.Rotation;
    }
    public void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        App.Locator.Rotation.OnPanUpdated(sender, e);
    }
}
public class RotationViewModel : ViewModelBase
{
    private double panValueBeginning;
    private double panValueRunning;
    private double screenWidthFactor = 100;
    private List<ArticleImage> articleImages;
    private ArticleImage selectedArticleImage;
    public ArticleImage SelectedArticleImage
    {
        get
        {
            return (selectedArticleImage == null ? articleImages.FirstOrDefault() : selectedArticleImage);
        }
        set
        {
            Set(() => SelectedArticleImage, ref selectedArticleImage, value);
        }
    }
    public RotationViewModel()
    {
        articleImages = new List<ArticleImage>();
        LoadImageList();
    }
    private void LoadImageList()
    {
        for (int i = 0; i < 64; i++)
        {
            string name = "_" + (i + 1).ToString("D2") + ".jpg";
            articleImages.Add(new ArticleImage(name));
        }
    }
    public void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        Debug.WriteLine(e.StatusType.ToString() + ": " + e.TotalX);
        switch (e.StatusType)
        {
            case GestureStatus.Started:
                panValueRunning = 0;
                break;
            case GestureStatus.Running:
                panValueRunning = e.TotalX;
                SelectImage(e.StatusType, e.TotalX);
                break;
            case GestureStatus.Completed:
                panValueBeginning = panValueRunning;
                SelectImage(e.StatusType, e.TotalX);
                break;
            case GestureStatus.Canceled:
                panValueBeginning = 0;
                break;
        }
    }
    private void SelectImage(GestureStatus status, double totalX)
    {
        double panValueRelative = (panValueBeginning + panValueRunning) % screenWidthFactor;
        double panValueAbsolute = (panValueRelative < 0 ? screenWidthFactor : 0) + panValueRelative;
        int index = Convert.ToInt32(Math.Max(1, Math.Min((panValueAbsolute / screenWidthFactor) * articleImages.Count, articleImages.Count))) - 1;
        SelectedArticleImage = articleImages[index];
    }
}
public class ArticleImage
{
    public string Path { get; }
    public ImageSource ImageSource { get; set; }
    public ArticleImage(string path)
    {
        Path = path;
        ImageSource.FromFile(path);
    }
}

我希望您了解我尝试执行的操作:OnPanUpdated 从文件系统加载新图像,具体取决于用户平移的距离。在 UWP 平台上,它正在工作,但远未运行......非常滞后,没有"实时"旋转。在 Android 上,我在 2 次成功平移后出现内存不足异常。我的方法通常是错误的吗?我该如何处理图像更改?

感谢您的任何回答!

在 Xamarin 窗体中平移图像

看起来

你正在试图模仿CarouselView的作用。您可能需要查看使用此控件,该控件将允许您在图像之间轻扫。它也是虚拟化的,因此您可能不会遇到这些内存问题。

Xamarin博客上有一篇文章可以帮助入门,在这里。

此包在 NuGet 上可用,当前是预发行版本,因此请确保在搜索时选中 Visual Studio 中的"包括预发行包"。

博客文章示例:

由于轮播视图

位于单独的程序集中,因此我们必须在页面的根目录中引入轮播视图的命名空间:

xmlns:cv="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"

然后,将控件添加到页面内容:

<cv:CarouselView ItemsSource="{Binding Images}" x:Name="CarouselImages">
    <cv:CarouselView.ItemTemplate>
      <DataTemplate>
        <Grid>
          <Image Source="{Binding Url}"/>
        </Grid>
      </DataTemplate>
    </cv:CarouselView.ItemTemplate>
  </cv:CarouselView>

如果要为 Windows 生成应用程序,则需要将数据模板添加到应用程序的 App.xaml 中的应用程序资源中。

首先在根节点中添加一个新的命名空间:

xmlns:uwp="using:Xamarin.Forms.Platform"

然后将以下内容添加到"应用程序资源"节点:

<DataTemplate x:Key="ItemTemplate">
    <uwp:ItemControl HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
</DataTemplate>

它应该看起来像这样:

<Application
    x:Class="MyApp.UWP.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:uwp="using:Xamarin.Forms.Platform"
    xmlns:local="using:MyApp.UWP"
    RequestedTheme="Light">
    <Application.Resources>
        <DataTemplate x:Key="ItemTemplate">
            <uwp:ItemControl HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
        </DataTemplate>
    </Application.Resources>
</Application>

链接器注意事项

若要确保轮播视图在发布模式下编译时不会"链接出",请确保通过将以下代码添加到项目的 AssemblyInfo(XAML 所在的位置).cs使用已编译的 XAML:

using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]

或者在每个项目中的 Forms.Init(); 调用之后添加以下代码:

var cv = typeof (Xamarin.Forms.CarouselView);
var assembly = Assembly.Load(cv.FullName);

其他资源:

表单文档

示例的源代码