PinchGesture Zoom(如Xamarin Form中的Instagram移动供稿屏幕)

时间:2018-08-10 08:11:14

标签: c# xamarin xamarin.forms zoom pinch

我正在尝试在xamarin跨平台应用程序中实现类似的缩放功能,例如Instagram移动应用程序提要屏幕。 实际上,我想在ImageView单元格内的ListView上添加捏合手势,如果用户捏合图像,则应该在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>

Zoom容器类

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;

    }
}
}

0 个答案:

没有答案