Xamarin Form 中的 PinchGesture 像 Instagram 移动提要屏幕一样缩放

Jyo*_*ash 5 c# zooming pinch xamarin xamarin.forms

我正在尝试在 xamarin 跨平台应用程序中实现类似的缩放功能,例如 Instagram 移动应用程序提要屏幕。实际上我想ImageViewListView单元格内部添加捏合手势,如果用户捏合图像,它应该放大ListView。一旦用户松开捏它应该自动调整到原始大小并适合单元格。
帮助我并提供解决方案。

以下示例代码工作但它在单元格内缩放,它不像 Instagram 缩放重叠/叠加效果。

XAML 代码

<ListView x:Name="listView" ItemSelected="PlayerList_OnItemSelected"  HasUnevenRows="false" RowHeight="300" BackgroundColor="#F6F3F6" 
RelativeLayout.XConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width, Factor=0}" 

RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height, Factor=.09}"

RelativeLayout.HeightConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height, Factor=.91}"

RelativeLayout.WidthConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width, Factor=1}">
<ListView.ItemTemplate>
    <DataTemplate>
<ViewCell >
<Frame Margin="5" Padding="5"  OutlineColor="White" HasShadow="true">

<RelativeLayout >
<Label Font="Bold,20" Text="{Binding name}" TextColor="Black"
        RelativeLayout.YConstraint="{ConstraintExpression 
        Type=RelativeToParent,
        Property=Height,
        Factor=.0}"
        RelativeLayout.XConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Property=Width, 
        Factor=.02}"
        RelativeLayout.WidthConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Property=Width,
        Factor=.9}"/>

    <local:PinchToZoomContainer RelativeLayout.WidthConstraint="{ConstraintExpression
        Type=RelativeToParent,
        Property=Width, 
        Factor=1}"
        RelativeLayout.XConstraint="{ConstraintExpression
        Type=RelativeToParent,
        Property=Width, 
        Factor=0}" 

        RelativeLayout.YConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Factor=.15, 
        Property=Height}">

        <local:PinchToZoomContainer.Content>
                <Image x:Name="imgBg" HeightRequest="180" Aspect="AspectFill" BackgroundColor="#F0F3F4"  Margin="1,1,1,-1" Source="{Binding thumbnail, Converter={StaticResource GetFeedImage}}" />
            </local:PinchToZoomContainer.Content>
        </local:PinchToZoomContainer>


    <Label FontSize="10" TextColor="#96AAC0" HorizontalTextAlignment="Center" HeightRequest="40" Text="{Binding posted_at}" 
        RelativeLayout.YConstraint="{ConstraintExpression 
        Type=RelativeToParent,
        Property=Height,
        Factor=.02}"
        RelativeLayout.XConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Property=Width, 
        Factor=.81}"
        RelativeLayout.WidthConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Property=Width,
        Factor=.2}"/>

    <Label FontSize="12" TextColor="#5B636E" HorizontalTextAlignment="Start"  Text="{Binding description}" 
        RelativeLayout.YConstraint="{ConstraintExpression 
        Type=RelativeToParent,
        Property=Height,
        Factor=.87}"
        RelativeLayout.XConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Property=Width, 
        Factor=.01}"
        RelativeLayout.WidthConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Property=Width,
        Factor=.98}"

        RelativeLayout.HeightConstraint="{ConstraintExpression 
        Type=RelativeToParent, 
        Property=Height,
        Factor=0,
        Constant=30}"/>
</RelativeLayout>
    </Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>

</ListView>
Run Code Online (Sandbox Code Playgroud)

缩放容器类

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;

    }
}
}
Run Code Online (Sandbox Code Playgroud)