Xamarin Android 捏合和平移无法在轮播视图中工作

发布于 2025-01-15 19:31:53 字数 1468 浏览 3 评论 0原文

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

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

发布评论

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

评论(1

木落 2025-01-22 19:31:53

你可以尝试下面的代码。

Xaml:

 <ContentPage.Content>
    <CarouselView ItemsSource="{Binding Images}">
        <CarouselView.ItemTemplate>
            <DataTemplate>
                <StackLayout>
                    <Frame HasShadow="True"
                   BorderColor="DarkGray"
                   CornerRadius="5"
                   Margin="20"
                   HeightRequest="300"
                   HorizontalOptions="Center"
                   VerticalOptions="CenterAndExpand">
                        <StackLayout>
                            <Label Text="{Binding Name}"
                           FontAttributes="Bold"
                           FontSize="Large"
                           HorizontalOptions="Center"
                           VerticalOptions="Center" />
                            <local:PinchToZoomContainer>
                                <local:PinchToZoomContainer.Content>
                                    <Image Source="{Binding ImageUrl}"
                           Aspect="AspectFill"
                           HeightRequest="250"
                           WidthRequest="250"
                           HorizontalOptions="Center">

                                    </Image>
                                </local:PinchToZoomContainer.Content>
                            </local:PinchToZoomContainer>
                         
                         
                        </StackLayout>
                    </Frame>
                </StackLayout>
            </DataTemplate>
        </CarouselView.ItemTemplate>
    </CarouselView>
</ContentPage.Content>

隐藏代码:

 public partial class Page27 : ContentPage
{
    public Page27()
    {
        InitializeComponent();
        this.BindingContext = new Page27ViewModel();
    }
}
 public class Page27Model
{
    public string Name { get; set; }

    public string ImageUrl { get; set; }

}
public class Page27ViewModel
{
    public ObservableCollection<Page27Model> Images { get; set; }
    public Page27ViewModel()
    {
        Images = new ObservableCollection<Page27Model>()
        {
            new Page27Model(){ Name="1", ImageUrl="durian.png" },
            new Page27Model(){ Name="2", ImageUrl="durian.png" },
            new Page27Model(){ Name="3", ImageUrl="durian.png" },
            new Page27Model(){ Name="4", ImageUrl="durian.png" },
        };
    }
}
public class PinchToZoomContainer : ContentView
{
    double currentScale = 1;
    double startScale = 1;
    double xOffset = 0;
    double yOffset = 0;

    public PinchToZoomContainer()
    {
        var pinchGesture = new PinchGestureRecognizer();
        pinchGesture.PinchUpdated += OnPinchUpdated;
        GestureRecognizers.Add(pinchGesture);
    }

    void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        if (e.Status == GestureStatus.Started)
        {
            // Store the current scale factor applied to the wrapped user interface element,
            // and zero the components for the center point of the translate transform.
            startScale = Content.Scale;
            Content.AnchorX = 0;
            Content.AnchorY = 0;
        }
        if (e.Status == GestureStatus.Running)
        {
            // Calculate the scale factor to be applied.
            currentScale += (e.Scale - 1) * startScale;
            currentScale = Math.Max(1, currentScale);

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
            // so get the X pixel coordinate.
            double renderedX = Content.X + xOffset;
            double deltaX = renderedX / Width;
            double deltaWidth = Width / (Content.Width * startScale);
            double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
            // so get the Y pixel coordinate.
            double renderedY = Content.Y + yOffset;
            double deltaY = renderedY / Height;
            double deltaHeight = Height / (Content.Height * startScale);
            double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;

            // Calculate the transformed element pixel coordinates.
            double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
            double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);

            // Apply translation based on the change in origin.
            Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1), 0);
            Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1), 0);

            // Apply scale factor
            Content.Scale = currentScale;
        }
        if (e.Status == GestureStatus.Completed)
        {
            // Store the translation delta's of the wrapped user interface element.
            xOffset = Content.TranslationX;
            yOffset = Content.TranslationY;
        }
    }
}
public static class DoubleExtensions
{
    public static double Clamp(this double self, double min, double max)
    {
        return Math.Min(max, Math.Max(self, min));
    }
}

在此处输入图像描述

You could try the code below.

Xaml:

 <ContentPage.Content>
    <CarouselView ItemsSource="{Binding Images}">
        <CarouselView.ItemTemplate>
            <DataTemplate>
                <StackLayout>
                    <Frame HasShadow="True"
                   BorderColor="DarkGray"
                   CornerRadius="5"
                   Margin="20"
                   HeightRequest="300"
                   HorizontalOptions="Center"
                   VerticalOptions="CenterAndExpand">
                        <StackLayout>
                            <Label Text="{Binding Name}"
                           FontAttributes="Bold"
                           FontSize="Large"
                           HorizontalOptions="Center"
                           VerticalOptions="Center" />
                            <local:PinchToZoomContainer>
                                <local:PinchToZoomContainer.Content>
                                    <Image Source="{Binding ImageUrl}"
                           Aspect="AspectFill"
                           HeightRequest="250"
                           WidthRequest="250"
                           HorizontalOptions="Center">

                                    </Image>
                                </local:PinchToZoomContainer.Content>
                            </local:PinchToZoomContainer>
                         
                         
                        </StackLayout>
                    </Frame>
                </StackLayout>
            </DataTemplate>
        </CarouselView.ItemTemplate>
    </CarouselView>
</ContentPage.Content>

Code behind:

 public partial class Page27 : ContentPage
{
    public Page27()
    {
        InitializeComponent();
        this.BindingContext = new Page27ViewModel();
    }
}
 public class Page27Model
{
    public string Name { get; set; }

    public string ImageUrl { get; set; }

}
public class Page27ViewModel
{
    public ObservableCollection<Page27Model> Images { get; set; }
    public Page27ViewModel()
    {
        Images = new ObservableCollection<Page27Model>()
        {
            new Page27Model(){ Name="1", ImageUrl="durian.png" },
            new Page27Model(){ Name="2", ImageUrl="durian.png" },
            new Page27Model(){ Name="3", ImageUrl="durian.png" },
            new Page27Model(){ Name="4", ImageUrl="durian.png" },
        };
    }
}
public class PinchToZoomContainer : ContentView
{
    double currentScale = 1;
    double startScale = 1;
    double xOffset = 0;
    double yOffset = 0;

    public PinchToZoomContainer()
    {
        var pinchGesture = new PinchGestureRecognizer();
        pinchGesture.PinchUpdated += OnPinchUpdated;
        GestureRecognizers.Add(pinchGesture);
    }

    void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        if (e.Status == GestureStatus.Started)
        {
            // Store the current scale factor applied to the wrapped user interface element,
            // and zero the components for the center point of the translate transform.
            startScale = Content.Scale;
            Content.AnchorX = 0;
            Content.AnchorY = 0;
        }
        if (e.Status == GestureStatus.Running)
        {
            // Calculate the scale factor to be applied.
            currentScale += (e.Scale - 1) * startScale;
            currentScale = Math.Max(1, currentScale);

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
            // so get the X pixel coordinate.
            double renderedX = Content.X + xOffset;
            double deltaX = renderedX / Width;
            double deltaWidth = Width / (Content.Width * startScale);
            double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
            // so get the Y pixel coordinate.
            double renderedY = Content.Y + yOffset;
            double deltaY = renderedY / Height;
            double deltaHeight = Height / (Content.Height * startScale);
            double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;

            // Calculate the transformed element pixel coordinates.
            double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
            double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);

            // Apply translation based on the change in origin.
            Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1), 0);
            Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1), 0);

            // Apply scale factor
            Content.Scale = currentScale;
        }
        if (e.Status == GestureStatus.Completed)
        {
            // Store the translation delta's of the wrapped user interface element.
            xOffset = Content.TranslationX;
            yOffset = Content.TranslationY;
        }
    }
}
public static class DoubleExtensions
{
    public static double Clamp(this double self, double min, double max)
    {
        return Math.Min(max, Math.Max(self, min));
    }
}

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文