adjust UI
This commit is contained in:
148
Gallery.Share/Resources/UI/AdaptedPage.cs
Normal file
148
Gallery.Share/Resources/UI/AdaptedPage.cs
Normal file
@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using Gallery.Services;
|
||||
using Gallery.Util;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.Resources.UI
|
||||
{
|
||||
public class AdaptedPage : ContentPage
|
||||
{
|
||||
public static readonly BindableProperty TopMarginProperty = BindableProperty.Create(nameof(TopMargin), typeof(Thickness), typeof(AdaptedPage));
|
||||
|
||||
public Thickness TopMargin
|
||||
{
|
||||
get => (Thickness)GetValue(TopMarginProperty);
|
||||
set => SetValue(TopMarginProperty, value);
|
||||
}
|
||||
|
||||
public event EventHandler Load;
|
||||
public event EventHandler Unload;
|
||||
|
||||
protected static readonly bool isPhone = DeviceInfo.Idiom == DeviceIdiom.Phone;
|
||||
|
||||
public AdaptedPage()
|
||||
{
|
||||
SetDynamicResource(Screen.StatusBarStyleProperty, Theme.Theme.StatusBarStyle);
|
||||
Shell.SetNavBarHasShadow(this, true);
|
||||
}
|
||||
|
||||
public virtual void OnLoad() => Load?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
public virtual void OnUnload() => Unload?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
public virtual void OnOrientationChanged(bool landscape)
|
||||
{
|
||||
var old = TopMargin;
|
||||
Thickness @new;
|
||||
if (Definition.IsFullscreenDevice)
|
||||
{
|
||||
@new = landscape ?
|
||||
AppShell.NavigationBarOffset :
|
||||
AppShell.TotalBarOffset;
|
||||
}
|
||||
else if (isPhone)
|
||||
{
|
||||
@new = landscape ?
|
||||
Definition.TopOffset32 :
|
||||
AppShell.TotalBarOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iPad
|
||||
@new = AppShell.TotalBarOffset;
|
||||
}
|
||||
if (old != @new)
|
||||
{
|
||||
TopMargin = @new;
|
||||
OnTopMarginChanged(old, @new);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnTopMarginChanged(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;
|
||||
element.Margin = m;
|
||||
element.CancelAnimations();
|
||||
if (start > 0 && animate)
|
||||
{
|
||||
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;
|
||||
});
|
||||
}
|
||||
else if (element.TranslationY != 0)
|
||||
{
|
||||
element.TranslationY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void Start(Action action)
|
||||
{
|
||||
if (Tap.IsBusy)
|
||||
{
|
||||
Log.Error($"{GetType()}.tap", "gesture recognizer is now busy...");
|
||||
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();
|
||||
private static readonly Tap instance = new();
|
||||
|
||||
private Tap() { }
|
||||
|
||||
public static Tap Start()
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
instance.isBusy = true;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private bool isBusy = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
isBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user