diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs index 97c71eca0f15..215e624d498f 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs @@ -200,8 +200,8 @@ protected virtual void UpdateFlyoutContent() void DisconnectRecyclerView() { if (_flyoutContentView.IsAlive() && - _flyoutContentView is RecyclerViewContainer rvc && - rvc.GetAdapter() is ShellFlyoutRecyclerAdapter sfra) + _flyoutContentView is ShellRecyclerView srv && + srv.GetAdapter() is ShellFlyoutRecyclerAdapter sfra) { sfra.Disconnect(); } @@ -219,29 +219,17 @@ AView CreateFlyoutContent(ViewGroup rootView) DisconnectRecyclerView(); + var context = ShellContext.AndroidContext; var content = ((IShellController)ShellContext.Shell).FlyoutContent; if (content == null) { - var lp = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MatchParent, CoordinatorLayout.LayoutParams.MatchParent); - lp.Behavior = new AppBarLayout.ScrollingViewBehavior(); - var context = ShellContext.AndroidContext; - var recyclerView = new RecyclerViewContainer(context) - { - LayoutParameters = lp - }; - - recyclerView.SetAdapter(new ShellFlyoutRecyclerAdapter(ShellContext, OnElementSelected)); - + var adapter = new ShellFlyoutRecyclerAdapter(ShellContext, OnElementSelected); + var recyclerView = new ShellRecyclerView(context, adapter); return recyclerView; } - _contentView = new ShellViewRenderer(ShellContext.AndroidContext, content, MauiContext); - - _contentView.PlatformView.LayoutParameters = new CoordinatorLayout.LayoutParams(LP.MatchParent, LP.MatchParent) - { - Behavior = new AppBarLayout.ScrollingViewBehavior() - }; - + _contentView = new ShellViewRenderer(context, content, MauiContext); + ShellRecyclerView.SetLayoutParameters(_contentView.PlatformView, scrollingEnabled: true); return _contentView.PlatformView; } @@ -470,9 +458,9 @@ void OnFlyoutViewLayoutChanging() void UpdateVerticalScrollMode() { - if (_flyoutContentView is RecyclerView rv && rv.GetLayoutManager() is ScrollLayoutManager lm) + if (_flyoutContentView is ShellRecyclerView rv) { - lm.ScrollVertically = _shellContext.Shell.FlyoutVerticalScrollMode; + ShellRecyclerView.SetLayoutParameters(rv, _shellContext.Shell.FlyoutVerticalScrollMode != ScrollMode.Disabled); } } @@ -796,66 +784,4 @@ void UpdateMinimumHeight() } } } - - class RecyclerViewContainer : RecyclerView - { - bool _disposed; - ScrollLayoutManager _layoutManager; - - public RecyclerViewContainer(Context context) : base(context) - { - SetClipToPadding(false); - SetLayoutManager(_layoutManager = new ScrollLayoutManager(context, (int)Orientation.Vertical, false)); - SetLayoutManager(new LinearLayoutManager(context, (int)Orientation.Vertical, false)); - } - - protected override void Dispose(bool disposing) - { - if (_disposed) - return; - - _disposed = true; - if (disposing) - { - SetLayoutManager(null); - var adapter = this.GetAdapter(); - SetAdapter(null); - adapter?.Dispose(); - _layoutManager?.Dispose(); - _layoutManager = null; - } - - base.Dispose(disposing); - } - } - - internal class ScrollLayoutManager : LinearLayoutManager - { - public ScrollMode ScrollVertically { get; set; } = ScrollMode.Auto; - - public ScrollLayoutManager(Context context, int orientation, bool reverseLayout) : base(context, orientation, reverseLayout) - { - } - - int GetVisibleChildCount() - { - var firstVisibleIndex = FindFirstCompletelyVisibleItemPosition(); - var lastVisibleIndex = FindLastCompletelyVisibleItemPosition(); - return lastVisibleIndex - firstVisibleIndex + 1; - } - - public override bool CanScrollVertically() - { - switch (ScrollVertically) - { - case ScrollMode.Disabled: - return false; - case ScrollMode.Enabled: - return true; - default: - case ScrollMode.Auto: - return ChildCount > GetVisibleChildCount(); - } - } - } } diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs index bd743ea0f6a2..fe4c102bcefa 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.Android.cs @@ -503,21 +503,21 @@ ShellFlyoutRenderer GetDrawerLayout(ShellRenderer shellRenderer) return (ShellFlyoutRenderer)shellContext.CurrentDrawerLayout; } - RecyclerView GetFlyoutMenuReyclerView(ShellRenderer shellRenderer) + ShellRecyclerView GetFlyoutMenuReyclerView(ShellRenderer shellRenderer) { IShellContext shellContext = shellRenderer; DrawerLayout dl = shellContext.CurrentDrawerLayout; var flyout = dl.GetChildAt(0); - RecyclerView flyoutContainer = null; + ShellRecyclerView flyoutContainer = null; var ViewGroup = dl.GetChildAt(1) as ViewGroup; var rc = ViewGroup.GetChildAt(0) as RecyclerView; if (dl.GetChildAt(1) is ViewGroup vg1 && - vg1.GetChildAt(0) is RecyclerView rvc) + vg1.GetChildAt(0) is ShellRecyclerView rv) { - flyoutContainer = rvc; + flyoutContainer = rv; } return flyoutContainer ?? throw new Exception("RecyclerView not found"); diff --git a/src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/ShellRecyclerView.java b/src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/ShellRecyclerView.java new file mode 100644 index 000000000000..71b2243d775f --- /dev/null +++ b/src/Core/AndroidNative/maui/src/main/java/com/microsoft/maui/ShellRecyclerView.java @@ -0,0 +1,40 @@ +package com.microsoft.maui; + +import android.content.Context; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.appbar.AppBarLayout; + +/** + * Used by Shell flyout menu + */ +public class ShellRecyclerView extends RecyclerView { + public ShellRecyclerView(@NonNull Context context, Adapter adapter) + { + super(context); + + setClipToPadding(false); + setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false)); + setLayoutParameters(this, true); + setAdapter(adapter); + } + + /** + * Configures a default, scrollable CoordinatorLayout.LayoutParams that matches its parent + * @param view + * @param scrollingEnabled + */ + public static void setLayoutParameters(View view, boolean scrollingEnabled) + { + CoordinatorLayout.LayoutParams layoutParams = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.MATCH_PARENT); + if (scrollingEnabled) { + layoutParams.setBehavior(new AppBarLayout.ScrollingViewBehavior()); + } + view.setLayoutParams(layoutParams); + } +} diff --git a/src/Core/src/maui.aar b/src/Core/src/maui.aar index 5512a9648083..0f6411757bda 100644 Binary files a/src/Core/src/maui.aar and b/src/Core/src/maui.aar differ