From 383530427e6053191318af7e9befba9ff3a7cedd Mon Sep 17 00:00:00 2001 From: Hal Eisen Date: Sat, 11 Jul 2026 08:08:48 -0700 Subject: [PATCH 1/3] ADFA-2686: Centralize the feedback FAB into one shared definition The "Send feedback" FAB was declared independently at every call site, so its size drifted: OnboardingActivity built it in code with no fabCustomSize (defaulting to Material's 56dp), while the five XML screens used 32dp. Define the FAB's appearance once in res/layout/feedback_fab.xml (size, icon, elevation, content description) and reuse it via in the five activity layouts and via LayoutInflater in OnboardingActivity. Size is driven by new feedback_fab_size (32dp) and feedback_fab_icon_size dimens, the latter controlling how snugly the icon fills the circle. Since the FAB now comes from an included binding, call sites reference binding.fabFeedback.root (nullable ?.root in AboutActivity, whose land/ sw600dp variants omit the FAB). Drag/position/click behavior in FeedbackButtonManager is unchanged. Verified on emulator: the feedback FAB now renders as the same 32dp circle on the editor, main, about, preferences, plugin-manager and onboarding screens (onboarding was previously the 56dp outlier). --- .../androidide/activities/AboutActivity.kt | 2 +- .../androidide/activities/MainActivity.kt | 2 +- .../activities/OnboardingActivity.kt | 32 +++++++++---------- .../activities/PluginManagerActivity.kt | 2 +- .../activities/PreferencesActivity.kt | 2 +- .../activities/editor/BaseEditorActivity.kt | 2 +- app/src/main/res/layout/activity_about.xml | 9 ++---- app/src/main/res/layout/activity_editor.xml | 7 ++-- app/src/main/res/layout/activity_main.xml | 7 ++-- .../res/layout/activity_plugin_manager.xml | 9 ++---- .../main/res/layout/activity_preferences.xml | 9 ++---- app/src/main/res/layout/feedback_fab.xml | 18 +++++++++++ resources/src/main/res/values/dimens.xml | 5 +++ 13 files changed, 57 insertions(+), 49 deletions(-) create mode 100644 app/src/main/res/layout/feedback_fab.xml diff --git a/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt index 4ae72de149..84adcfdb7d 100755 --- a/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt @@ -78,7 +78,7 @@ class AboutActivity : EdgeToEdgeIDEActivity() { supportActionBar!!.setDisplayHomeAsUpEnabled(true) supportActionBar!!.setTitle(R.string.about) toolbar.setNavigationOnClickListener { onBackPressedDispatcher.onBackPressed() } - feedbackButtonManager = FeedbackButtonManager(this@AboutActivity, fabFeedback) + feedbackButtonManager = FeedbackButtonManager(this@AboutActivity, fabFeedback?.root) feedbackButtonManager?.setupDraggableFab() aboutHeader.apply { diff --git a/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt index e537afdb72..de2731000f 100755 --- a/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt @@ -136,7 +136,7 @@ class MainActivity : EdgeToEdgeIDEActivity() { feedbackButtonManager = FeedbackButtonManager( activity = this, - feedbackFab = binding.fabFeedback, + feedbackFab = binding.fabFeedback.root, ) feedbackButtonManager?.setupDraggableFab() diff --git a/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt index 1a45872dd0..03304b2f21 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt @@ -171,24 +171,24 @@ class OnboardingActivity : AppIntro2() { val appIntroContainer: ConstraintLayout? = findViewById(R.id.background) if (appIntroContainer != null) { - feedbackButton = FloatingActionButton(this@OnboardingActivity).apply { - id = R.id.fab_feedback - setImageResource(R.drawable.baseline_feedback_64) - contentDescription = getString(string.send_feedback) - val layoutParams = ConstraintLayout.LayoutParams( + // Reuse the shared feedback FAB definition (size, icon, elevation) so this + // matches every other screen (ADFA-2686); only positioning is set here. + feedbackButton = (layoutInflater.inflate( + R.layout.feedback_fab, appIntroContainer, false + ) as FloatingActionButton).apply { + layoutParams = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT - ) - - layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID - layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID - val marginInPx = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - 16f, - resources.displayMetrics - ).toInt() - layoutParams.setMargins(marginInPx, marginInPx, marginInPx, marginInPx) - this.layoutParams = layoutParams + ).apply { + startToStart = ConstraintLayout.LayoutParams.PARENT_ID + bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID + val marginInPx = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 16f, + resources.displayMetrics + ).toInt() + setMargins(marginInPx, marginInPx, marginInPx, marginInPx) + } } appIntroContainer.addView(feedbackButton) diff --git a/app/src/main/java/com/itsaky/androidide/activities/PluginManagerActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/PluginManagerActivity.kt index 53799d007f..b01483e4c1 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/PluginManagerActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/PluginManagerActivity.kt @@ -187,7 +187,7 @@ class PluginManagerActivity : EdgeToEdgeIDEActivity() { feedbackButtonManager = FeedbackButtonManager( activity = this, - feedbackFab = binding.fabFeedback, + feedbackFab = binding.fabFeedback.root, ) feedbackButtonManager?.setupDraggableFab() } diff --git a/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt index a26a12518e..c5d1fd31ed 100755 --- a/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt @@ -65,7 +65,7 @@ class PreferencesActivity : EdgeToEdgeIDEActivity() { feedbackButtonManager = FeedbackButtonManager( activity = this, - feedbackFab = binding.fabFeedback, + feedbackFab = binding.fabFeedback.root, ) feedbackButtonManager?.setupDraggableFab() diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt index 0c573adb4d..20a440ae91 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt @@ -733,7 +733,7 @@ abstract class BaseEditorActivity : feedbackButtonManager = FeedbackButtonManager( activity = this, - feedbackFab = binding.fabFeedback, + feedbackFab = binding.fabFeedback.root, getLogContent = ::getLogContent, ) feedbackButtonManager?.setupDraggableFab() diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 52efb578aa..f2ed13a670 100755 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -96,15 +96,12 @@ - + android:layout_gravity="bottom|start" /> diff --git a/app/src/main/res/layout/activity_editor.xml b/app/src/main/res/layout/activity_editor.xml index 5986761123..4f2a1ce77e 100755 --- a/app/src/main/res/layout/activity_editor.xml +++ b/app/src/main/res/layout/activity_editor.xml @@ -68,15 +68,12 @@ - diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 5ba7fdf8ca..29f92c67cc 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -83,15 +83,12 @@ android:visibility="gone" /> - diff --git a/app/src/main/res/layout/activity_plugin_manager.xml b/app/src/main/res/layout/activity_plugin_manager.xml index 6503a069a0..f1a269b5d7 100644 --- a/app/src/main/res/layout/activity_plugin_manager.xml +++ b/app/src/main/res/layout/activity_plugin_manager.xml @@ -78,15 +78,12 @@ android:contentDescription="@string/cd_add" app:srcCompat="@drawable/ic_add" /> - + android:layout_gravity="bottom|start" /> diff --git a/app/src/main/res/layout/activity_preferences.xml b/app/src/main/res/layout/activity_preferences.xml index 66dc7e257d..916d58d18c 100755 --- a/app/src/main/res/layout/activity_preferences.xml +++ b/app/src/main/res/layout/activity_preferences.xml @@ -49,15 +49,12 @@ - + android:layout_margin="16dp" /> diff --git a/app/src/main/res/layout/feedback_fab.xml b/app/src/main/res/layout/feedback_fab.xml new file mode 100644 index 0000000000..7a2dd09a1a --- /dev/null +++ b/app/src/main/res/layout/feedback_fab.xml @@ -0,0 +1,18 @@ + + + diff --git a/resources/src/main/res/values/dimens.xml b/resources/src/main/res/values/dimens.xml index 98584cd383..74faa9a71b 100755 --- a/resources/src/main/res/values/dimens.xml +++ b/resources/src/main/res/values/dimens.xml @@ -9,4 +9,9 @@ 24dp 24dp 16dp + + + 32dp + 26dp From 7f3ff75fe0d0fc70d5769b5883e7f8c86c405a46 Mon Sep 17 00:00:00 2001 From: Hal Eisen Date: Sat, 11 Jul 2026 08:27:03 -0700 Subject: [PATCH 2/3] ADFA-2686: Add feedback FAB to about landscape/sw600dp variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The land and sw600dp variants of activity_about.xml omitted the feedback FAB, which violates the invariant that every page must always offer feedback. Add the shared feedback_fab include to both variants (bottom|start, matching portrait). Now that fab_feedback is present in every activity_about variant, its View Binding field is non-null, so AboutActivity uses binding.fabFeedback.root (dropping the previous nullable ?.root) — consistent with the other screens. --- .../com/itsaky/androidide/activities/AboutActivity.kt | 2 +- app/src/main/res/layout-land/activity_about.xml | 8 ++++++++ app/src/main/res/layout-sw600dp/activity_about.xml | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt index 84adcfdb7d..9eb8ddbccc 100755 --- a/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt @@ -78,7 +78,7 @@ class AboutActivity : EdgeToEdgeIDEActivity() { supportActionBar!!.setDisplayHomeAsUpEnabled(true) supportActionBar!!.setTitle(R.string.about) toolbar.setNavigationOnClickListener { onBackPressedDispatcher.onBackPressed() } - feedbackButtonManager = FeedbackButtonManager(this@AboutActivity, fabFeedback?.root) + feedbackButtonManager = FeedbackButtonManager(this@AboutActivity, fabFeedback.root) feedbackButtonManager?.setupDraggableFab() aboutHeader.apply { diff --git a/app/src/main/res/layout-land/activity_about.xml b/app/src/main/res/layout-land/activity_about.xml index ea074ff595..9a4ecfa240 100755 --- a/app/src/main/res/layout-land/activity_about.xml +++ b/app/src/main/res/layout-land/activity_about.xml @@ -118,4 +118,12 @@ + + diff --git a/app/src/main/res/layout-sw600dp/activity_about.xml b/app/src/main/res/layout-sw600dp/activity_about.xml index ea074ff595..9a4ecfa240 100755 --- a/app/src/main/res/layout-sw600dp/activity_about.xml +++ b/app/src/main/res/layout-sw600dp/activity_about.xml @@ -118,4 +118,12 @@ + + From 100fdbc0393d2cdd388bc0bfabb71ee5283cbaf2 Mon Sep 17 00:00:00 2001 From: Hal Eisen Date: Sun, 12 Jul 2026 10:16:50 -0700 Subject: [PATCH 3/3] ADFA-2686: Address CodeRabbit nitpicks on feedback FAB - feedback_fab.xml: use app:elevation and app:srcCompat (Material-recommended attributes) instead of android:elevation / android:src. - Centralize the FAB margin: add @dimen/feedback_fab_margin (16dp) and reference it from all 7 feedback-FAB includes (editor/main/about/preferences/plugin_manager plus about land/sw600dp variants) instead of hardcoding 16dp. - OnboardingActivity: read the same dimen via getDimensionPixelSize instead of a hardcoded 16dp TypedValue conversion, so the margin lives in one place. --- .../itsaky/androidide/activities/OnboardingActivity.kt | 8 ++------ app/src/main/res/layout-land/activity_about.xml | 2 +- app/src/main/res/layout-sw600dp/activity_about.xml | 2 +- app/src/main/res/layout/activity_about.xml | 2 +- app/src/main/res/layout/activity_editor.xml | 2 +- app/src/main/res/layout/activity_main.xml | 2 +- app/src/main/res/layout/activity_plugin_manager.xml | 2 +- app/src/main/res/layout/activity_preferences.xml | 2 +- app/src/main/res/layout/feedback_fab.xml | 4 ++-- resources/src/main/res/values/dimens.xml | 1 + 10 files changed, 12 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt index 03304b2f21..385feadbcc 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/OnboardingActivity.kt @@ -19,7 +19,6 @@ package com.itsaky.androidide.activities import android.content.Intent import android.os.Bundle -import android.util.TypedValue import android.view.View import android.view.ViewTreeObserver import android.view.animation.Animation @@ -182,11 +181,8 @@ class OnboardingActivity : AppIntro2() { ).apply { startToStart = ConstraintLayout.LayoutParams.PARENT_ID bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID - val marginInPx = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - 16f, - resources.displayMetrics - ).toInt() + val marginInPx = + resources.getDimensionPixelSize(R.dimen.feedback_fab_margin) setMargins(marginInPx, marginInPx, marginInPx, marginInPx) } } diff --git a/app/src/main/res/layout-land/activity_about.xml b/app/src/main/res/layout-land/activity_about.xml index 9a4ecfa240..4ec21aaa12 100755 --- a/app/src/main/res/layout-land/activity_about.xml +++ b/app/src/main/res/layout-land/activity_about.xml @@ -123,7 +123,7 @@ layout="@layout/feedback_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="16dp" + android:layout_margin="@dimen/feedback_fab_margin" android:layout_gravity="bottom|start" /> diff --git a/app/src/main/res/layout-sw600dp/activity_about.xml b/app/src/main/res/layout-sw600dp/activity_about.xml index 9a4ecfa240..4ec21aaa12 100755 --- a/app/src/main/res/layout-sw600dp/activity_about.xml +++ b/app/src/main/res/layout-sw600dp/activity_about.xml @@ -123,7 +123,7 @@ layout="@layout/feedback_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="16dp" + android:layout_margin="@dimen/feedback_fab_margin" android:layout_gravity="bottom|start" /> diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index f2ed13a670..516183136f 100755 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -101,7 +101,7 @@ layout="@layout/feedback_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="16dp" + android:layout_margin="@dimen/feedback_fab_margin" android:layout_gravity="bottom|start" /> diff --git a/app/src/main/res/layout/activity_editor.xml b/app/src/main/res/layout/activity_editor.xml index 4f2a1ce77e..9c9e12900f 100755 --- a/app/src/main/res/layout/activity_editor.xml +++ b/app/src/main/res/layout/activity_editor.xml @@ -73,7 +73,7 @@ layout="@layout/feedback_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="16dp" + android:layout_margin="@dimen/feedback_fab_margin" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 29f92c67cc..069a7183cf 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -88,7 +88,7 @@ layout="@layout/feedback_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="16dp" + android:layout_margin="@dimen/feedback_fab_margin" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/src/main/res/layout/activity_plugin_manager.xml b/app/src/main/res/layout/activity_plugin_manager.xml index f1a269b5d7..919d60c6fd 100644 --- a/app/src/main/res/layout/activity_plugin_manager.xml +++ b/app/src/main/res/layout/activity_plugin_manager.xml @@ -83,7 +83,7 @@ layout="@layout/feedback_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="16dp" + android:layout_margin="@dimen/feedback_fab_margin" android:layout_gravity="bottom|start" /> diff --git a/app/src/main/res/layout/activity_preferences.xml b/app/src/main/res/layout/activity_preferences.xml index 916d58d18c..f36f1eb036 100755 --- a/app/src/main/res/layout/activity_preferences.xml +++ b/app/src/main/res/layout/activity_preferences.xml @@ -55,6 +55,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|start" - android:layout_margin="16dp" /> + android:layout_margin="@dimen/feedback_fab_margin" /> diff --git a/app/src/main/res/layout/feedback_fab.xml b/app/src/main/res/layout/feedback_fab.xml index 7a2dd09a1a..2cb4a06238 100644 --- a/app/src/main/res/layout/feedback_fab.xml +++ b/app/src/main/res/layout/feedback_fab.xml @@ -12,7 +12,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/send_feedback" - android:elevation="16dp" - android:src="@drawable/baseline_feedback_64" + app:elevation="16dp" + app:srcCompat="@drawable/baseline_feedback_64" app:fabCustomSize="@dimen/feedback_fab_size" app:maxImageSize="@dimen/feedback_fab_icon_size" /> diff --git a/resources/src/main/res/values/dimens.xml b/resources/src/main/res/values/dimens.xml index 74faa9a71b..8ee5f2a988 100755 --- a/resources/src/main/res/values/dimens.xml +++ b/resources/src/main/res/values/dimens.xml @@ -14,4 +14,5 @@ feedback_fab_icon_size controls how snugly the icon fills the circle. --> 32dp 26dp + 16dp