[英]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。 為什么要將GestureContainer
的AnchorX
為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.