簡體   English   中英

Xamarin在方向改變形式上形成iOS轉向角落

[英]Xamarin forms iOS on orientation changes image goes to corner

我有一個用於手勢控制的自定義控件。 我在控件中有一個帶有圖像的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;                   
        }
    }     
}

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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM