optimize: follow/illust page animation

This commit is contained in:
Tsanie Lily 2020-05-17 16:15:02 +08:00
parent fb19f9b3f3
commit 91e3ba62bf
9 changed files with 154 additions and 124 deletions

@ -23,7 +23,11 @@ namespace Pixiview.iOS.Renderers
//var mode = ForPage.GetLargeTitleDisplay(page);
//NavigationItem.LargeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Automatic;
page.InitOrientation((Orientation)UIDevice.CurrentDevice.Orientation);
//lastOrientation = UIDevice.CurrentDevice.Orientation;
//var landscape =
// lastOrientation == UIDeviceOrientation.LandscapeLeft ||
// lastOrientation == UIDeviceOrientation.LandscapeRight;
//page.OnOrientationChanged(landscape);
page.OnLoad();
}
}
@ -86,7 +90,10 @@ namespace Pixiview.iOS.Renderers
if (Element is AdaptedPage page)
{
AppShell.Current?.SetStatusBarHeight(UIApplication.SharedApplication.StatusBarFrame.Height);
page.OnOrientationChanged((Orientation)lastOrientation);
var landscape =
lastOrientation == UIDeviceOrientation.LandscapeLeft ||
lastOrientation == UIDeviceOrientation.LandscapeRight;
page.OnOrientationChanged(landscape);
}
}
}

@ -101,6 +101,7 @@ namespace Pixiview
protected override void OnSleep()
{
base.OnSleep();
}
protected override void OnResume()

@ -118,38 +118,34 @@ namespace Pixiview.Illust
}
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
int columns;
#if __IOS__
var oldMargin = PanelTopMargin;
Thickness newMargin;
public override void OnOrientationChanged(bool landscape)
{
base.OnOrientationChanged(landscape);
if (StyleDefinition.IsFullscreenDevice)
{
newMargin = width > height ?
AppShell.HalfNavigationBarOffset :
AppShell.NavigationBarOffset;
topOffset = width > height ?
topOffset = landscape ?
AppShell.NavigationBarOffset.Top :
AppShell.TotalBarOffset.Top;
}
else if (isPhone)
{
newMargin = width > height ?
StyleDefinition.TopOffset16 :
StyleDefinition.TopOffset32;
topOffset = width > height ?
topOffset = landscape ?
StyleDefinition.TopOffset32.Top :
AppShell.TotalBarOffset.Top;
}
else
{
// ipad
newMargin = StyleDefinition.TopOffset37;
// iPad
topOffset = AppShell.TotalBarOffset.Top;
}
}
#endif
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
int columns;
if (width > height)
{
columns = isPhone ? 4 : 6;
@ -158,13 +154,6 @@ namespace Pixiview.Illust
{
columns = isPhone ? 2 : 4;
}
#if __IOS__
if (oldMargin != newMargin)
{
PanelTopMargin = newMargin;
OnPanelTopMarginChanged(oldMargin, newMargin);
}
#endif
if (Columns != columns)
{
Columns = columns;
@ -301,7 +290,7 @@ namespace Pixiview.Illust
if (scrollView.ScrollY > -topOffset)
{
#if __IOS__
await scrollView.ScrollToAsync(0, -topOffset, true);
await scrollView.ScrollToAsync(scrollView.ScrollX, -topOffset, true);
#else
await scrollView.ScrollToAsync(0, -topOffset, false);
#endif

@ -32,12 +32,10 @@
</StackLayout>
</ScrollView>
<u:BlurryPanel x:Name="panelBar" VerticalOptions="Start"
HeightRequest="{OnPlatform Android=40, iOS=50}"
Margin="{Binding PanelTopMargin}"/>
HeightRequest="{OnPlatform Android=40, iOS=50}"/>
<SearchBar x:Name="searchBar" Placeholder="{r:Text Search}"
HeightRequest="{OnPlatform Android=40, iOS=50}"
VerticalOptions="Start"
Margin="{Binding PageTopMargin}"
CancelButtonColor="{DynamicResource TintColor}"
Text="{Binding Keywords, Mode=TwoWay}"
SearchButtonPressed="SearchBar_SearchButtonPressed"/>

@ -38,6 +38,23 @@ namespace Pixiview.Illust
protected override ActivityIndicator LoadingIndicator => activityLoading;
protected override double IndicatorMarginTop => 66;
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
searchBar.Margin = PageTopMargin;
panelBar.Margin = PanelTopMargin;
}
#if __IOS__
public override void OnOrientationChanged(bool landscape)
{
base.OnOrientationChanged(landscape);
AnimateToMargin(searchBar, PageTopMargin);
AnimateToMargin(panelBar, PanelTopMargin);
}
#endif
protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data)
{
if (data.body == null)

@ -233,7 +233,7 @@ namespace Pixiview.Illust
if (scrollDirection == ScrollDirection.Down)
{
// stop the scrolling
await scrollView.ScrollToAsync(0, scrollView.ScrollY, false);
await scrollView.ScrollToAsync(scrollView.ScrollX, scrollView.ScrollY, false);
}
await Task.WhenAll(
labelCaret.RotateTo(180, easing: Easing.CubicOut),

@ -15,7 +15,7 @@
<ToolbarItem Order="Primary" Clicked="More_Clicked"
IconImageSource="{DynamicResource FontIconMore}"/>
</ContentPage.ToolbarItems>
<Grid Padding="{Binding PageTopMargin}" RowSpacing="0">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
@ -29,20 +29,22 @@
</CarouselView.ItemsLayout>
</CarouselView>
<ProgressBar x:Name="progress" IsVisible="{Binding ProgressVisible}"
Progress="0.05"
VerticalOptions="Start">
<ProgressBar.Margin>
<OnPlatform x:TypeArguments="Thickness" Android="0, -6, 0, 0"/>
</ProgressBar.Margin>
</ProgressBar>
<Grid Margin="{Binding PageTopMargin}" VerticalOptions="Start">
<ProgressBar x:Name="progress" IsVisible="{Binding ProgressVisible}"
Progress="0.05">
<ProgressBar.Margin>
<OnPlatform x:TypeArguments="Thickness" Android="0, -6, 0, 0"/>
</ProgressBar.Margin>
</ProgressBar>
</Grid>
<u:RoundLabel Text="{Binding PagePositionText}"
BackgroundColor="{DynamicResource MaskColor}" Margin="0, 6, 6, 0"
Padding="6, 4" CornerRadius="6"
HorizontalOptions="End" VerticalOptions="Start"
FontSize="Micro" TextColor="White"
IsVisible="{Binding IsPageVisible}"/>
<Grid Margin="{Binding PageTopMargin}" IsVisible="{Binding IsPageVisible}"
HorizontalOptions="End" VerticalOptions="Start">
<u:RoundLabel Text="{Binding PagePositionText}"
BackgroundColor="{DynamicResource MaskColor}" Margin="0, 6, 6, 0"
Padding="6, 4" CornerRadius="6"
FontSize="Micro" TextColor="White"/>
</Grid>
<u:RoundLabel Text="{Binding AnimeStatus}"
BackgroundColor="{DynamicResource MaskColor}" Margin="0, 0, 6, 6"

@ -162,11 +162,6 @@ namespace Pixiview.Illust
}
}
public override void OnLoad()
{
OnOrientationChanged(CurrentOrientation);
}
protected override void OnAppearing()
{
base.OnAppearing();
@ -193,6 +188,20 @@ namespace Pixiview.Illust
}
}
#if __IOS__
protected override void OnPageTopMarginChanged(Thickness old, Thickness @new)
{
var illusts = Illusts;
if (illusts != null)
{
for (var i = 0; i < illusts.Length; i++)
{
illusts[i].TopPadding = @new;
}
}
}
#endif
private DataTemplate GetCarouseTemplate()
{
return new DataTemplate(() =>
@ -241,7 +250,7 @@ namespace Pixiview.Illust
var tapNext = new TapGestureRecognizer();
tapNext.Tapped += TapNext_Tapped;
return new Grid
var grid = new Grid
{
Children =
{
@ -272,6 +281,10 @@ namespace Pixiview.Illust
original
}
};
#if __IOS__
grid.SetBinding(Xamarin.Forms.Layout.PaddingProperty, nameof(IllustDetailItem.TopPadding));
#endif
return grid;
});
}
@ -288,10 +301,16 @@ namespace Pixiview.Illust
PagePositionText = $"1/{items.Length}";
}
#if __IOS__
var topMargin = PageTopMargin;
#endif
for (var i = 0; i < items.Length; i++)
{
items[i] = new IllustDetailItem
{
#if __IOS__
TopPadding = topMargin,
#endif
Id = illust.Id
};
if (i == 0)
@ -320,12 +339,18 @@ namespace Pixiview.Illust
App.DebugPrint($"local page count ({items.Length}) is not equals the remote one ({pages.body.Length})");
var tmp = new IllustDetailItem[pages.body.Length];
items.CopyTo(items, 0);
#if __IOS__
var topMargin = PageTopMargin;
#endif
for (var i = items.Length; i < tmp.Length; i++)
{
tmp[i] = new IllustDetailItem
{
Id = illustItem.Id,
Loading = true
#if __IOS__
TopPadding = topMargin,
#endif
Loading = i == 0
};
}
Illusts = items = tmp;
@ -703,6 +728,16 @@ namespace Pixiview.Illust
nameof(Loading), typeof(bool), typeof(IllustDetailItem));
public static readonly BindableProperty DownloadingProperty = BindableProperty.Create(
nameof(Downloading), typeof(bool), typeof(IllustDetailItem));
#if __IOS__
public static readonly BindableProperty TopPaddingProperty = BindableProperty.Create(
nameof(TopPadding), typeof(Thickness), typeof(IllustDetailItem));
public Thickness TopPadding
{
get => (Thickness)GetValue(TopPaddingProperty);
set => SetValue(TopPaddingProperty, value);
}
#endif
public ImageSource Image
{

@ -23,12 +23,9 @@ namespace Pixiview.UI
get => (Thickness)GetValue(PanelTopMarginProperty);
protected set => SetValue(PanelTopMarginProperty, value);
}
public Orientation CurrentOrientation { get; private set; }
public event EventHandler Load;
public event EventHandler Unload;
public event EventHandler<ThicknessEventArgs> PageTopMarginChanged;
public event EventHandler<OrientationEventArgs> OrientationChanged;
protected static readonly bool isPhone = DeviceInfo.Idiom == DeviceIdiom.Phone;
@ -48,85 +45,83 @@ namespace Pixiview.UI
Unload?.Invoke(this, EventArgs.Empty);
}
public virtual void OnOrientationChanged(Orientation orientation)
{
#if __IOS__
public virtual void OnOrientationChanged(bool landscape)
{
var oldMargin = PageTopMargin;
var oldPanelMargin = PanelTopMargin;
Thickness newMargin;
switch (orientation)
Thickness newPanelMargin;
if (StyleDefinition.IsFullscreenDevice)
{
case Orientation.Portrait:
newMargin = AppShell.TotalBarOffset;
break;
case Orientation.PortraitUpsideDown:
case Orientation.Unknown:
case Orientation.LandscapeLeft:
case Orientation.LandscapeRight:
default:
if (StyleDefinition.IsFullscreenDevice)
{
newMargin = AppShell.NavigationBarOffset;
}
else
{
newMargin = isPhone ? StyleDefinition.TopOffset32 : AppShell.TotalBarOffset;
}
break;
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);
}
#endif
OrientationChanged?.Invoke(this, new OrientationEventArgs { CurrentOrientation = orientation });
if (oldPanelMargin != newPanelMargin)
{
PanelTopMargin = newPanelMargin;
}
}
#if __IOS__
protected virtual void OnPageTopMarginChanged(Thickness old, Thickness @new) { }
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
OnOrientationChanged(width > height);
}
if (PageTopMargin == default)
protected void AnimateToMargin(View element, Thickness margin, bool animate = true)
{
var m = margin;
var start = element.Margin.Top - m.Top;
element.Margin = m;
if (start != 0 && animate)
{
if (StyleDefinition.IsFullscreenDevice)
ViewExtensions.CancelAnimations(element);
element.Animate("margin", top =>
{
PageTopMargin = width > height ?
AppShell.NavigationBarOffset :
AppShell.TotalBarOffset;
}
else if (isPhone)
element.TranslationY = top;
},
start, 0,
#if DEBUG
length: 500,
#else
length: 300,
#endif
easing: Easing.SinInOut,
finished: (v, r) =>
{
PageTopMargin = width > height ?
StyleDefinition.TopOffset32 :
AppShell.TotalBarOffset;
}
else
{
PageTopMargin = AppShell.TotalBarOffset;
}
element.TranslationY = 0;
});
}
}
#endif
public virtual void OnPageTopMarginChanged(Thickness old, Thickness @new)
{
PageTopMarginChanged?.Invoke(this, new ThicknessEventArgs
{
OldMargin = old,
NewMargin = @new
});
}
public virtual void OnPanelTopMarginChanged(Thickness old, Thickness @new)
{
}
public void InitOrientation(Orientation orientation)
{
CurrentOrientation = orientation;
}
protected void Start(Action action)
{
if (Tap.IsBusy)
@ -175,18 +170,4 @@ namespace Pixiview.UI
public Thickness OldMargin { get; set; }
public Thickness NewMargin { get; set; }
}
public class OrientationEventArgs : EventArgs
{
public Orientation CurrentOrientation { get; set; }
}
public enum Orientation
{
Unknown,
Portrait,
PortraitUpsideDown,
LandscapeLeft,
LandscapeRight
}
}