📄 src/Views/EdgeToEdgeHelper.cs
using Android.Views;
using AndroidX.Core.View;

namespace NotesApp.Views;

// Under Android 15+'s forced edge-to-edge, content draws behind the status/nav bars unless
// something applies their insets as padding. android:fitsSystemWindows only works for
// Material's AppBarLayout, which this app doesn't use (no collapsing/scroll behavior needed),
// so each screen's root view gets this explicit ViewCompat listener instead - padding all four
// edges on top of whatever padding was already authored in the layout XML.
public static class EdgeToEdgeHelper
{
    public static void Apply(View root)
    {
        var baseLeft = root.PaddingLeft;
        var baseTop = root.PaddingTop;
        var baseRight = root.PaddingRight;
        var baseBottom = root.PaddingBottom;

        ViewCompat.SetOnApplyWindowInsetsListener(
            root,
            new Listener(baseLeft, baseTop, baseRight, baseBottom)
        );
    }

    // Bottom padding also accounts for the IME (on-screen keyboard), taking whichever of the
    // nav bar or the keyboard is taller rather than summing them - the keyboard, when visible,
    // already covers the nav bar's region, so adding both would double that overlap. Padding
    // the root (rather than e.g. a text field directly) means a weighted child in a vertical
    // layout - like NoteViewActivity's EditText - genuinely shrinks via normal layout, instead
    // of the child having to reconcile its own padding against its internal text/scroll state.
    // A view with no keyboard ever focused inside it just sees Ime().Bottom stay 0 always.
    private class Listener(int baseLeft, int baseTop, int baseRight, int baseBottom)
        : Java.Lang.Object,
            IOnApplyWindowInsetsListener
    {
        public WindowInsetsCompat? OnApplyWindowInsets(View? v, WindowInsetsCompat? insets)
        {
            if (v is null || insets is null)
                return insets;

            var bars = insets.GetInsets(WindowInsetsCompat.Type.SystemBars())!;
            var ime = insets.GetInsets(WindowInsetsCompat.Type.Ime())!;
            v.SetPadding(
                baseLeft + bars.Left,
                baseTop + bars.Top,
                baseRight + bars.Right,
                baseBottom + Math.Max(bars.Bottom, ime.Bottom)
            );
            return insets;
        }
    }
}