feature: scroll animation in follow/ranking page
This commit is contained in:
parent
ef70d7108a
commit
6235430ded
@ -12,7 +12,8 @@
|
|||||||
IconImageSource="{DynamicResource FontIconRefresh}"/>
|
IconImageSource="{DynamicResource FontIconRefresh}"/>
|
||||||
</ContentPage.ToolbarItems>
|
</ContentPage.ToolbarItems>
|
||||||
<Grid>
|
<Grid>
|
||||||
<ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never">
|
<ScrollView HorizontalOptions="Fill" HorizontalScrollBarVisibility="Never"
|
||||||
|
Scrolled="ScrollView_Scrolled">
|
||||||
<u:FlowLayout ItemsSource="{Binding Illusts}"
|
<u:FlowLayout ItemsSource="{Binding Illusts}"
|
||||||
HorizontalOptions="Fill" Column="{Binding Columns}"
|
HorizontalOptions="Fill" Column="{Binding Columns}"
|
||||||
RowSpacing="16" ColumnSpacing="16"
|
RowSpacing="16" ColumnSpacing="16"
|
||||||
@ -24,7 +25,8 @@
|
|||||||
</u:FlowLayout.Margin>
|
</u:FlowLayout.Margin>
|
||||||
</u:FlowLayout>
|
</u:FlowLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<u:BlurryPanel VerticalOptions="Start" HeightRequest="{OnPlatform Android=40, iOS=50}"
|
<u:BlurryPanel x:Name="panelBar" VerticalOptions="Start"
|
||||||
|
HeightRequest="{OnPlatform Android=40, iOS=50}"
|
||||||
Margin="{Binding PanelTopMargin}"/>
|
Margin="{Binding PanelTopMargin}"/>
|
||||||
<SearchBar x:Name="searchBar" Placeholder="{r:Text Search}"
|
<SearchBar x:Name="searchBar" Placeholder="{r:Text Search}"
|
||||||
HeightRequest="{OnPlatform Android=40, iOS=50}"
|
HeightRequest="{OnPlatform Android=40, iOS=50}"
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
|
||||||
using Pixiview.Utils;
|
using Pixiview.Utils;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
@ -19,6 +18,9 @@ namespace Pixiview.Illust
|
|||||||
set => SetValue(KeywordsProperty, value);
|
set => SetValue(KeywordsProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double lastScrollY = double.MinValue;
|
||||||
|
private ScrollDirection scrollDirection = ScrollDirection.Stop;
|
||||||
|
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
Resources.Add("cardView", GetCardViewTemplate());
|
Resources.Add("cardView", GetCardViewTemplate());
|
||||||
@ -26,24 +28,17 @@ namespace Pixiview.Illust
|
|||||||
|
|
||||||
#if __IOS__
|
#if __IOS__
|
||||||
searchBar.BackgroundColor = Color.Transparent;
|
searchBar.BackgroundColor = Color.Transparent;
|
||||||
#elif __ANDROID__
|
#else
|
||||||
searchBar.SetDynamicResource(SearchBar.TextColorProperty, UI.Theme.ThemeBase.TextColor);
|
searchBar.SetDynamicResource(SearchBar.TextColorProperty, UI.Theme.ThemeBase.TextColor);
|
||||||
searchBar.SetDynamicResource(SearchBar.PlaceholderColorProperty, UI.Theme.ThemeBase.SubTextColor);
|
searchBar.SetDynamicResource(SearchBar.PlaceholderColorProperty, UI.Theme.ThemeBase.SubTextColor);
|
||||||
searchBar.SetDynamicResource(BackgroundColorProperty, UI.Theme.ThemeBase.WindowColor);
|
searchBar.SetDynamicResource(BackgroundColorProperty, UI.Theme.ThemeBase.WindowColor);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data, ICommand command)
|
protected override IEnumerable<IllustItem> DoGetIllustList(IllustData data)
|
||||||
{
|
{
|
||||||
return data.body.page.follow.Select(i =>
|
return data.body.page.follow.Select(i =>
|
||||||
{
|
data.body.thumbnails.illust.FirstOrDefault(l => l.illustId == i.ToString())?.ConvertToItem());
|
||||||
var item = data.body.thumbnails.illust.FirstOrDefault(l => l.illustId == i.ToString())?.ConvertToItem();
|
|
||||||
if (item != null)
|
|
||||||
{
|
|
||||||
item.IllustTapped = command;
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IllustData DoLoadIllustData(bool force)
|
protected override IllustData DoLoadIllustData(bool force)
|
||||||
@ -73,5 +68,41 @@ namespace Pixiview.Illust
|
|||||||
Task.Run(() => App.OpenUrl(new Uri("pixiview://example.com/artworks/" + key)));
|
Task.Run(() => App.OpenUrl(new Uri("pixiview://example.com/artworks/" + key)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __IOS__
|
||||||
|
private const int searchBarHeight = 50;
|
||||||
|
#else
|
||||||
|
private const int searchBarHeight = 40;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
|
||||||
|
{
|
||||||
|
var y = e.ScrollY;
|
||||||
|
if (y > lastScrollY)
|
||||||
|
{
|
||||||
|
// down
|
||||||
|
if (scrollDirection != ScrollDirection.Down && y > searchBarHeight - topOffset)
|
||||||
|
{
|
||||||
|
scrollDirection = ScrollDirection.Down;
|
||||||
|
ViewExtensions.CancelAnimations(searchBar);
|
||||||
|
ViewExtensions.CancelAnimations(panelBar);
|
||||||
|
searchBar.TranslateTo(0, -searchBarHeight, easing: Easing.CubicIn);
|
||||||
|
panelBar.TranslateTo(0, -searchBarHeight, easing: Easing.CubicIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// up
|
||||||
|
if (scrollDirection != ScrollDirection.Up)
|
||||||
|
{
|
||||||
|
scrollDirection = ScrollDirection.Up;
|
||||||
|
ViewExtensions.CancelAnimations(searchBar);
|
||||||
|
ViewExtensions.CancelAnimations(panelBar);
|
||||||
|
searchBar.TranslateTo(0, 0, easing: Easing.CubicOut);
|
||||||
|
panelBar.TranslateTo(0, 0, easing: Easing.CubicOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastScrollY = y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
xmlns:u="clr-namespace:Pixiview.UI"
|
xmlns:u="clr-namespace:Pixiview.UI"
|
||||||
xmlns:r="clr-namespace:Pixiview.Resources"
|
xmlns:r="clr-namespace:Pixiview.Resources"
|
||||||
x:Class="Pixiview.Illust.RankingPage"
|
x:Class="Pixiview.Illust.RankingPage"
|
||||||
BackgroundColor="{DynamicResource WindowColor}">
|
BackgroundColor="{DynamicResource WindowColor}"
|
||||||
|
Title="{r:Text Ranking}">
|
||||||
<Shell.TitleView>
|
<Shell.TitleView>
|
||||||
<Grid VerticalOptions="Fill" ColumnSpacing="6"
|
<Grid VerticalOptions="Fill" ColumnSpacing="6"
|
||||||
HorizontalOptions="{x:OnPlatform Android=Start, iOS=Fill}">
|
HorizontalOptions="{x:OnPlatform Android=Start, iOS=Fill}">
|
||||||
@ -23,7 +24,8 @@
|
|||||||
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
|
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
|
||||||
</Label.GestureRecognizers>
|
</Label.GestureRecognizers>
|
||||||
</Label>
|
</Label>
|
||||||
<Label Grid.Column="2" Text="{Binding PanelState}"
|
<Label Grid.Column="2" x:Name="labelCaret"
|
||||||
|
Text="{DynamicResource IconCaretDown}"
|
||||||
TextColor="{DynamicResource TextColor}"
|
TextColor="{DynamicResource TextColor}"
|
||||||
FontFamily="{DynamicResource IconSolidFontFamily}"
|
FontFamily="{DynamicResource IconSolidFontFamily}"
|
||||||
FontSize="Small"
|
FontSize="Small"
|
||||||
@ -44,6 +46,7 @@
|
|||||||
</ScrollView>
|
</ScrollView>
|
||||||
<u:BlurryPanel x:Name="panelFilter" VerticalOptions="Start" Opacity="0"
|
<u:BlurryPanel x:Name="panelFilter" VerticalOptions="Start" Opacity="0"
|
||||||
Margin="{Binding PanelTopMargin}"
|
Margin="{Binding PanelTopMargin}"
|
||||||
|
BackgroundColor="{DynamicResource WindowColor}"
|
||||||
HeightRequest="{Binding Height, Source={x:Reference gridFilter}}"/>
|
HeightRequest="{Binding Height, Source={x:Reference gridFilter}}"/>
|
||||||
<Grid x:Name="gridFilter" VerticalOptions="Start" Opacity="0"
|
<Grid x:Name="gridFilter" VerticalOptions="Start" Opacity="0"
|
||||||
Margin="{Binding PageTopMargin}" Padding="10">
|
Margin="{Binding PageTopMargin}" Padding="10">
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
|
||||||
using Pixiview.Resources;
|
using Pixiview.Resources;
|
||||||
using Pixiview.UI;
|
|
||||||
using Pixiview.Utils;
|
using Pixiview.Utils;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@ -16,8 +14,6 @@ namespace Pixiview.Illust
|
|||||||
private static readonly string[] segmentDates = { "daily", "weekly", "monthly", "male" };
|
private static readonly string[] segmentDates = { "daily", "weekly", "monthly", "male" };
|
||||||
private static readonly object sync = new object();
|
private static readonly object sync = new object();
|
||||||
|
|
||||||
public static readonly BindableProperty PanelStateProperty = BindableProperty.Create(
|
|
||||||
nameof(PanelState), typeof(string), typeof(RankingPage), StyleDefinition.IconCaretDown);
|
|
||||||
public static readonly BindableProperty SegmentDateProperty = BindableProperty.Create(
|
public static readonly BindableProperty SegmentDateProperty = BindableProperty.Create(
|
||||||
nameof(SegmentDate), typeof(int), typeof(RankingPage), propertyChanged: OnSegmentDatePropertyChanged);
|
nameof(SegmentDate), typeof(int), typeof(RankingPage), propertyChanged: OnSegmentDatePropertyChanged);
|
||||||
public static readonly BindableProperty SegmentTypeProperty = BindableProperty.Create(
|
public static readonly BindableProperty SegmentTypeProperty = BindableProperty.Create(
|
||||||
@ -54,11 +50,6 @@ namespace Pixiview.Illust
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string PanelState
|
|
||||||
{
|
|
||||||
get => (string)GetValue(PanelStateProperty);
|
|
||||||
set => SetValue(PanelStateProperty, value);
|
|
||||||
}
|
|
||||||
public int SegmentDate
|
public int SegmentDate
|
||||||
{
|
{
|
||||||
get => (int)GetValue(SegmentDateProperty);
|
get => (int)GetValue(SegmentDateProperty);
|
||||||
@ -70,8 +61,9 @@ namespace Pixiview.Illust
|
|||||||
set => SetValue(SegmentTypeProperty, value);
|
set => SetValue(SegmentTypeProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double lastScrollY = double.MinValue;
|
||||||
|
|
||||||
private bool isFilterVisible;
|
private bool isFilterVisible;
|
||||||
private double topOffset;
|
|
||||||
private string lastQueryKey;
|
private string lastQueryKey;
|
||||||
private string queryDate;
|
private string queryDate;
|
||||||
private int currentPage;
|
private int currentPage;
|
||||||
@ -91,30 +83,6 @@ namespace Pixiview.Illust
|
|||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnSizeAllocated(double width, double height)
|
|
||||||
{
|
|
||||||
base.OnSizeAllocated(width, height);
|
|
||||||
if (StyleDefinition.IsFullscreenDevice)
|
|
||||||
{
|
|
||||||
topOffset = width > height ?
|
|
||||||
AppShell.NavigationBarOffset.Top :
|
|
||||||
AppShell.TotalBarOffset.Top;
|
|
||||||
}
|
|
||||||
else if (isPhone)
|
|
||||||
{
|
|
||||||
topOffset = width > height ?
|
|
||||||
StyleDefinition.TopOffset32.Top :
|
|
||||||
AppShell.TotalBarOffset.Top;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: ipad
|
|
||||||
topOffset = AppShell.TotalBarOffset.Top;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool IsLazyload => true;
|
|
||||||
|
|
||||||
protected override void DoIllustsLoaded(IllustCollection collection)
|
protected override void DoIllustsLoaded(IllustCollection collection)
|
||||||
{
|
{
|
||||||
var now = IllustCollection;
|
var now = IllustCollection;
|
||||||
@ -131,17 +99,9 @@ namespace Pixiview.Illust
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<IllustItem> DoGetIllustList(IllustRankingData data, ICommand command)
|
protected override IEnumerable<IllustItem> DoGetIllustList(IllustRankingData data)
|
||||||
{
|
{
|
||||||
return data.contents.Select(i =>
|
return data.contents.Select(i => i.ConvertToItem());
|
||||||
{
|
|
||||||
var item = i.ConvertToItem();
|
|
||||||
if (item != null)
|
|
||||||
{
|
|
||||||
item.IllustTapped = command;
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IllustRankingData DoLoadIllustData(bool force)
|
protected override IllustRankingData DoLoadIllustData(bool force)
|
||||||
@ -176,8 +136,8 @@ namespace Pixiview.Illust
|
|||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
isFilterVisible = true;
|
isFilterVisible = true;
|
||||||
PanelState = StyleDefinition.IconCaretUp;
|
|
||||||
await Task.WhenAll(
|
await Task.WhenAll(
|
||||||
|
labelCaret.RotateTo(180, easing: Easing.CubicOut),
|
||||||
gridFilter.TranslateTo(0, 0, easing: Easing.CubicOut),
|
gridFilter.TranslateTo(0, 0, easing: Easing.CubicOut),
|
||||||
gridFilter.FadeTo(1, easing: Easing.CubicOut),
|
gridFilter.FadeTo(1, easing: Easing.CubicOut),
|
||||||
panelFilter.TranslateTo(0, 0, easing: Easing.CubicOut),
|
panelFilter.TranslateTo(0, 0, easing: Easing.CubicOut),
|
||||||
@ -187,12 +147,12 @@ namespace Pixiview.Illust
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
isFilterVisible = false;
|
isFilterVisible = false;
|
||||||
PanelState = StyleDefinition.IconCaretDown;
|
|
||||||
await Task.WhenAll(
|
await Task.WhenAll(
|
||||||
gridFilter.TranslateTo(0, -100, easing: Easing.CubicOut),
|
labelCaret.RotateTo(0, easing: Easing.CubicIn),
|
||||||
gridFilter.FadeTo(0, easing: Easing.CubicOut),
|
gridFilter.TranslateTo(0, -100, easing: Easing.CubicIn),
|
||||||
panelFilter.TranslateTo(0, -100, easing: Easing.CubicOut),
|
gridFilter.FadeTo(0, easing: Easing.CubicIn),
|
||||||
panelFilter.FadeTo(0, easing: Easing.CubicOut)
|
panelFilter.TranslateTo(0, -100, easing: Easing.CubicIn),
|
||||||
|
panelFilter.FadeTo(0, easing: Easing.CubicIn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,8 +175,19 @@ namespace Pixiview.Illust
|
|||||||
|
|
||||||
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
|
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
|
||||||
{
|
{
|
||||||
|
var y = e.ScrollY;
|
||||||
|
if (y > lastScrollY)
|
||||||
|
{
|
||||||
|
// down
|
||||||
|
if (isFilterVisible)
|
||||||
|
{
|
||||||
|
ToggleFilterPanel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastScrollY = y;
|
||||||
|
|
||||||
var bottomOffset = scrollView.ContentSize.Height - (scrollView.LayoutAreaOverride.Height * 2);
|
var bottomOffset = scrollView.ContentSize.Height - (scrollView.LayoutAreaOverride.Height * 2);
|
||||||
if (e.ScrollY > 0 && e.ScrollY + topOffset > bottomOffset)
|
if (y > 0 && y + topOffset > bottomOffset)
|
||||||
{
|
{
|
||||||
bool refresh = false;
|
bool refresh = false;
|
||||||
lock (sync)
|
lock (sync)
|
||||||
@ -235,6 +206,7 @@ namespace Pixiview.Illust
|
|||||||
}
|
}
|
||||||
if (refresh)
|
if (refresh)
|
||||||
{
|
{
|
||||||
|
App.DebugPrint($"start to load page {nextPage}");
|
||||||
StartLoad(true);
|
StartLoad(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user