我已经单独实现了pan和pinch,它工作正常。我现在正在尝试使用捏合和平移,我发现了一些问题。这是我的代码:
XAML:
<AbsoluteLayout x:Name="PinchZoomContainer">
<controls:NavBar x:Name="NavBar" ShowPrevNext="true" ShowMenu="false" IsModal="true" />
<controls:PanContainer x:Name="PinchToZoomContainer">
<Image x:Name="ImageMain" />
</controls:PanContainer>
</AbsoluteLayout>
捏/手势添加:
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(panGesture);
var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinchGesture);
Pan方法:
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:
// Translate and ensure we don't pan beyond the wrapped user interface element bounds.
Content.TranslationX = Math.Max(Math.Min(0, x + e.TotalX), -Math.Abs(Content.Width - App.ScreenWidth));
Content.TranslationY = Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs(Content.Height - App.ScreenHeight));
break;
case GestureStatus.Completed:
// Store the translation applied during the pan
x = Content.TranslationX;
y = Content.TranslationY;
break;
}
}
捏法:
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;
//ImageMain.AnchorX = 0;
//ImageMain.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
currentScale = Math.Min(currentScale, 2.5);
// 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;
}
}
如果我关闭任一手势并仅使用另一个手势,那么功能完美无缺。当我添加平移和捏合手势时会出现问题。似乎正在发生的是:
1)平底锅实际上似乎按预期工作 2)当你最初平移图像时,让我们说,将图像移动到Y中心和X中心,然后你尝试缩放,图像被设置回它的初始状态。然后,当你平移时,它会让你回到你试图缩放之前的位置(这就是为什么我说平底锅工作正常)。
根据我对调试的理解,当你放大它时,它没有考虑你目前所处的位置。因此,当您先平移,然后进行缩放时,它不会放大您所处的位置,而是放大图像的起始点。然后当你尝试从那里平移时,pan方法仍会记住你的位置,它会让你回到你试图缩放之前的位置。
希望对此有所了解。显然,我的捏合方法存在问题。我只是想(显然无法弄清楚)我需要在其中添加逻辑,并考虑到您当前所处的位置。
答案 0 :(得分:9)
主要原因可能是每个人似乎都复制并使用此代码(来自dev.xamarin网站),其中包含非常复杂且非常不必要的协调计算:-)。这是不必要的,因为我们可以简单地让视图为我们做繁重的工作,使用AnchorX
和AnchorY
属性来实现此目的。
我们可以进行双击操作以放大并恢复到原始比例。请注意,因为Xamarin无法为其Tap
事件提供坐标值(实际上非常不明智的决定),我们现在只能从中心放大:
private void OnTapped(object sender, EventArgs e)
{
if (Scale > MIN_SCALE)
{
this.ScaleTo(MIN_SCALE, 250, Easing.CubicInOut);
this.TranslateTo(0, 0, 250, Easing.CubicInOut);
}
else
{
AnchorX = AnchorY = 0.5;
this.ScaleTo(MAX_SCALE, 250, Easing.CubicInOut);
}
}
捏合处理器同样简单,根本不需要计算任何翻译。我们所要做的就是将锚点设置为捏起点,框架将完成其余的工作,缩放将围绕这一点进行。请注意,我们这里甚至还有一个额外的功能,即在缩放比例两端的过冲时弹性反弹。
private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
switch (e.Status)
{
case GestureStatus.Started:
StartScale = Scale;
AnchorX = e.ScaleOrigin.X;
AnchorY = e.ScaleOrigin.Y;
break;
case GestureStatus.Running:
double current = Scale + (e.Scale - 1) * StartScale;
Scale = Clamp(current, MIN_SCALE * (1 - OVERSHOOT), MAX_SCALE * (1 + OVERSHOOT));
break;
case GestureStatus.Completed:
if (Scale > MAX_SCALE)
this.ScaleTo(MAX_SCALE, 250, Easing.SpringOut);
else if (Scale < MIN_SCALE)
this.ScaleTo(MIN_SCALE, 250, Easing.SpringOut);
break;
}
}
平移处理程序,甚至更简单。一开始,我们计算锚点的起点,在平移过程中,我们不断更改锚点。这个锚点相对于视图区域,我们可以很容易地将它夹在0和1之间,这样就可以在极端情况下停止平移而不进行任何平移计算。
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Started:
StartX = (1 - AnchorX) * Width;
StartY = (1 - AnchorY) * Height;
break;
case GestureStatus.Running:
AnchorX = Clamp(1 - (StartX + e.TotalX) / Width, 0, 1);
AnchorY = Clamp(1 - (StartY + e.TotalY) / Height, 0, 1);
break;
}
}
使用的常量和变量就是:
private const double MIN_SCALE = 1;
private const double MAX_SCALE = 8;
private const double OVERSHOOT = 0.15;
private double StartX, StartY;
private double StartScale;
答案 1 :(得分:3)
采用完全不同的处理方法。对于任何有问题的人来说,这是100%的工作。
<强> OnPanUpdated 强>
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
var s = (ContentView)sender;
// do not allow pan if the image is in its intial size
if (currentScale == 1)
return;
switch (e.StatusType)
{
case GestureStatus.Running:
double xTrans = xOffset + e.TotalX, yTrans = yOffset + e.TotalY;
// do not allow verical scorlling unless the image size is bigger than the screen
s.Content.TranslateTo(xTrans, yTrans, 0, Easing.Linear);
break;
case GestureStatus.Completed:
// Store the translation applied during the pan
xOffset = s.Content.TranslationX;
yOffset = s.Content.TranslationY;
// center the image if the width of the image is smaller than the screen width
if (originalWidth * currentScale < ScreenWidth && ScreenWidth > ScreenHeight)
xOffset = (ScreenWidth - originalWidth * currentScale) / 2 - s.Content.X;
else
xOffset = System.Math.Max(System.Math.Min(0, xOffset), -System.Math.Abs(originalWidth * currentScale - ScreenWidth));
// center the image if the height of the image is smaller than the screen height
if (originalHeight * currentScale < ScreenHeight && ScreenHeight > ScreenWidth)
yOffset = (ScreenHeight - originalHeight * currentScale) / 2 - s.Content.Y;
else
//yOffset = System.Math.Max(System.Math.Min((originalHeight - (ScreenHeight)) / 2, yOffset), -System.Math.Abs((originalHeight * currentScale - ScreenHeight - (originalHeight - ScreenHeight) / 2)) + (NavBar.Height + App.StatusBarHeight));
yOffset = System.Math.Max(System.Math.Min((originalHeight - (ScreenHeight)) / 2, yOffset), -System.Math.Abs((originalHeight * currentScale - ScreenHeight - (originalHeight - ScreenHeight) / 2)));
// bounce the image back to inside the bounds
s.Content.TranslateTo(xOffset, yOffset, 500, Easing.BounceOut);
break;
}
}
<强> OnPinchUpdated 强>
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
var s = (ContentView)sender;
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 = s.Content.Scale;
s.Content.AnchorX = 0;
s.Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = System.Math.Max(1, currentScale);
currentScale = System.Math.Min(currentScale, 5);
//scaleLabel.Text = "Scale: " + currentScale.ToString ();
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = s.Content.X + xOffset;
double deltaX = renderedX / App.ScreenWidth;
double deltaWidth = App.ScreenWidth / (s.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 = s.Content.Y + yOffset;
double deltaY = renderedY / App.ScreenHeight;
double deltaHeight = App.ScreenHeight / (s.Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * s.Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * s.Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
var transX = targetX.Clamp(-s.Content.Width * (currentScale - 1), 0);
var transY = targetY.Clamp(-s.Content.Height * (currentScale - 1), 0);
s.Content.TranslateTo(transX, transY, 0, Easing.Linear);
// Apply scale factor.
s.Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation applied during the pan
xOffset = s.Content.TranslationX;
yOffset = s.Content.TranslationY;
// center the image if the width of the image is smaller than the screen width
if (originalWidth * currentScale < ScreenWidth && ScreenWidth > ScreenHeight)
xOffset = (ScreenWidth - originalWidth * currentScale) / 2 - s.Content.X;
else
xOffset = System.Math.Max(System.Math.Min(0, xOffset), -System.Math.Abs(originalWidth * currentScale - ScreenWidth));
// center the image if the height of the image is smaller than the screen height
if (originalHeight * currentScale < ScreenHeight && ScreenHeight > ScreenWidth)
yOffset = (ScreenHeight - originalHeight * currentScale) / 2 - s.Content.Y;
else
yOffset = System.Math.Max(System.Math.Min((originalHeight - ScreenHeight) / 2, yOffset), -System.Math.Abs(originalHeight * currentScale - ScreenHeight - (originalHeight - ScreenHeight) / 2));
// bounce the image back to inside the bounds
s.Content.TranslateTo(xOffset, yOffset, 500, Easing.BounceOut);
}
}
OnSizeAllocated (大多数情况下你可能不需要,但有些你需要。考虑ScreenWidth
,ScreenHeight
,yOffset
,xOffset
, currentScale
)
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height); //must be called
if (width != -1 && (ScreenWidth != width || ScreenHeight != height))
{
ResetLayout(width, height);
originalWidth = initialLoad ?
ImageWidth >= 960 ?
App.ScreenWidth > 320
? 768
: 320
: ImageWidth / 3
: imageContainer.Content.Width / imageContainer.Content.Scale;
var normalizedHeight = ImageWidth >= 960 ?
App.ScreenWidth > 320 ? ImageHeight / (ImageWidth / 768)
: ImageHeight / (ImageWidth / 320)
: ImageHeight / 3;
originalHeight = initialLoad ?
normalizedHeight : (imageContainer.Content.Height / imageContainer.Content.Scale);
ScreenWidth = width;
ScreenHeight = height;
xOffset = imageContainer.TranslationX;
yOffset = imageContainer.TranslationY;
currentScale = imageContainer.Scale;
if (initialLoad)
initialLoad = false;
}
}
布局(C#中的XAML)
ImageMain = new Image
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
Aspect = Aspect.AspectFill,
Source = ImageMainSource
};
imageContainer = new ContentView
{
Content = ImageMain,
BackgroundColor = Xamarin.Forms.Color.Black,
WidthRequest = App.ScreenWidth - 250
};
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
imageContainer.GestureRecognizers.Add(panGesture);
var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += OnPinchUpdated;
imageContainer.GestureRecognizers.Add(pinchGesture);
double smallImageHeight = ImageHeight / (ImageWidth / 320);
absoluteLayout = new AbsoluteLayout
{
HeightRequest = App.ScreenHeight,
BackgroundColor = Xamarin.Forms.Color.Black,
};
AbsoluteLayout.SetLayoutFlags(imageContainer, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds(imageContainer, new Rectangle(0f, 0f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
absoluteLayout.Children.Add(imageContainer, new Rectangle(0, 0, 1, 1), AbsoluteLayoutFlags.All);
Content = absoluteLayout;
答案 2 :(得分:0)
对我来说,它的工作方式如下所示,只是对问题中给出的代码做了一些更改,
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;
width = Content.Width * currentScale;
height = Content.Height * currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
x = Content.TranslationX;
y = Content.TranslationY;
}
}
邮政编码
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (!width.Equals(Content.Width) && !height.Equals(Content.Height))
{
switch (e.StatusType)
{
case GestureStatus.Started:
startX = Content.TranslationX;
startY = Content.TranslationY;
break;
case GestureStatus.Running:
if (!width.Equals(0))
{
Content.TranslationX = Math.Max(Math.Min(0, x + e.TotalX), -Math.Abs(Content.Width - width));// App.ScreenWidth));
}
if (!height.Equals(0))
{
Content.TranslationY = Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs(Content.Height - height)); //App.ScreenHeight));
}
break;
case GestureStatus.Completed:
// Store the translation applied during the pan
x = Content.TranslationX;
y = Content.TranslationY;
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
break;
}
}
}
答案 3 :(得分:0)
我一直在使用Pan&zoom制作图像查看器...
我遇到了另一个变化。
我会和你分享。
首先,我们需要一个Pan / Zoom类控制器:
using System;
using Xamarin.Forms;
namespace Project.Util
{
public class PanZoom
{
bool pitching = false;
bool panning = false;
bool collectFirst = false;
double xOffset = 0;
double yOffset = 0;
//scale processing...
double scaleMin;
double scaleMax;
double scale;
double _xScaleOrigin;
double _yScaleOrigin;
double panTotalX;
double panTotalY;
ContentPage contentPage;
View Content;
public void Setup(ContentPage cp, View content)
{
contentPage = cp;
Content = content;
PinchGestureRecognizer pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += PinchUpdated;
contentPage.Content.GestureRecognizers.Add(pinchGesture);
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
contentPage.Content.GestureRecognizers.Add(panGesture);
contentPage.SizeChanged += (sender, e) => { layoutElements(); };
}
public void layoutElements()
{
if (contentPage.Width <= 0 || contentPage.Height <= 0 || Content.WidthRequest <= 0 || Content.HeightRequest <= 0)
return;
xOffset = 0;
yOffset = 0;
double pageW = contentPage.Width;
double pageH = contentPage.Height;
double w_s = pageW / Content.WidthRequest;
double h_s = pageH / Content.HeightRequest;
if (w_s < h_s)
scaleMin = w_s;
else
scaleMin = h_s;
scaleMax = scaleMin * 3.0;
scale = scaleMin;
double w = Content.WidthRequest * scale;
double h = Content.HeightRequest * scale;
double x = pageW / 2.0 - w / 2.0 + xOffset;
double y = pageH / 2.0 - h / 2.0 + yOffset;
AbsoluteLayout.SetLayoutBounds(Content, new Rectangle(x, y, w, h));
}
void fixPosition(
ref double x, ref double y, ref double w, ref double h,
bool setoffset
)
{
double pageW = contentPage.Width;
double pageH = contentPage.Height;
if (w <= pageW)
{
double new_x = pageW / 2.0 - w / 2.0;
if (setoffset)
xOffset = new_x - (pageW / 2.0 - w / 2.0);
x = new_x;
} else
{
if (x > 0)
{
double new_x = 0;
if (setoffset)
xOffset = new_x - (pageW / 2.0 - w / 2.0);
x = new_x;
}
if (x < (pageW - w))
{
double new_x = (pageW - w);
if (setoffset)
xOffset = new_x - (pageW / 2.0 - w / 2.0);
x = new_x;
}
}
if (h <= pageH)
{
double new_y = pageH / 2.0 - h / 2.0;
if (setoffset)
yOffset = new_y - (pageH / 2.0 - h / 2.0);
y = new_y;
}
else
{
if (y > 0)
{
double new_y = 0;
if (setoffset)
yOffset = new_y - (pageH / 2.0 - h / 2.0);
y = new_y;
}
if (y < (pageH - h))
{
double new_y = (pageH - h);
if (setoffset)
yOffset = new_y - (pageH / 2.0 - h / 2.0);
y = new_y;
}
}
}
private void PinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (sender != contentPage.Content)
return;
switch (e.Status)
{
case GestureStatus.Started:
{
pitching = true;
collectFirst = true;
double pageW = contentPage.Width;
double pageH = contentPage.Height;
_xScaleOrigin = e.ScaleOrigin.X * pageW;
_yScaleOrigin = e.ScaleOrigin.Y * pageH;
}
break;
case GestureStatus.Running:
if (pitching)
{
double targetScale = scale * e.Scale;
targetScale = Math.Min(Math.Max(scaleMin, targetScale), scaleMax);
double scaleDelta = targetScale / scale;
double pageW = contentPage.Width;
double pageH = contentPage.Height;
double w_old = Content.WidthRequest * scale;
double h_old = Content.HeightRequest * scale;
double x_old = pageW / 2.0 - w_old / 2.0 + xOffset;
double y_old = pageH / 2.0 - h_old / 2.0 + yOffset;
scale = targetScale;
//new w and h
double w = Content.WidthRequest * scale;
double h = Content.HeightRequest * scale;
//transform x old and y old
// to get new scaled position over a pivot
double _x = (x_old - _xScaleOrigin) * scaleDelta + _xScaleOrigin;
double _y = (y_old - _yScaleOrigin) * scaleDelta + _yScaleOrigin;
//fix offset to be equal to _x and _y
double x = pageW / 2.0 - w / 2.0 + xOffset;
double y = pageH / 2.0 - h / 2.0 + yOffset;
xOffset += _x - x;
yOffset += _y - y;
x = pageW / 2.0 - w / 2.0 + xOffset;
y = pageH / 2.0 - h / 2.0 + yOffset;
fixPosition(ref x, ref y, ref w, ref h, true);
AbsoluteLayout.SetLayoutBounds(Content, new Rectangle(x, y, w, h));
}
break;
case GestureStatus.Completed:
pitching = false;
break;
}
}
public void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (sender != contentPage.Content)
return;
switch (e.StatusType)
{
case GestureStatus.Started:
{
panning = true;
panTotalX = e.TotalX;
panTotalY = e.TotalY;
collectFirst = true;
}
break;
case GestureStatus.Running:
if (panning)
{
if (collectFirst)
{
collectFirst = false;
panTotalX = e.TotalX;
panTotalY = e.TotalY;
}
double pageW = contentPage.Width;
double pageH = contentPage.Height;
double deltaX = e.TotalX - panTotalX;
double deltaY = e.TotalY - panTotalY;
panTotalX = e.TotalX;
panTotalY = e.TotalY;
xOffset += deltaX;
yOffset += deltaY;
double w = Content.WidthRequest * scale;
double h = Content.HeightRequest * scale;
double x = pageW / 2.0 - w / 2.0 + xOffset;
double y = pageH / 2.0 - h / 2.0 + yOffset;
fixPosition(ref x, ref y, ref w, ref h, true);
AbsoluteLayout.SetLayoutBounds(Content, new Rectangle(x, y, w, h));
}
break;
case GestureStatus.Completed:
panning = false;
break;
}
}
}
}
在内容页面中:
using System;
using FFImageLoading.Forms;
using Xamarin.Forms;
using Project.Util;
namespace Project.ContentPages
{
public class ContentPage_ImageViewer : ContentPage
{
AbsoluteLayout al = null;
CachedImage image = null;
PanZoom panZoom;
public ContentPage_ImageViewer(string imageURL)
{
MasterDetailPage mdp = Application.Current.MainPage as MasterDetailPage;
mdp.IsGestureEnabled = false;
NavigationPage.SetHasBackButton(this, true);
Title = "";
image = new CachedImage()
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Aspect = Aspect.Fill,
LoadingPlaceholder = "placeholder_320x322.png",
ErrorPlaceholder = "placeholder_320x322.png",
Source = imageURL,
RetryCount = 3,
DownsampleToViewSize = false,
IsVisible = false,
FadeAnimationEnabled = false
};
image.Success += delegate (object sender, CachedImageEvents.SuccessEventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
image.WidthRequest = e.ImageInformation.OriginalWidth;
image.HeightRequest = e.ImageInformation.OriginalHeight;
image.IsVisible = true;
for(int i = al.Children.Count-1; i >= 0; i--)
{
if (al.Children[i] is ActivityIndicator)
al.Children.RemoveAt(i);
}
panZoom.layoutElements();
});
};
ActivityIndicator ai = new ActivityIndicator()
{
IsRunning = true,
Scale = (Device.RuntimePlatform == Device.Android) ? 0.25 : 1.0,
VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.Fill,
Color = Color.White
};
Content = (al = new AbsoluteLayout()
{
VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.Fill,
BackgroundColor = Color.Black,
Children =
{
image,
ai
}
});
AbsoluteLayout.SetLayoutFlags(image, AbsoluteLayoutFlags.None);
AbsoluteLayout.SetLayoutBounds(ai, new Rectangle(0, 0, 1, 1));
AbsoluteLayout.SetLayoutFlags(ai, AbsoluteLayoutFlags.All);
panZoom = new PanZoom();
panZoom.Setup(this, image);
}
}
}