Skip to content

feat(deck-picker): edge to edge support#20964

Open
david-allison wants to merge 3 commits intoankidroid:mainfrom
david-allison:edge-2-edge
Open

feat(deck-picker): edge to edge support#20964
david-allison wants to merge 3 commits intoankidroid:mainfrom
david-allison:edge-2-edge

Conversation

@david-allison
Copy link
Copy Markdown
Member

@david-allison david-allison commented May 7, 2026

Note

Assisted-by: Claude Opus 4.7 - lots of discussion, wasn't too helpful here

Purpose / Description

This PR enables edge to edge support for the Deck Picker. The DeckPicker currently uses an opaque toolbar, so we only need to focus on edge-to-edge for the bottom bar & side panels (for example: if there's a camera cutout on a tablet).

Fixes

Approach

This was difficult and there was a lot of trial and error.

Deck List & "Studied X cards in Y seconds"

The deck list needs to be at the bottom of the screen.

- android:layout_above="@id/review_summary_text_view"

Due to this, the deck list appears under the review summary. Before this change, the review_summary background was effectively opaque, and now needs to handle overlap with the deck name, without obscuring the content.

Furthermore, some Android versions have a 'transparent nav', which applied a transparency filter to elements underneath it. Different Android versions did this differently, and the colors were non-public(with API <= 25 not supporting dark navigation buttons), so I rolled my own (BottomFadeFrameLayout): using a DST_OUT filter.

FAB

val fabBottomOffset = if (isRobolectric) 12.dp.toPx(this) else -12.dp.toPx(this)
floatingActionButtonBinding.root.updatePadding(bottom = bars.bottom + fabBottomOffset)

The floating action bar is surprisingly complex: it uses a ScrollView to handle smaller screens, and this means we need a margin for the shadow to display properly, rather than removing its clipping behavior.

I extracted some of the bottom padding to try and remove 'fabBottomOffset', but due to the shadow requirements, this did not seem feasible.

isRobolectric: due to an undetermined bug, the FAB was ~24dp too low on the screenshot after edge to edge was implemented. This fixes it manually

How Has This Been Tested?

tools/compare-screenshot-test.sh 8f35410 "com.ichi2.anki.Deck**ScreenshotTest" image image
  • Google Pixel 9 Pro
  • AOSP API 24 emulator [phone]
  • Pixel 6 Pro API 33 emulator
  • API 34 Tablet Emulator
  • Pixel 10 Pro API 37 Emulator
  • API 29 Medium Phone
  • API 27 Medium Phone
Details Screenshot 2026-05-07 at 01 31 49 Screenshot 2026-05-07 at 01 32 09 Screenshot 2026-05-07 at 01 32 31 Screenshot 2026-05-07 at 01 34 03 Screenshot 2026-05-07 at 01 50 02

Overlap with selected deck - same style as the standard Android bottom nav

Screenshot 2026-05-07 at 01 38 27

Learning (optional, can help others)

https://developer.android.com/develop/ui/views/layout/edge-to-edge

Checklist

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

For activities with 'Theme_Dark.Launcher', android:windowBackground is
set, but was never removed.

On views with transparent backgrounds (such as the Card Browser column
headers), this leaked through when edge to edge was enabled

Part of issue 17334 - Edge to Edge

Assisted-by: Claude Opus 4.7 - diagnostics + fix
Prep for edge-to-edge work.

Scrolling tests were attempted, but Roborazzi did not scroll the
RecyclerView correctly

Issue 17334

Assisted-by: Claude Opus 4.7 - much of the initial implementation
In order to support edge to edge, we needed to move the RecyclerView
underneath the nav + "Studied X in Y" TextView.

The bottom nav on many Android phones will fade the content underneath
it, but different phones have different implementations, using private
colors. So we define our own 'BottomFadeFrameLayout' to handle this.

Roughly equivalent to the fade on an API 33 emulator

----

The screenshot test did not place the FAB in the correct place
vertically. Therefore adjustmnets were made behind an isRobolectric
wrapper

The last row of the RecyclerView is moved by a few pixels to be directly
 in-line with the top of the FAB

The padding cannot be lower, otherwise the FAB would obscure the
counts

I attempted to make tests in Roborazzi which scrolled to the bottom of
the list, but they were flaky (1px of padding made a huge difference in
scroll position)

Issue 17334
@david-allison david-allison added this to the 2.25 release milestone May 7, 2026
Comment on lines +105 to +108
SystemBarStyle.auto(
lightScrim = Color.TRANSPARENT,
darkScrim = Color.TRANSPARENT,
)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have { Themes.isNightTheme } to handle a user selecting a theme manually

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant