194 lines
5.5 KiB
C#
194 lines
5.5 KiB
C#
using System;
|
|
using Gallery.UI.Theme;
|
|
using Gallery.Utils;
|
|
using Xamarin.Essentials;
|
|
using Xamarin.Forms;
|
|
|
|
namespace Gallery.UI
|
|
{
|
|
public class AdaptedPage : ContentPage
|
|
{
|
|
public static readonly BindableProperty PageTopMarginProperty = BindableProperty.Create(
|
|
nameof(PageTopMargin), typeof(Thickness), typeof(AdaptedPage));
|
|
public static readonly BindableProperty PanelTopMarginProperty = BindableProperty.Create(
|
|
nameof(PanelTopMargin), typeof(Thickness), typeof(AdaptedPage));
|
|
|
|
public Thickness PageTopMargin
|
|
{
|
|
get => (Thickness)GetValue(PageTopMarginProperty);
|
|
protected set => SetValue(PageTopMarginProperty, value);
|
|
}
|
|
public Thickness PanelTopMargin
|
|
{
|
|
get => (Thickness)GetValue(PanelTopMarginProperty);
|
|
protected set => SetValue(PanelTopMarginProperty, value);
|
|
}
|
|
|
|
public event EventHandler Load;
|
|
public event EventHandler Unload;
|
|
|
|
protected static readonly bool isPhone = DeviceInfo.Idiom == DeviceIdiom.Phone;
|
|
|
|
public AdaptedPage()
|
|
{
|
|
SetDynamicResource(Screen.StatusBarStyleProperty, ThemeBase.StatusBarStyle);
|
|
Shell.SetNavBarHasShadow(this, true);
|
|
}
|
|
|
|
public virtual void OnLoad()
|
|
{
|
|
Load?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
public virtual void OnUnload()
|
|
{
|
|
Unload?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
#if __IOS__
|
|
public virtual void OnOrientationChanged(bool landscape)
|
|
{
|
|
var oldMargin = PageTopMargin;
|
|
var oldPanelMargin = PanelTopMargin;
|
|
Thickness newMargin;
|
|
Thickness newPanelMargin;
|
|
if (StyleDefinition.IsFullscreenDevice)
|
|
{
|
|
var iPhone12 =
|
|
#if DEBUG
|
|
DeviceInfo.Name.StartsWith("iPhone 12") ||
|
|
#endif
|
|
DeviceInfo.Model.StartsWith("iPhone13,");
|
|
|
|
newMargin = landscape ?
|
|
AppShell.NavigationBarOffset :
|
|
AppShell.TotalBarOffset;
|
|
newPanelMargin = landscape ?
|
|
AppShell.HalfNavigationBarOffset :
|
|
AppShell.NavigationBarOffset;
|
|
}
|
|
else if (isPhone)
|
|
{
|
|
newMargin = landscape ?
|
|
StyleDefinition.TopOffset32 :
|
|
AppShell.TotalBarOffset;
|
|
newPanelMargin = landscape ?
|
|
StyleDefinition.TopOffset16 :
|
|
StyleDefinition.TopOffset32;
|
|
}
|
|
else
|
|
{
|
|
// iPad
|
|
newMargin = AppShell.TotalBarOffset;
|
|
newPanelMargin = StyleDefinition.TopOffset37;
|
|
}
|
|
if (oldMargin != newMargin)
|
|
{
|
|
PageTopMargin = newMargin;
|
|
OnPageTopMarginChanged(oldMargin, newMargin);
|
|
}
|
|
if (oldPanelMargin != newPanelMargin)
|
|
{
|
|
PanelTopMargin = newPanelMargin;
|
|
}
|
|
}
|
|
|
|
protected virtual void OnPageTopMarginChanged(Thickness old, Thickness @new) { }
|
|
|
|
protected override void OnSizeAllocated(double width, double height)
|
|
{
|
|
base.OnSizeAllocated(width, height);
|
|
OnOrientationChanged(width > height);
|
|
}
|
|
|
|
protected void AnimateToMargin(View element, Thickness margin, bool animate = true)
|
|
{
|
|
var m = margin;
|
|
var start = element.Margin.Top - m.Top;
|
|
#if DEBUG
|
|
if (start != 0)
|
|
{
|
|
App.DebugPrint($"{element.GetType()}, margin-top from {element.Margin.Top} to {margin.Top}");
|
|
}
|
|
#endif
|
|
element.Margin = m;
|
|
if (start > 0 && animate)
|
|
{
|
|
ViewExtensions.CancelAnimations(element);
|
|
element.Animate("margin", top =>
|
|
{
|
|
element.TranslationY = top;
|
|
},
|
|
start, 0,
|
|
#if DEBUG
|
|
length: 500,
|
|
#else
|
|
length: 300,
|
|
#endif
|
|
easing: Easing.SinInOut,
|
|
finished: (v, r) =>
|
|
{
|
|
element.TranslationY = 0;
|
|
});
|
|
}
|
|
}
|
|
#endif
|
|
|
|
protected void Start(Action action)
|
|
{
|
|
if (Tap.IsBusy)
|
|
{
|
|
#if LOG
|
|
App.DebugPrint("gesture recognizer is now busy...");
|
|
#endif
|
|
return;
|
|
}
|
|
using (Tap.Start())
|
|
{
|
|
action();
|
|
}
|
|
}
|
|
|
|
private class Tap : IDisposable
|
|
{
|
|
public static bool IsBusy
|
|
{
|
|
get
|
|
{
|
|
lock (sync)
|
|
{
|
|
return _instance?.isBusy == true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static readonly object sync = new object();
|
|
private static readonly Tap _instance = new Tap();
|
|
|
|
private Tap() { }
|
|
|
|
public static Tap Start()
|
|
{
|
|
lock (sync)
|
|
{
|
|
_instance.isBusy = true;
|
|
}
|
|
return _instance;
|
|
}
|
|
|
|
private bool isBusy = false;
|
|
|
|
public void Dispose()
|
|
{
|
|
isBusy = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class ThicknessEventArgs : EventArgs
|
|
{
|
|
public Thickness OldMargin { get; set; }
|
|
public Thickness NewMargin { get; set; }
|
|
}
|
|
}
|