Skip to content

ADFA-3123 | Adaptive navigation patterns#1055

Open
jatezzz wants to merge 3 commits intostagefrom
feat/ADFA-3123-adaptive-navigation-patterns
Open

ADFA-3123 | Adaptive navigation patterns#1055
jatezzz wants to merge 3 commits intostagefrom
feat/ADFA-3123-adaptive-navigation-patterns

Conversation

@jatezzz
Copy link
Collaborator

@jatezzz jatezzz commented Mar 9, 2026

This PR refactors the UI to properly support adaptive navigation patterns across different screen sizes and orientations, specifically addressing the editor's toolbars and the project template list.

Changes include:

  • Editor Toolbars: Replaced imperative view manipulation in BaseEditorActivity with a native FlexboxLayout in content_editor.xml. This automatically handles wrapping the ProjectActionsToolbar below the title_toolbar on smaller screens and places them side-by-side on larger screens (like tablets or in landscape mode), eliminating the need for complex layout calculations in code.
  • Template List: Migrated from a FlexboxLayoutManager with a custom GlobalLayoutListener to a dynamic GridLayoutManager in TemplateListFragment. This natively adjusts the number of columns (between 1 and 4) based on the available screen width, providing a much smoother and more performant reflow when resizing the window (e.g., in DeX mode) or rotating the device.
  • Template Items: Updated layout_template_list_item.xml to use match_parent widths, ensuring the cards properly fill their assigned grid columns without leaving awkward empty spaces.
  • Cleanup: Removed unused diff calculation logic from TemplateListAdapter.

Details

1000097917.mp4

Ticket

ADFA-3123

Observation

The use of GridLayoutManager combined with onConfigurationChanged for the template list provides a significant performance improvement over the previous GlobalLayoutListener approach, especially in desktop-like environments (Samsung DeX) where window resizing triggers frequent layout passes.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Release Notes - Adaptive Navigation Patterns (PR #1055)

Changes

  • Editor Toolbar Refactor: Removed imperative orientation-based toolbar rearrangement in BaseEditorActivity and replaced AppBar layout with a FlexboxLayout (content_editor.xml) so title_toolbar and ProjectActionsToolbar wrap automatically (stack on small screens, side-by-side on larger screens).
  • New ProjectActionsToolbar: Introduced com.itsaky.androidide.ui.ProjectActionsToolbar and adjusted common/project_actions_toolbar.xml to use wrap_content widths for toolbar and its HorizontalScrollView.
  • Template Grid Layout: Replaced FlexboxLayoutManager + GlobalLayoutListener with a GridLayoutManager in TemplateListFragment and added dynamic span recalculation (1–4 columns) based on available width; updateSpanCount is called after adapter setup and onConfigurationChanged.
  • Template Item Layout: layout_template_list_item.xml changed card and inner layout widths from wrap_content to match_parent so items fill grid columns.
  • Adapter Cleanup: Removed DiffUtil-based diff calculation and related filler logic from TemplateListAdapter; simplified long-press tooltip lambda usage.

Performance Improvements

  • GridLayoutManager + onConfigurationChanged significantly reduces reflow overhead and improves responsiveness in desktop-like environments (e.g., Samsung DeX) compared to the previous GlobalLayoutListener/FlexboxLayoutManager approach.

Risks & Best Practice Notes

  • Diffing removed: TemplateListAdapter no longer uses DiffUtil. Incremental updates (item insert/update/remove) are not applied automatically — callers must replace the full list or reintroduce a diffing mechanism to avoid janky updates or full refreshes.
  • Span calculation may be imprecise: The span count computation does not account for container padding/margins or item spacing, which can produce suboptimal column counts or minor overflow on narrow viewports; consider measuring available width minus paddings or using LayoutManager.SpanSizeLookup for mixed spans.
  • Silent failures on layoutManager mismatch: span updates assume a GridLayoutManager; if layoutManager is null or different the cast/update may be skipped silently. Add explicit checks or fallbacks to avoid silent no-ops.
  • Flexbox in AppBar: Embedding a FlexboxLayout with wrap behavior inside AppBarLayout may behave differently across OEMs and older Android versions—verify behavior on low-API and custom-launcher environments.
  • Minor potential bug: TemplateListAdapter contains a changed lambda parameter name in tooltip handling (unused parameter replaced with _ while still referencing the previous value) — review for consistent tooltip/tag usage.

Recommendations

  • Reintroduce DiffUtil or a stable diffing strategy if templates can change after initial load.
  • Compute span counts using measured available width (accounting for paddings/margins) or use a reliable minimum item width in pixels rather than dp-only heuristics.
  • Add null/type checks around layoutManager casts and more defensive handling for UI components touched during configuration changes.

Walkthrough

Removes orientation-based toolbar rearrangement, drops DiffUtil and related logic from the template adapter, replaces Flexbox-based template list with a GridLayoutManager that recalculates span counts on configuration changes, and refactors the editor AppBar to use a FlexboxLayout containing a new ProjectActionsToolbar.

Changes

Cohort / File(s) Summary
Toolbar Configuration Simplification
app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt
Removed syncProjectToolbarRowForOrientation and its calls from onCreate/onConfigurationChanged; removed unused LinearLayout/TextView imports.
Template List Adapter Simplification
app/src/main/java/com/itsaky/androidide/adapters/TemplateListAdapter.kt
Removed DiffUtil-based diffing and fillDiff logic; adjusted long-press tooltip lambda parameter naming.
Template List Layout Restructuring
app/src/main/java/com/itsaky/androidide/fragments/TemplateListFragment.kt
Replaced Flexbox layout with GridLayoutManager (initial span=1); added onConfigurationChanged override and updateSpanCount() to recompute spanCount based on orientation/item count; removed global layout listener and Flexbox utilities.
Editor AppBar UI Change
app/src/main/res/layout/content_editor.xml
Replaced standalone toolbar with a FlexboxLayout containing the title toolbar and a new ProjectActionsToolbar; adjusted sizing, margins, and wrapping behavior.
Project Actions Toolbar Width Adjustment
common/src/main/res/layout/project_actions_toolbar.xml
Changed layout_width from match_parent to wrap_content on MaterialToolbar and its HorizontalScrollView.
Template Item Width
app/src/main/res/layout/layout_template_list_item.xml
Changed MaterialCardView and inner LinearLayout width from wrap_content to match_parent for full-width items.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • itsaky-adfa
  • jomen-adfa
  • hal-eisen-adfa

Poem

🐰 I hopped through layouts, trimmed a twisty rule,
I nudged the grid to make the list feel cool.
Toolbars now bask without turning round,
Fewer hops, lighter paws upon this ground. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'ADFA-3123 | Adaptive navigation patterns' directly captures the main objective of refactoring UI for adaptive layout support across screen sizes and orientations.
Description check ✅ Passed The PR description thoroughly explains all major changes including editor toolbars, template list migration, template items, and cleanup—all of which are present in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/ADFA-3123-adaptive-navigation-patterns

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/com/itsaky/androidide/fragments/TemplateListFragment.kt`:
- Around line 79-84: The tooltip is being anchored to binding.root inside the
setOnLongClickListener attached to binding.exitButton, which can position it far
from the pressed control; update the call to
TooltipManager.showIdeCategoryTooltip (inside the
binding.exitButton.setOnLongClickListener block) to use the exit button as the
anchor (e.g., anchorView = binding.exitButton or the listener's view parameter)
while keeping context=requireContext() and tag=EXIT_TO_MAIN so the tooltip
appears next to the long-pressed button.
- Around line 68-73: The span calculation currently uses
resources.configuration.screenWidthDp; change to compute span count from the
actual RecyclerView width by adding a helper method (e.g.,
updateSpanCount(minItemWidthDp: Int)) in TemplateListFragment that measures
binding.list.width (after layout) and sets gridLayoutManager.spanCount
accordingly, call this helper from binding.list.doOnLayout for initial setup and
from onConfigurationChanged() to recompute on rotations/size changes; ensure you
keep the GridLayoutManager instance (gridLayoutManager) and update its spanCount
rather than recreating the adapter or list.

In `@app/src/main/res/layout/content_editor.xml`:
- Around line 65-74: The ProjectActionsToolbar is declared wrap_content but
inflates project_actions_toolbar.xml whose root MaterialToolbar uses
android:layout_width="match_parent", causing measurement ambiguity; open
project_actions_toolbar.xml and change the root MaterialToolbar's
android:layout_width to "wrap_content" (and likewise change any immediate child
views that use match_parent to wrap_content or use wrap_content with appropriate
paddings) so the custom view ProjectActionsToolbar can size itself correctly
within the FlexboxLayout.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5c2c5a9c-d4dd-4eef-8f67-57efbc14f805

📥 Commits

Reviewing files that changed from the base of the PR and between 5a56a46 and b66cbf0.

📒 Files selected for processing (5)
  • app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt
  • app/src/main/java/com/itsaky/androidide/adapters/TemplateListAdapter.kt
  • app/src/main/java/com/itsaky/androidide/fragments/TemplateListFragment.kt
  • app/src/main/res/layout/content_editor.xml
  • app/src/main/res/layout/layout_template_list_item.xml
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt

@dara-abijo-adfa dara-abijo-adfa requested a review from a team March 10, 2026 10:30
jatezzz added 2 commits March 10, 2026 08:46
Change toolbar to wrap_content and cap grid columns by orientation and item count.
@jatezzz jatezzz force-pushed the feat/ADFA-3123-adaptive-navigation-patterns branch from b66cbf0 to 290fe77 Compare March 10, 2026 13:48
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/src/main/java/com/itsaky/androidide/fragments/TemplateListFragment.kt (1)

99-111: Consider using actual RecyclerView width for span calculation.

The current approach uses orientation and item count, but doesn't account for the actual available width of binding.list. This can cause issues in constrained layouts (split-screen, foldables, embedded containers) where the RecyclerView may be narrower than expected.

Using binding.list.width after layout would provide more accurate span counts across all scenarios.

Suggested approach using actual width
+import androidx.core.view.doOnLayout
 ...
+	private val minItemWidthDp = 160
+
 	override fun onConfigurationChanged(newConfig: Configuration) {
 		super.onConfigurationChanged(newConfig)
-
-		updateSpanCount()
+		_binding?.list?.post { updateSpanCount() }
 	}
 
 	private fun updateSpanCount() {
-		val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
-		val maxSpans = if (isLandscape) 6 else 4
-
+		val listWidthPx = binding.list.width
+		if (listWidthPx <= 0) return
+		
+		val minItemWidthPx = (minItemWidthDp * resources.displayMetrics.density).toInt()
 		val itemCount = binding.list.adapter?.itemCount ?: 0
-
-		val optimalSpans = maxOf(1, minOf(maxSpans, itemCount))
-
+		val widthBasedSpans = (listWidthPx / minItemWidthPx).coerceIn(1, 6)
+		val optimalSpans = minOf(widthBasedSpans, maxOf(1, itemCount))
+		
 		val layoutManager = binding.list.layoutManager as? GridLayoutManager
 		if (layoutManager != null && layoutManager.spanCount != optimalSpans) {
 			layoutManager.spanCount = optimalSpans
 		}
 	}

Also update the initial setup to use doOnLayout:

binding.list.layoutManager = gridLayoutManager
binding.list.doOnLayout { updateSpanCount() }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/itsaky/androidide/fragments/TemplateListFragment.kt`
around lines 99 - 111, The updateSpanCount currently bases spans on orientation
and item count only; change it to measure the actual available width of
binding.list (use binding.list.width after layout) and compute optimalSpans from
availableWidth divided by a target minimum column width (e.g.,
desiredItemMinWidth), clamped between 1 and maxSpans; update the
GridLayoutManager.spanCount accordingly in updateSpanCount; also ensure
updateSpanCount is invoked after layout by calling binding.list.doOnLayout {
updateSpanCount() } (and/or attach an OnLayoutChangeListener) where the layout
manager is set so width measurement is valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/com/itsaky/androidide/fragments/TemplateListFragment.kt`:
- Around line 99-111: The updateSpanCount currently bases spans on orientation
and item count only; change it to measure the actual available width of
binding.list (use binding.list.width after layout) and compute optimalSpans from
availableWidth divided by a target minimum column width (e.g.,
desiredItemMinWidth), clamped between 1 and maxSpans; update the
GridLayoutManager.spanCount accordingly in updateSpanCount; also ensure
updateSpanCount is invoked after layout by calling binding.list.doOnLayout {
updateSpanCount() } (and/or attach an OnLayoutChangeListener) where the layout
manager is set so width measurement is valid.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 46fe4dd9-d078-4c5b-9a0b-dd6e86b9cacd

📥 Commits

Reviewing files that changed from the base of the PR and between b66cbf0 and 290fe77.

📒 Files selected for processing (6)
  • app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt
  • app/src/main/java/com/itsaky/androidide/adapters/TemplateListAdapter.kt
  • app/src/main/java/com/itsaky/androidide/fragments/TemplateListFragment.kt
  • app/src/main/res/layout/content_editor.xml
  • app/src/main/res/layout/layout_template_list_item.xml
  • common/src/main/res/layout/project_actions_toolbar.xml
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/res/layout/layout_template_list_item.xml

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants