-
Notifications
You must be signed in to change notification settings - Fork 106
[MBL-18831] Implement edge-to-edge rendering with landscape support #3346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- Enable edge-to-edge in NavigationActivity with EdgeToEdgeHelper - Apply window insets to bottom navigation bar to handle navigation bar overlap - Apply window insets to DashboardFragment toolbar for status bar spacing - Update toolbar layout to wrap_content with minHeight to accommodate status bar padding - Create WindowInsetsHelper utility to replace deprecated SYSTEM_UI_FLAG APIs - Create EdgeToEdgeHelper utility for consistent edge-to-edge enablement - Update theme to use transparent system bars for edge-to-edge rendering 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Enable edge-to-edge in NavigationActivity with opaque status bar - Add extension functions in WindowInsetsHelper for common inset patterns: - applyTopSystemBarInsets() - applyBottomSystemBarInsets() - applyHorizontalSystemBarInsets() - applySystemBarInsets() with flexible parameters - doOnApplyWindowInsets() for custom handling - Update DashboardFragment to handle toolbar top insets - Update CourseBrowserFragment for collapsing toolbar edge-to-edge support - Apply bottom insets to navigation bar and divider - Change toolbar layouts to wrap_content with minHeight for dynamic sizing - Set status bar to opaque (darkStatusBarColor) and navigation bar to transparent 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Create CanvasScaffold with built-in edge-to-edge support - Automatically handles navigation bar insets via contentWindowInsets - Drop-in replacement for Material Scaffold - Update CanvasAppBar and CanvasThemedAppBar with status bar insets - TopAppBar now includes windowInsets = WindowInsets.statusBars - Automatically pushes toolbar content below status bar - Create WindowInsetsModifiers.kt with reusable modifier extensions - systemBarsPadding() for both status and navigation bar padding - statusBarsPadding() for status bar only - Update CalendarScreen to use CanvasScaffold - Update AssignmentListScreen to use CanvasScaffold All Compose screens can now adopt edge-to-edge by simply using CanvasScaffold instead of Scaffold, with proper inset handling automatically applied. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add ViewCompat.requestApplyInsets() to WindowInsetsHelper for proper inset dispatch timing - Apply top status bar insets to all XML fragment toolbars - Apply bottom navigation bar insets to scrollable content (RecyclerViews, ScrollViews, WebViews, ViewPagers) - Update CanvasScaffold to automatically wrap content with navigation bar insets for all Compose screens - Change XML toolbar heights from fixed actionBarSize to wrap_content with minHeight - Add missing view IDs and imports Implements MBL-18831 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Apply top status bar insets to toolbars in XML fragments - Apply bottom navigation bar insets to scrollable content (SwipeRefreshLayout, ScrollView) - Update XML toolbar heights from fixed actionBarSize to wrap_content with minHeight - Updated fragments: - EditDashboardFragment - InboxFragment (both toolbar and editToolbar) - EmailNotificationPreferencesFragment - PushNotificationPreferencesFragment - OfflineContentFragment - SyncSettingsFragment - HomeroomFragment Implements MBL-18831 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…e screens - Remove bottom insets from DashboardFragment (has bottom navigation bar) - Update pandautils Compose screens to use CanvasScaffold: - GradesScreen - SettingsScreen - SmartSearchScreen - SmartSearchPreferencesScreen - Add missing import for HomeroomFragment Fixes double padding issue on screens with bottom navigation bars. CanvasScaffold automatically handles navigation bar insets for all Compose screens. Implements MBL-18831 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Implement comprehensive edge-to-edge rendering across Teacher, Parent, Student apps and shared libraries, fixing all layout overlaps and inset handling issues. **Teacher App:** - Fix StudentContextFragment and FileListFragment crashes (LayoutParams type mismatch - RelativeLayout vs CoordinatorLayout) - Add edge-to-edge for 40+ fragments including CourseSettings, QuizList, DiscussionsList, FileSearch, PostPolicy, CommentLibrary, Profile, SpeedGrader fragments, and more - Fix FAB insets across all fragments with correct LayoutParams types - Update 50+ XML layouts with proper toolbar height handling (wrap_content + minHeight pattern) **Parent App:** - Fix DashboardFragment toolbar insets - Add FAB insets to CourseDetailsScreen and ManageStudentsScreen (Compose) - Fix edge-to-edge for QrPairing, AnnouncementDetails, Alerts, AlertSettings, Courses, and CreateAccount screens **Student App:** - Update night mode styles for edge-to-edge compatibility **Shared Libraries:** *pandautils:* - Add edge-to-edge for DiscussionDetailsWebViewFragment, LtiLaunchFragment, AssignmentDetailsFragment - Fix InboxFragment FAB insets with programmatic CoordinatorLayout handling - Fix InboxDetailsScreen Compose toolbar overlap with status bar insets - Fix TriStateBottomSheet navigation bar overlap in SpeedGrader - Remove unnecessary Scaffold padding in SpeedGraderContentScreen - Update theme values for edge-to-edge compatibility *login-api-2:* - Add edge-to-edge for all login activities (FindSchool, LandingPage, SignIn, LoginWithQR, AcceptableUsePolicy) - Update login activity layouts with proper toolbar height handling - Update theme styles for edge-to-edge Key patterns implemented: - Toolbars: applyTopSystemBarInsets() + wrap_content + minHeight - Scrollable content: applyBottomSystemBarInsets() - FABs: Manual insets with correct LayoutParams type matching parent container - Compose: windowInsetsPadding() + contentWindowInsets = WindowInsets(0,0,0,0) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…ixes
This commit completes the edge-to-edge rendering implementation across
all apps (Teacher, Student, Parent) and shared libraries by addressing
HIGH and MEDIUM priority issues identified in comprehensive expert review.
## Expert Review Results
Implementation assessed at ~90% complete with solid architecture and patterns.
All critical functionality now properly supports edge-to-edge rendering with
landscape support and keyboard handling.
## Changes Made
### HIGH Priority Fixes (Expert Review)
1. **Fixed CanvasScaffold to Support Text Input Screens**
- Added contentWindowInsets parameter with default WindowInsets.navigationBars
- Allows screens to specify IME union for text input or zero insets as needed
- Added comprehensive KDoc with usage examples
- Location: libs/pandautils/src/main/java/com/instructure/pandautils/compose/composables/CanvasScaffold.kt
2. **Fixed Missing IME Insets Request in SpeedGraderCommentsFragment**
- Added ViewCompat.requestApplyInsets() for commentInputContainer
- Ensures IME insets apply immediately when view is attached
- Prevents keyboard appearing before insets are applied
- Location: apps/teacher/src/main/java/com/instructure/teacher/fragments/SpeedGraderCommentsFragment.kt:186-188
3. **Completed Parent App Fragment Coverage**
- Updated SimpleWebViewFragment with toolbar and horizontal insets
- Added applyTopSystemBarInsets() to toolbar in applyTheme()
- Added applyHorizontalSystemBarInsets() to root view in onViewCreated()
- Location: apps/parent/src/main/java/com/instructure/parentapp/features/webview/SimpleWebViewFragment.kt
### MEDIUM Priority Fixes
4. **Fixed Missing Toolbar Insets in AttendanceListFragment**
- Added toolbar.applyTopSystemBarInsets() in setupViews()
- Ensures status bar doesn't overlap toolbar
- Location: apps/teacher/src/main/java/com/instructure/teacher/fragments/AttendanceListFragment.kt:117
5. **Updated 5 Compose Screens with Text Input for IME Support**
- Added WindowInsets.ime.union(WindowInsets.navigationBars) to:
* InboxComposeScreen.kt (subject + body fields)
* RecipientPickerScreen.kt (search field)
* InboxSignatureScreen.kt (signature field)
* CreateUpdateToDoScreen.kt (title/description fields)
* CreateUpdateEventScreen.kt (title/location fields)
- Prevents keyboard from obscuring text input fields
- All locations: libs/pandautils/src/main/java/com/instructure/pandautils/features/*/composables/
6. **Updated 11 Compose Screens with Zero Content Insets**
- Added WindowInsets(0, 0, 0, 0) to read-only/list screens:
* CourseSelectorActivity.kt
* SubmissionListScreen.kt
* SelectContextScreen.kt
* GradePreferencesScreen.kt
* AssignmentListFilterScreen.kt
* CalendarFilterScreen.kt
* ProgressScreen.kt
* ToDoScreen.kt
* EventScreen.kt
* CustomFrequencyScreen.kt
* SpeedGraderCommentLibraryScreen.kt
- Ensures proper edge-to-edge rendering without IME interference
## Architecture Summary
**Hybrid Insets Approach:**
- Horizontal insets → Fragment root views (landscape support)
- Vertical insets → Individual scrollable views
- IME insets → Text input containers (keyboard avoidance)
- Compose contentWindowInsets → Properly configured per screen type
**Patterns Established:**
- View-based fragments: applyHorizontalSystemBarInsets() on root
- Toolbars: applyTopSystemBarInsets() before other setup
- Scrollable content: applyBottomSystemBarInsets() or custom IME handling
- Compose screens: Explicit contentWindowInsets configuration
- FABs: windowInsetsPadding() with systemBars horizontal + bottom
## Files Modified Summary
- 1 Helper class (CanvasScaffold.kt) - Enhanced with parameter
- 3 View-based fragments - Fixed missing insets
- 16 Compose screens - Added contentWindowInsets configuration
- Total: 20 files modified
## Build Verification
✅ Teacher app builds successfully (devDebug)
✅ Student app builds successfully (devDebug)
✅ Parent app builds successfully (devDebug)
## Testing Checklist
Verified:
- [x] All apps compile without errors
- [x] CanvasScaffold parameter properly passed through
- [x] IME insets request added where needed
- [x] Parent app View-based fragments covered
Manual testing recommended:
- [ ] Text input screens - keyboard doesn't obscure inputs
- [ ] Landscape mode - horizontal insets working
- [ ] All bottom navigation screens - content not clipped
- [ ] Dialogs and bottom sheets - proper insets handling
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Resolved conflict in SmartSearchPreferencesScreen.kt by keeping CanvasScaffold (from our edge-to-edge branch) instead of plain Scaffold (from master), while preserving the onCancel callback fix from master.
📊 Code Coverage Report✅ Student
|
libs/pandautils/src/main/java/com/instructure/pandautils/compose/WindowInsetsModifiers.kt
Outdated
Show resolved
Hide resolved
kdeakinstructure
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QA Findings in Slack thread
adamNagy56
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also sent my QA Findings in Slack thread.
tamaskozmer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just have some really minor suggestions, but haven't tested the build.
...nt/src/main/java/com/instructure/student/AnnotationComments/AnnotationCommentListFragment.kt
Outdated
Show resolved
Hide resolved
...in/java/com/instructure/teacher/PSPDFKit/AnnotationComments/AnnotationCommentListFragment.kt
Outdated
Show resolved
Hide resolved
Addresses the most critical issues identified in QA testing: **Teacher App:** - Fix bottom navigation menu not displayed in portrait mode (CRITICAL) - Changed from padding to margin on BottomNavigationView - Ensures entire bottom bar sits above system navigation bar **Calendar (All Apps):** - Fix FAB positioning (was too high with bottom bar margin) - Set contentWindowInsets to zero in CalendarScreen - Prevents double-spacing since Activity handles insets **Student App:** - Fix Syllabus toolbar overlap with status bar - Added minHeight and top padding for status bar insets - Added proper imports instead of fully qualified names - Fix Syllabus summary RecyclerView content overlap - Added clipToPadding and bottom insets handling - Content scrolls behind nav bar but last item stops above it - Fix Course Browser RecyclerView with clipToPadding 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Applied horizontal (left/right) system bar insets to fragment containers in main activities and login activities to prevent content overlap with navigation bars in landscape mode. Changes: - Student app: Applied horizontal insets to fullscreen (fragment container) - Teacher app: Applied horizontal insets to container (fragment container) - Parent app: Applied horizontal insets to root (navigation host container) - Removed view.applyHorizontalSystemBarInsets() from 52 fragment files - Login activities: Added horizontal insets to BaseLoginFindSchoolActivity and BaseLoginSignInActivity - Fixed toolbar minHeight to use ?android:attr/actionBarSize in all login layouts - Added clipToPadding="false" to RecyclerViews in login layouts This ensures: - Content extends behind status bar in portrait (edge-to-edge) - Horizontal insets prevent landscape navigation bar overlap - Bottom bars use margin to sit above system navigation bar - Individual views handle their own bottom insets as needed - Toolbars maintain proper minimum height in all orientations Addresses QA findings for landscape mode content overlap issues. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Disable fragment retention for Hilt-annotated SyllabusRepositoryFragment. Hilt fragments cannot be retained (retainInstance = true) as it causes 'onAttach called multiple times with different Context' errors. The parent MobiusFragment class sets retainInstance = true by default, so we explicitly override it to false in onCreate(), matching the pattern used in Student app's SyllabusRepositoryFragment. Fixes crash: java.lang.IllegalStateException: onAttach called multiple times with different Context! Hilt Fragments should not be retained.
This commit fixes several edge-to-edge issues related to bottom buttons and navigation bars: 1. Added applyBottomSystemBarMargin() function to apply bottom margin instead of padding for buttons that need exact height dimensions. 2. Fixed Student app dashboard - changed bottom navigation bar from using bottom margin to bottom padding, allowing it to extend into the gesture navigation area while keeping content properly positioned. 3. Fixed assignment details screens - changed from applying margin to SwipeRefreshLayout to applying it directly to submit buttons. This ensures buttons maintain their exact height (56dp) with proper spacing. 4. Fixed offline content screen sync button - applied bottom margin instead of padding to maintain exact button height. Pattern established: - Bottom navigation/tab bars: Use bottom padding (extends into system bar) - Bottom action buttons: Use bottom margin (maintains exact size) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Fixed multiple issues with floating action buttons and bottom navigation: 1. **Bottom navigation blank space** - Removed bottomBarDivider inset listener in NavigationActivity. The divider no longer needs bottom margin since the bottom bar itself now has bottom padding. 2. **FAB margin preservation** - Updated applyBottomSystemBarMargin() to preserve original bottom margins from XML layouts. The function now captures the original margin and adds system bar insets on top, ensuring FABs maintain their intended spacing (e.g., 16dp + nav bar). 3. **Applied FAB fixes** to: - FileListFragment: addFab for creating files/folders - PeopleDetailsFragment: compose FAB for messaging This ensures proper touch targets and spacing above gesture navigation in edge-to-edge mode. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Applied bottom system bar insets to PlayerView to ensure video controls (play/pause, seek bar, etc.) are positioned above the navigation bar. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Applied bottom system bar margin to the message FAB in assignment details to ensure proper spacing above the navigation bar while preserving the original 16dp margin - Fixed simple webview toolbar overlap with status bar 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
kdeakinstructure
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QA findings in Slack thread.
adamNagy56
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also sent my QA Findings in Slack thread.
… cutout insets Apply both navigation bar and display cutout insets to prevent content from being hidden behind system UI elements. In landscape mode with devices that have a hole punch camera, the keyboard was showing gaps on both sides because: - Navigation bar exists on one side - Display cutout (camera) exists on the other side or top The fix uses maxOf() to apply the larger value between navigation bar and display cutout insets, ensuring proper padding on both sides. Updated activities: - NavigationActivity (Student app) - InitActivity (Teacher app) - MainActivity (Parent app) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Resolved conflicts: - DashboardFragment.kt: Combined edge-to-edge import changes with new drag handling code - ToDoListScreen.kt: Added missing Snackbar-related imports from master 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
adamNagy56
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QA findings in Slack thread.
kdeakinstructure
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See QA findings in Slack thread.
- Remove unnecessary bottom inset from OldToDoListFragment - Apply conditional bottom insets to InboxFragment based on app type (Parent vs Teacher/Student) - Add top system bar insets to CreateDiscussionWebViewFragment toolbar - Update CreateDiscussionWebViewFragment layout to use minHeight for toolbar - Fix SmartSearchScreen dimming issue by clearing window dim flags from previous screen - Add horizontal insets support to CreateDiscussionWebViewFragment 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Summary
Implements comprehensive edge-to-edge rendering across all Canvas Android apps (Teacher, Student, Parent) and shared libraries, with full landscape mode support and keyboard handling.
Changes
Architecture
contentWindowInsetsconfigurationWindowInsetsHelper.ktwith extension functions for consistent insets applicationImplementation Details
View-Based Fragments (83 files)
applyHorizontalSystemBarInsets()to root views for landscape supportapplyTopSystemBarInsets()to toolbars for status bar handlingapplyBottomSystemBarInsets()to scrollable contentmaxOf(ime.bottom, systemBars.bottom)Compose Screens (32 files)
WindowInsets.ime.union(WindowInsets.navigationBars)WindowInsets(0, 0, 0, 0)windowInsetsPadding(WindowInsets.systemBars.only(...))CanvasScaffoldwith flexiblecontentWindowInsetsparameterTheme Configuration
windowOptOutEdgeToEdgeEnforcementfrom all app themesEdgeToEdgeHelper.enableEdgeToEdge()in onCreateFiles Modified
Test plan:
Manual testing performed:
Testing recommended:
refs: MBL-18831
affects: Teacher, Student, Parent
release note: Implemented edge-to-edge rendering with full landscape support for Android 15+ requirements
Checklist