Skip to content

Commit

Permalink
added new caching logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-Dobrynin committed Jul 23, 2024
1 parent 3fb84aa commit 71e235a
Show file tree
Hide file tree
Showing 17 changed files with 281 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,84 +4,63 @@

using AndroidX.Core.Widget;

using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;

namespace MPowerKit.VirtualizeListView;

public class VirtualizeListViewRenderer : ScrollViewHandler
public partial class VirtualizeListViewHandler
{
protected override MauiScrollView CreatePlatformView()
{
var scrollView = new SmoothScrollView(
new ContextThemeWrapper(MauiContext!.Context, Resource.Style.scrollViewTheme), null!,
Resource.Attribute.scrollViewStyle)
new ContextThemeWrapper(MauiContext!.Context, Resource.Style.scrollViewTheme),
null!,
Resource.Attribute.scrollViewStyle,
VirtualView as VirtualizeListView)
{
ClipToOutline = true,
FillViewport = true
};

return scrollView;
}

protected override void ConnectHandler(MauiScrollView platformView)
{
base.ConnectHandler(platformView);

if (VirtualView is VirtualizeListView listView)
{
listView.AdjustScrollRequested += ListView_AdjustScrollRequested;
}
}

protected override void DisconnectHandler(MauiScrollView platformView)
{
if (VirtualView is VirtualizeListView listView)
{
listView.AdjustScrollRequested -= ListView_AdjustScrollRequested;
}

base.DisconnectHandler(platformView);
}

private void ListView_AdjustScrollRequested(object? sender, (double dx, double dy) e)
{
if (PlatformView is SmoothScrollView scrollView)
{
scrollView.AdjustScroll((int)this.Context.ToPixels(e.dx), (int)this.Context.ToPixels(e.dy));
}
}
}

public class SmoothScrollView : MauiScrollView
{
private OverScroller _scroller;

public SmoothScrollView(Context context) : base(context)
private VirtualizeListView _listView;

public SmoothScrollView(Context context, VirtualizeListView listView) : base(context)
{
Init(context);
Init(context, listView);
}

public SmoothScrollView(Context context, Android.Util.IAttributeSet attrs) : base(context, attrs)
public SmoothScrollView(Context context, Android.Util.IAttributeSet attrs, VirtualizeListView listView) : base(context, attrs)
{
Init(context);
Init(context, listView);
}

public SmoothScrollView(Context context, Android.Util.IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
public SmoothScrollView(Context context, Android.Util.IAttributeSet attrs, int defStyleAttr, VirtualizeListView listView) : base(context, attrs, defStyleAttr)
{
Init(context);
Init(context, listView);
}

private void Init(Context context)
private void Init(Context context, VirtualizeListView listView)
{
var field = Java.Lang.Class.FromType(typeof(NestedScrollView)).GetDeclaredField("mScroller");
field.Accessible = true;

_scroller = (field.Get(this) as OverScroller)!;
_listView = listView;
}

public virtual void AdjustScroll(int dx, int dy)
public virtual void AdjustScroll(double dxdp, double dydp)
{
var dx = (int)this.Context.ToPixels(dxdp);
var dy = (int)this.Context.ToPixels(dydp);

if (!_scroller.IsFinished)
{
var velocity = _scroller.CurrVelocity + dy;
Expand All @@ -91,14 +70,21 @@ public virtual void AdjustScroll(int dx, int dy)
this.ScrollBy(dx, dy);

_scroller.ForceFinished(true);
Fling((int)direction);
base.Fling((int)direction);
}
else
{
ScrollBy(dx, dy);
}
}

public override void Fling(int velocityY)
{
velocityY = (int)(velocityY / (int)_listView.ScrollSpeed);

base.Fling(velocityY);
}

protected override void OnScrollChanged(int l, int t, int oldl, int oldt)
{
base.OnScrollChanged(l, t, oldl, oldt);
Expand Down
7 changes: 2 additions & 5 deletions MPowerKit.VirtualizeListView/BuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ public static MauiAppBuilder UseMPowerKitListView(this MauiAppBuilder builder)
{
builder.ConfigureMauiHandlers(handlers =>
{
#if ANDROID
handlers.AddHandler<VirtualizeListView, VirtualizeListViewRenderer>();
#endif
#if ANDROID || IOS
#if !WINDOWS
handlers.AddHandler<VirtualizeListView, VirtualizeListViewHandler>();
handlers.AddHandler<FixedRefreshView, FixedRefreshViewRenderer>();
#endif
});
Expand Down
1 change: 1 addition & 0 deletions MPowerKit.VirtualizeListView/CellHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
public class CellHolder : Grid
{
public VirtualizeListViewItem? Item { get; set; }
public bool IsCached => Item is null;

public CellHolder()
{
Expand Down
31 changes: 22 additions & 9 deletions MPowerKit.VirtualizeListView/ItemsLayoutManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ public override Size Measure(double widthConstraint, double heightConstraint)
var measuredHeight = 0d;
var measuredWidth = 0d;

Size newSize = new();
if (Layout.ReadOnlyLaidOutItems.Count > 0)
{
var lastItem = Layout.ReadOnlyLaidOutItems[^1];

newSize = new(lastItem.Bounds.Right, lastItem.Bounds.Bottom);
}

var items = CollectionsMarshal.AsSpan((Layout as IBindableLayout).Children as List<IView>);
var length = items.Length;

Expand All @@ -26,20 +34,25 @@ public override Size Measure(double widthConstraint, double heightConstraint)
var child = items[n];
var view = child as CellHolder;

if (view.Item!.IsCached || !view.Item.IsAttached) continue;
if (/*view.Item!.IsCached ||*/ view.IsCached || !view.Item.IsAttached) continue;

var bounds = view.Item.CellBounds;
//var bounds = view.Item.CellBounds;

var measure = child.Measure(double.PositiveInfinity, double.PositiveInfinity);

measuredWidth = Math.Max(measuredWidth, bounds.Left + view.Item.Margin.Right + measure.Width);
measuredHeight = Math.Max(measuredHeight, bounds.Top + view.Item.Margin.Bottom + measure.Height);
//measuredWidth = Math.Max(measuredWidth, bounds.Left + view.Item.Margin.Right + measure.Width);
//measuredHeight = Math.Max(measuredHeight, bounds.Top + view.Item.Margin.Bottom + measure.Height);
}

var finalWidth = GetFinalLength(Layout.Width, widthConstraint, measuredWidth);
var finalHeight = GetFinalLength(Layout.Height, heightConstraint, measuredHeight);
//var finalWidth = GetFinalLength(Layout.Width, widthConstraint, measuredWidth);
//var finalHeight = GetFinalLength(Layout.Height, heightConstraint, measuredHeight);

//var finalWidth = GetFinalLength(newSize.Width, widthConstraint, measuredWidth);
//var finalHeight = GetFinalLength(newSize.Height, heightConstraint, measuredHeight);

//return new(finalWidth, finalHeight);

return new(finalWidth, finalHeight);
return newSize;
}

public override Size ArrangeChildren(Rect bounds)
Expand All @@ -57,9 +70,9 @@ public override Size ArrangeChildren(Rect bounds)
var child = items[n];
var view = child as CellHolder;
#if WINDOWS
if (view.Item.IsCached || !view.Item.IsAttached) continue;
if (/*view.Item.IsCached ||*/ view.IsCached || !view.Item.IsAttached) continue;
#elif ANDROID
if (!view.Item.IsCached && !view.Item.IsAttached) continue;
if (/*!view.Item.IsCached &&*/ view.IsCached || !view.Item.IsAttached) continue;
#endif

var (x, y) =
Expand Down
8 changes: 4 additions & 4 deletions MPowerKit.VirtualizeListView/LinearItemsLayoutManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ protected override void ArrangeItem(IReadOnlyList<VirtualizeListViewItem> items,
item.Cell.HeightRequest = AutoSize;
}

item.CellBounds = new Rect(margin.Left, bottom + margin.Top, request.Width, request.Height);
item.Bounds = new Rect(0d, bottom, request.Width, request.Height + margin.VerticalThickness);
item.CellBounds = new Rect(margin.Left, bottom + margin.Top, newAvailableSpace.Width, request.Height);
item.Bounds = new Rect(0d, bottom, newAvailableSpace.Width, request.Height + margin.VerticalThickness);
}
else
{
Expand All @@ -89,8 +89,8 @@ protected override void ArrangeItem(IReadOnlyList<VirtualizeListViewItem> items,
item.Cell.WidthRequest = AutoSize;
}

item.CellBounds = new Rect(right + margin.Left, margin.Top, request.Width, request.Height);
item.Bounds = new Rect(right, 0d, request.Width + margin.HorizontalThickness, request.Height);
item.CellBounds = new Rect(right + margin.Left, margin.Top, request.Width, newAvailableSpace.Height);
item.Bounds = new Rect(right, 0d, request.Width + margin.HorizontalThickness, newAvailableSpace.Height);
}
}

Expand Down
23 changes: 19 additions & 4 deletions MPowerKit.VirtualizeListView/MPowerKit.VirtualizeListView.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net8.0-android;net8.0-ios</TargetFrameworks>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.22621.0</TargetFrameworks>

<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
Expand All @@ -10,6 +12,7 @@

<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>

<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>MPowerKit.VirtualizeListView</Title>
Expand All @@ -25,9 +28,21 @@
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>

<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('windows'))">
<DefineConstants>WINDOWS</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="!$(TargetFramework.Contains('android'))">
<Compile Remove="**\**\*.Android.cs" />
<None Include="**\**\*.Android.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />

<Compile Remove="**\**\Android\**\*.cs" />
<None Include="**\**\Android\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<ItemGroup Condition="!$(TargetFramework.Contains('ios')) AND !$(TargetFramework.Contains('maccatalyst'))">
<Compile Remove="**\**\*.MaciOS.cs" />
<None Include="**\**\*.MaciOS.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />

<Compile Remove="**\**\MaciOS\**\*.cs" />
<None Include="**\**\MaciOS\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
Expand Down
16 changes: 16 additions & 0 deletions MPowerKit.VirtualizeListView/MaciOS/VirtualizeListViewHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.Maui.Handlers;

using UIKit;

namespace MPowerKit.VirtualizeListView;

public partial class VirtualizeListViewHandler : ScrollViewHandler
{
public static void MapScrollSpeed(VirtualizeListViewHandler handler, VirtualizeListView virtualizeListView)
{
handler.PlatformView.DecelerationRate =
virtualizeListView.ScrollSpeed is ScrollSpeed.Normal
? UIScrollView.DecelerationRateNormal
: UIScrollView.DecelerationRateFast;
}
}
8 changes: 8 additions & 0 deletions MPowerKit.VirtualizeListView/ScrollSpeed.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace MPowerKit.VirtualizeListView;

public enum ScrollSpeed
{
Normal = 1,
Slow = 2,
Slowest = 5
}
Loading

0 comments on commit 71e235a

Please sign in to comment.