【问题标题】:Xamarin forms iOS on orientation changes image goes to cornerXamarin 在方向更改时形成 iOS 图像转到角落
【发布时间】:2018-09-22 10:37:15
【问题描述】:

我有一个用于手势控制的自定义控件。我在控件中有一个带有图像的 xaml。在 android 上我禁用了方向更改,但在 iOS 上我们为 ipad 分发,因此允许更改方向。

如果我以纵向或横向进入屏幕一切正常,但如果我以纵向进入然后我改变方向,之前居中的图像移动到以中心为坐标 0,0 的角落.最终,如果你改变很多方向,图像就会消失。

我尝试删除手势控件并且图像正常,我还尝试将控件放在 AbsoluteLayout 中,然后它可以正常工作,但图像没有填满屏幕。

这是 xaml:

<ContentPage.Content>
    <StackLayout>
        <controls:GestureContainer>
            <controls:GestureContainer.Content>
                <ffimageloading:CachedImage     
                        x:Name="_imageCache"
                        Aspect="AspectFit"
                        DownsampleToViewSize="True"
                        Source="{Binding Image.ImageStream}"/>
             </controls:GestureContainer.Content>
        </controls:GestureContainer>
    </StackLayout>
</ContentPage.Content>

这是 GestureContainer 控件

public class GestureContainer : ContentView
{
    private const double MIN_SCALE = 1;
    private const double MAX_SCALE = 4;
    private double startScale, currentScale;
    private double startX, startY;
    private double xOffset, yOffset;

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

        var pan = new PanGestureRecognizer();            
        pan.PanUpdated += OnPanUpdated;
        GestureRecognizers.Add(pan);

        TapGestureRecognizer tap = new TapGestureRecognizer { NumberOfTapsRequired = 2 };
        tap.Tapped += OnTapped;
        GestureRecognizers.Add(tap);

        Scale = MIN_SCALE;
        TranslationX = TranslationY = 0;
        AnchorX = AnchorY = 0;
    }

    private void OnTapped(object sender, EventArgs e)
    {
        if (Content.Scale > MIN_SCALE)
        {
            RestoreScaleValues();
        }
        else
        {
            Content.AnchorX = Content.AnchorY = 0.5;
            Content.ScaleTo(MAX_SCALE, 250, Easing.CubicInOut);             
        }
    }
    void RestoreScaleValues()
    {
        Content.ScaleTo(MIN_SCALE, 250, Easing.CubicInOut);
        Content.TranslateTo(0.5, 0.5, 250, Easing.CubicInOut);

        currentScale = 1;

        Content.TranslationX = 0.5;
        Content.TranslationY = 0.5;

        xOffset = Content.TranslationX;
        yOffset = Content.TranslationY;
    }

    void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        if (e.Status == GestureStatus.Started)
        {
            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;
        }
    }

    void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {          
        switch (e.StatusType)
        {
            case GestureStatus.Started:
                startX = e.TotalX;
                startY = e.TotalY;
                Content.AnchorX = 0;
                Content.AnchorY = 0;
                break;

            case GestureStatus.Running:
                var maxTranslationX = Content.Scale * Content.Width - Content.Width;
                Content.TranslationX = Math.Min(0, Math.Max(-maxTranslationX, xOffset + e.TotalX - startX));

                var maxTranslationY = Content.Scale * Content.Height - Content.Height;
                Content.TranslationY = Math.Min(0, Math.Max(-maxTranslationY, yOffset + e.TotalY - startY));

                break;

            case GestureStatus.Completed:
                xOffset = Content.TranslationX;
                yOffset = Content.TranslationY;
                break;                   
        }
    }     
}

【问题讨论】:

  • 您好,您的问题解决了吗?
  • 不...一开始你的选择很好,我给你+1就是这样,但如果我改变锚点,旋转工作正常,但手势变得奇怪

标签: ios ipad xamarin.forms screen-orientation


【解决方案1】:

AnchorX 声明了变换的 X 分量,默认值为 0.5。为什么要将GestureContainerAnchorX设置为0?可以尝试去掉构造方法中的代码。

由于您将其设置为 0,因此当您旋转屏幕时,页面将再次布局其子视图。然后你会看到GestureContainer像(0, 0)一样移动到页面的角落。

事件OnMeasure()会在方向改变时触发,所以你也可以在这个事件中重置它:

protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
    Scale = MIN_SCALE;
    Content.TranslationX = Content.TranslationY = 0;
    Content.AnchorX = Content.AnchorY = 0.5;
    return base.OnMeasure(widthConstraint, heightConstraint);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 2015-12-10
    • 2011-05-20
    相关资源
    最近更新 更多