diff --git a/PasscodeLock/src/main/java/org/wordpress/passcodelock/PasscodeManagePasswordActivity.java b/PasscodeLock/src/main/java/org/wordpress/passcodelock/PasscodeManagePasswordActivity.java index 563294851..b48c46a24 100644 --- a/PasscodeLock/src/main/java/org/wordpress/passcodelock/PasscodeManagePasswordActivity.java +++ b/PasscodeLock/src/main/java/org/wordpress/passcodelock/PasscodeManagePasswordActivity.java @@ -1,12 +1,15 @@ package org.wordpress.passcodelock; import android.annotation.SuppressLint; +import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.TextView; import androidx.core.hardware.fingerprint.FingerprintManagerCompat; import androidx.core.os.CancellationSignal; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsControllerCompat; public class PasscodeManagePasswordActivity extends AbstractPasscodeKeyboardActivity { public static final String KEY_TYPE = "type"; @@ -17,6 +20,23 @@ public class PasscodeManagePasswordActivity extends AbstractPasscodeKeyboardActi @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + // Setup edge-to-edge display for Android 15+ compatibility + // This is a fullscreen passcode activity without toolbar + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + WindowCompat.setDecorFitsSystemWindows(getWindow(), false); + + WindowInsetsControllerCompat controller = WindowCompat.getInsetsController( + getWindow(), + getWindow().getDecorView() + ); + + if (controller != null) { + // Dark status bar appearance for the passcode screen background + controller.setAppearanceLightStatusBars(false); + controller.setAppearanceLightNavigationBars(false); + } + } Bundle extras = getIntent().getExtras(); if (extras != null) { diff --git a/PasscodeLock/src/main/res/layout/app_passcode_keyboard.xml b/PasscodeLock/src/main/res/layout/app_passcode_keyboard.xml index cbaed5825..e612a83d6 100644 --- a/PasscodeLock/src/main/res/layout/app_passcode_keyboard.xml +++ b/PasscodeLock/src/main/res/layout/app_passcode_keyboard.xml @@ -6,10 +6,11 @@ android:background="@color/passcodelock_background" android:layout_height="match_parent" android:layout_width="match_parent" + android:fitsSystemWindows="false" android:paddingBottom="24dp" android:paddingLeft="24dp" android:paddingRight="24dp" - android:paddingTop="32dp"> + android:paddingTop="?attr/actionBarSize"> + android:parentActivityName=".NotesActivity" + android:theme="@style/Theme.Simplestyle"> = Build.VERSION_CODES.VANILLA_ICE_CREAM) { + SystemBarUtils.setupEdgeToEdgeWithAutoTheming(this@AddTagActivity, root, null, null) + } + + // Add minimal IME (keyboard) insets handling for dialog positioning + ViewCompat.setOnApplyWindowInsetsListener(root) { view, insets -> + val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()) + view.setPadding(view.paddingLeft, view.paddingTop, view.paddingRight, imeInsets.bottom) + insets + } + } - setContentView(binding.root) } private fun ActivityTagAddBinding.setupViews() { diff --git a/Simplenote/src/main/java/com/automattic/simplenote/CollaboratorsActivity.kt b/Simplenote/src/main/java/com/automattic/simplenote/CollaboratorsActivity.kt index 2838e2a59..004a979d1 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/CollaboratorsActivity.kt +++ b/Simplenote/src/main/java/com/automattic/simplenote/CollaboratorsActivity.kt @@ -13,9 +13,10 @@ import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import com.automattic.simplenote.databinding.ActivityCollaboratorsBinding import com.automattic.simplenote.utils.CollaboratorsAdapter -import com.automattic.simplenote.utils.CollaboratorsAdapter.* import com.automattic.simplenote.utils.CollaboratorsAdapter.CollaboratorDataItem.* +import com.automattic.simplenote.utils.DisplayUtils import com.automattic.simplenote.utils.IntentUtils +import com.automattic.simplenote.utils.SystemBarUtils import com.automattic.simplenote.utils.toast import com.automattic.simplenote.viewmodels.CollaboratorsViewModel import com.automattic.simplenote.viewmodels.CollaboratorsViewModel.Event @@ -47,6 +48,16 @@ class CollaboratorsActivity : ThemedAppCompatActivity() { setObservers() viewModel.loadCollaborators(noteId) + + // Setup edge-to-edge display with proper WindowInsets handling + // Use auto-theming to properly handle status bar appearance based on theme + val toolbar = findViewById(R.id.toolbar) + SystemBarUtils.setupEdgeToEdgeWithAutoTheming( + this@CollaboratorsActivity, + findViewById(R.id.main_parent_view), + toolbar, + collaboratorsList + ) } } @@ -79,6 +90,9 @@ class CollaboratorsActivity : ThemedAppCompatActivity() { collaboratorsList.setEmptyView(empty.root) buttonAddCollaborator.setOnClickListener { viewModel.clickAddCollaborator() } + buttonAddCollaborator.setOnApplyWindowInsetsListener { view, insets -> + DisplayUtils.applyWindowInsetsForFloatingActionButton(insets, resources, view) + } empty.image.setImageResource(R.drawable.ic_collaborate_24dp) empty.title.text = getString(R.string.no_collaborators) diff --git a/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorActivity.java b/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorActivity.java index e7338d8d8..c9d32cd68 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorActivity.java +++ b/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorActivity.java @@ -36,6 +36,7 @@ import com.automattic.simplenote.utils.DisplayUtils; import com.automattic.simplenote.utils.IntentUtils; import com.automattic.simplenote.utils.NetworkUtils; +import com.automattic.simplenote.utils.SystemBarUtils; import com.automattic.simplenote.utils.WidgetUtils; import com.automattic.simplenote.widgets.NoteEditorViewPager; import com.automattic.simplenote.widgets.RobotoMediumTextView; @@ -230,6 +231,15 @@ public void onPageScrollStateChanged(int state) { "note_list_widget_note_tapped" ); } + + // Setup edge-to-edge display with proper WindowInsets handling + // Use auto-theming to properly handle status bar appearance based on theme + SystemBarUtils.setupEdgeToEdgeWithAutoTheming( + this, + findViewById(R.id.main_parent_view), + toolbar, + findViewById(R.id.pager) + ); } @Override diff --git a/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorFragment.java b/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorFragment.java index afb535a01..02c8c3788 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorFragment.java +++ b/Simplenote/src/main/java/com/automattic/simplenote/NoteEditorFragment.java @@ -82,6 +82,7 @@ import com.automattic.simplenote.utils.TagsMultiAutoCompleteTextView; import com.automattic.simplenote.utils.TagsMultiAutoCompleteTextView.OnTagAddedListener; import com.automattic.simplenote.utils.TextHighlighter; +import com.automattic.simplenote.utils.SystemBarUtils; import com.automattic.simplenote.utils.ThemeUtils; import com.automattic.simplenote.utils.WidgetUtils; import com.automattic.simplenote.viewmodels.NoteEditorViewModel; @@ -204,7 +205,7 @@ public boolean onCreateActionMode(ActionMode mode, Menu menu) { DrawableUtils.tintMenuWithAttribute(getActivity(), menu, R.attr.toolbarIconColor); } - requireActivity().getWindow().setStatusBarColor(ThemeUtils.getColorFromAttribute(requireContext(), R.attr.mainBackgroundColor)); + SystemBarUtils.setStatusBarColor(requireActivity(), ThemeUtils.getColorFromAttribute(requireContext(), R.attr.mainBackgroundColor)); return true; } @@ -279,7 +280,7 @@ public void onDestroyActionMode(ActionMode mode) { } new Handler().postDelayed( - () -> requireActivity().getWindow().setStatusBarColor( + () -> SystemBarUtils.setStatusBarColor(requireActivity(), getResources().getColor(android.R.color.transparent, requireActivity().getTheme())), requireContext().getResources().getInteger(android.R.integer.config_mediumAnimTime) ); diff --git a/Simplenote/src/main/java/com/automattic/simplenote/NoteListFragment.java b/Simplenote/src/main/java/com/automattic/simplenote/NoteListFragment.java index 1bbb67858..c1b6b8ee8 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/NoteListFragment.java +++ b/Simplenote/src/main/java/com/automattic/simplenote/NoteListFragment.java @@ -80,6 +80,7 @@ import com.automattic.simplenote.utils.SimplenoteLinkify; import com.automattic.simplenote.utils.StrUtils; import com.automattic.simplenote.utils.TextHighlighter; +import com.automattic.simplenote.utils.SystemBarUtils; import com.automattic.simplenote.utils.ThemeUtils; import com.automattic.simplenote.utils.WidgetUtils; import com.automattic.simplenote.widgets.RobotoRegularTextView; @@ -193,7 +194,7 @@ public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { inflater.inflate(R.menu.bulk_edit, menu); DrawableUtils.tintMenuWithAttribute(getActivity(), menu, R.attr.actionModeTextColor); mActionMode = actionMode; - requireActivity().getWindow().setStatusBarColor(ThemeUtils.getColorFromAttribute(requireContext(), R.attr.mainBackgroundColor)); + SystemBarUtils.setStatusBarColor(requireActivity(), ThemeUtils.getColorFromAttribute(requireContext(), R.attr.mainBackgroundColor)); return true; } @@ -304,7 +305,7 @@ public void onDestroyActionMode(ActionMode mode) { new Runnable() { @Override public void run() { - requireActivity().getWindow().setStatusBarColor(getResources().getColor(android.R.color.transparent, requireActivity().getTheme())); + SystemBarUtils.setStatusBarColor(requireActivity(), getResources().getColor(android.R.color.transparent, requireActivity().getTheme())); } }, requireContext().getResources().getInteger(android.R.integer.config_longAnimTime) diff --git a/Simplenote/src/main/java/com/automattic/simplenote/PreferencesActivity.java b/Simplenote/src/main/java/com/automattic/simplenote/PreferencesActivity.java index f0ef0df1c..758300195 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/PreferencesActivity.java +++ b/Simplenote/src/main/java/com/automattic/simplenote/PreferencesActivity.java @@ -2,6 +2,7 @@ import android.os.Bundle; import android.view.View; +import android.view.ViewGroup; import android.widget.Toast; import androidx.appcompat.widget.Toolbar; @@ -9,6 +10,7 @@ import androidx.preference.Preference; import com.automattic.simplenote.utils.BrowserUtils; +import com.automattic.simplenote.utils.SystemBarUtils; import org.wordpress.passcodelock.PasscodePreferenceFragment; import org.wordpress.passcodelock.PasscodePreferenceFragmentCompat; @@ -56,6 +58,15 @@ protected void onCreate(Bundle savedInstanceState) { mPreferencesFragment = (PreferencesFragment) fragmentManager.findFragmentByTag(preferencesTag); mPasscodePreferenceFragment = (PasscodePreferenceFragmentCompat) fragmentManager.findFragmentByTag(passcodeTag); } + + // Setup edge-to-edge display with proper WindowInsets handling + // Use auto-theming to properly handle status bar appearance based on theme + SystemBarUtils.setupEdgeToEdgeWithAutoTheming( + this, + findViewById(R.id.main_parent_view), + toolbar, + findViewById(R.id.preferences_container) + ); } @Override diff --git a/Simplenote/src/main/java/com/automattic/simplenote/TagsActivity.kt b/Simplenote/src/main/java/com/automattic/simplenote/TagsActivity.kt index e84d64ec4..65b0dec73 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/TagsActivity.kt +++ b/Simplenote/src/main/java/com/automattic/simplenote/TagsActivity.kt @@ -16,6 +16,7 @@ import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import com.automattic.simplenote.databinding.ActivityTagsBinding import com.automattic.simplenote.utils.* +import com.automattic.simplenote.utils.SystemBarUtils import com.automattic.simplenote.viewmodels.TagsEvent import com.automattic.simplenote.viewmodels.TagsEvent.* import com.automattic.simplenote.viewmodels.TagsViewModel @@ -36,6 +37,16 @@ class TagsActivity : ThemedAppCompatActivity() { binding.setObservers() viewModel.start() + + // Setup edge-to-edge display with proper WindowInsets handling + // Use auto-theming to properly handle status bar appearance based on theme + val toolbar = findViewById(R.id.toolbar) + SystemBarUtils.setupEdgeToEdgeWithAutoTheming( + this, + findViewById(R.id.main_parent_view), + toolbar, + binding.list + ) } private fun ActivityTagsBinding.setupViews() { @@ -62,6 +73,9 @@ class TagsActivity : ThemedAppCompatActivity() { viewModel.longClickAddTag() true } + buttonAdd.setOnApplyWindowInsetsListener { view, insets -> + DisplayUtils.applyWindowInsetsForFloatingActionButton(insets, resources, view) + } } private fun ActivityTagsBinding.setObservers() { diff --git a/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteAuthenticationActivity.java b/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteAuthenticationActivity.java index 647bd216a..7ce9eb4dd 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteAuthenticationActivity.java +++ b/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteAuthenticationActivity.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.ContextThemeWrapper; @@ -11,6 +12,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; @@ -20,6 +25,7 @@ import com.automattic.simplenote.analytics.AnalyticsTracker; import com.automattic.simplenote.utils.IntentUtils; import com.automattic.simplenote.utils.StrUtils; +import com.automattic.simplenote.utils.SystemBarUtils; import com.automattic.simplenote.utils.WordPressUtils; import com.automattic.simplenote.viewmodels.MagicLinkUiState; import com.automattic.simplenote.viewmodels.CompleteMagicLinkViewModel; @@ -59,6 +65,28 @@ public class SimplenoteAuthenticationActivity extends AuthenticationActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + // Setup edge-to-edge display only on Android 15+ to avoid breaking existing theming + // Since this extends Simperium's AuthenticationActivity, we need to be conservative + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + WindowCompat.setDecorFitsSystemWindows(getWindow(), false); + SystemBarUtils.setSystemBarsAppearance(this, true, true); // Dark icons on light background + + // Apply navigation bar insets to avoid button overlap with 3-button navigation + ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content), (v, windowInsets) -> { + Insets systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); + + // Apply bottom padding to avoid navigation bar overlap + v.setPadding( + v.getPaddingLeft(), + v.getPaddingTop(), + v.getPaddingRight(), + systemBars.bottom + ); + + return WindowInsetsCompat.CONSUMED; + }); + } final Intent intent = getIntent(); diff --git a/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteSignupActivity.java b/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteSignupActivity.java index 1b14aa12c..6b5e73cba 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteSignupActivity.java +++ b/Simplenote/src/main/java/com/automattic/simplenote/authentication/SimplenoteSignupActivity.java @@ -12,6 +12,7 @@ import com.automattic.simplenote.R; import com.automattic.simplenote.authentication.magiclink.MagicLinkConfirmationFragment; +import com.automattic.simplenote.utils.SystemBarUtils; import dagger.hilt.android.AndroidEntryPoint; @@ -45,6 +46,17 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { final boolean isSignUp = !getIntent().getBooleanExtra(KEY_IS_LOGIN, false); initContainer(isSignUp); initToolbar(isSignUp); + + // Setup edge-to-edge display with proper WindowInsets handling + // Toolbar has white background, so we need light status bar appearance (dark icons) + SystemBarUtils.setupEdgeToEdgeWithToolbar( + this, + findViewById(R.id.main), + mToolbar, + findViewById(R.id.fragment_container), + true, // Light status bar (dark icons) for white toolbar background + true // Light navigation bar (dark icons) + ); } private void initContainer(final boolean isSignUp) { diff --git a/Simplenote/src/main/java/com/automattic/simplenote/utils/DisplayUtils.java b/Simplenote/src/main/java/com/automattic/simplenote/utils/DisplayUtils.java index 4c4f30fc0..0288dd802 100644 --- a/Simplenote/src/main/java/com/automattic/simplenote/utils/DisplayUtils.java +++ b/Simplenote/src/main/java/com/automattic/simplenote/utils/DisplayUtils.java @@ -3,12 +3,17 @@ import android.app.Activity; import android.content.Context; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Point; +import android.os.Build; import android.util.TypedValue; import android.view.Display; import android.view.View; +import android.view.WindowInsets; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; +import android.widget.RelativeLayout; +import com.google.android.material.floatingactionbutton.FloatingActionButton; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -149,4 +154,39 @@ public static void showKeyboard(@Nullable final View view) { inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); } } + + /** + * Apply window insets for a {@link FloatingActionButton} in a {@link RelativeLayout} to the given {@link View}. + * + * @param insets {@link WindowInsets} to apply to {@link View}. + * @param resources {@link Resources} to get dimension value from. + * @param view {@link View} to apply {@link WindowInsets} to. + * + * @return {@link WindowInsets} supplied from a listener. + */ + public static WindowInsets applyWindowInsetsForFloatingActionButton(WindowInsets insets, Resources resources, View view) { + int bottom; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + bottom = insets.getInsets(WindowInsets.Type.systemBars()).bottom; + } else { + bottom = insets.getSystemWindowInsetBottom(); + } + + int button = (int) resources.getDimension(R.dimen.button_floating); + int margin = (int) resources.getDimension(R.dimen.margin_default); + + RelativeLayout.LayoutParams buttonLayoutParams = new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.WRAP_CONTENT, + RelativeLayout.LayoutParams.WRAP_CONTENT + ); + buttonLayoutParams.setMargins(margin, 0, margin, bottom + margin); + buttonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + buttonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_END); + buttonLayoutParams.height = button; + buttonLayoutParams.width = button; + view.setLayoutParams(buttonLayoutParams); + + return insets; + } } diff --git a/Simplenote/src/main/java/com/automattic/simplenote/utils/SystemBarUtils.kt b/Simplenote/src/main/java/com/automattic/simplenote/utils/SystemBarUtils.kt new file mode 100644 index 000000000..32d1e2dcc --- /dev/null +++ b/Simplenote/src/main/java/com/automattic/simplenote/utils/SystemBarUtils.kt @@ -0,0 +1,174 @@ +package com.automattic.simplenote.utils + +import android.app.Activity +import android.content.res.Configuration +import android.os.Build +import android.view.View +import android.view.ViewGroup.MarginLayoutParams +import androidx.annotation.ColorInt +import androidx.appcompat.widget.Toolbar +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import kotlin.math.max + +/** + * Utility class to handle system bar appearance changes in a way that's compatible + * with Android 15's deprecated APIs for statusBarColor and navigationBarColor. + */ +object SystemBarUtils { + /** + * Sets the status bar color in a way that's compatible across Android versions. + * On Android 15+, this becomes a no-op as the API is deprecated. + * + * @param activity The activity whose status bar color should be changed + * @param color The color to set + */ + @JvmStatic + @Suppress("deprecation") + fun setStatusBarColor(activity: Activity?, @ColorInt color: Int) { + if (activity == null) return + + val window = activity.getWindow() + if (window == null) return + + // For Android 15+, we should use edge-to-edge design instead + // but for backward compatibility, we'll still set the color on older versions + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { + window.setStatusBarColor(color) + } + // On Android 15+, the deprecated setStatusBarColor is ignored + // Apps should migrate to edge-to-edge design with WindowInsets handling + } + + /** + * Sets the appearance of system bars (status bar and navigation bar) to be light or dark. + * This is the modern way to control system bar appearance. + * + * @param activity The activity + * @param lightStatusBar Whether status bar content should be dark (for light backgrounds) + * @param lightNavigationBar Whether navigation bar content should be dark (for light backgrounds) + */ + @JvmStatic + fun setSystemBarsAppearance(activity: Activity?, lightStatusBar: Boolean, lightNavigationBar: Boolean) { + if (activity == null) return + + val controller = WindowCompat.getInsetsController( + activity.getWindow(), + activity.getWindow().getDecorView() + ) + + controller.isAppearanceLightStatusBars = lightStatusBar + controller.isAppearanceLightNavigationBars = lightNavigationBar + } + + /** + * Sets up edge-to-edge display with custom system bar appearance. + * + * @param activity The activity to setup + * @param rootView The root view of the activity layout + * @param toolbar The toolbar that should be pushed below the status bar + * @param contentView The main content view that should avoid navigation bar overlap + * @param lightStatusBar Whether status bar content should be dark (for light backgrounds) + * @param lightNavigationBar Whether navigation bar content should be dark (for light backgrounds) + */ + @JvmStatic + fun setupEdgeToEdgeWithToolbar( + activity: Activity, + rootView: View?, + toolbar: Toolbar?, + contentView: View?, + lightStatusBar: Boolean, + lightNavigationBar: Boolean + ) { + // Enable edge-to-edge display + WindowCompat.setDecorFitsSystemWindows(activity.getWindow(), false) + + // Set custom status bar appearance + setSystemBarsAppearance(activity, lightStatusBar, lightNavigationBar) + + rootView?.let { + // Apply insets to the root view first - handles horizontal system bars (notches/cutouts) + ViewCompat.setOnApplyWindowInsetsListener(it, { v: View, windowInsets: WindowInsetsCompat -> + val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + // Apply horizontal insets to root view to handle notches/cutouts + v.setPadding( + systemBars.left, + 0, // Don't apply top padding here - toolbar will handle it + systemBars.right, + 0 // Don't apply bottom padding here - content view will handle it + ) + windowInsets + }) + } + + // Handle toolbar insets - make sure it doesn't overlap with status bar + toolbar?.let { + ViewCompat.setOnApplyWindowInsetsListener(it, { v: View, windowInsets: WindowInsetsCompat -> + val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + // Apply top margin to toolbar to push it below status bar + val toolbarParams = v.getLayoutParams() as MarginLayoutParams? + toolbarParams?.let { + it.topMargin = systemBars.top + v.setLayoutParams(it) + } + windowInsets + }) + } + + // Handle content view insets - avoid overlap with navigation bar + contentView?.let { + ViewCompat.setOnApplyWindowInsetsListener( + it, + { v: View, windowInsets: WindowInsetsCompat -> + val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + val ime = windowInsets.getInsets(WindowInsetsCompat.Type.ime()) + // Apply bottom padding to avoid navigation bar overlap, but let's consider IME too + // this will prevent the keyboard from pushing the content down + val bottomPadding = max(systemBars.bottom, ime.bottom) + v.setPadding( + v.getPaddingLeft(), + v.getPaddingTop(), + v.getPaddingRight(), + bottomPadding + ) + // WARNING: Don't consume IME insets - let them pass through to child views (scroll views) + // this will allow proper scrolling when keyboard appears + windowInsets.inset(0, 0, 0, systemBars.bottom) + }) + } + } + + /** + * Automatically determines the appropriate status bar appearance based on the current theme. + * Sets up edge-to-edge display with proper theming. + * + * @param activity The activity to setup + * @param rootView The root view of the activity layout + * @param toolbar The toolbar that should be pushed below the status bar + * @param contentView The main content view that should avoid navigation bar overlap + */ + @JvmStatic + fun setupEdgeToEdgeWithAutoTheming(activity: Activity?, rootView: View?, toolbar: Toolbar?, contentView: View?) { + if (activity == null || rootView == null) return + + // Determine if we're in light or dark theme + val isLightTheme = isLightTheme(activity) + + // Setup edge-to-edge with appropriate theme + setupEdgeToEdgeWithToolbar(activity, rootView, toolbar, contentView, isLightTheme, isLightTheme) + } + + /** + * Determines if the current theme is light or dark. + * + * @param activity The activity to check + * @return true if light theme, false if dark theme + */ + private fun isLightTheme(activity: Activity?): Boolean { + if (activity == null) return true + + val nightModeFlags = activity.getResources().getConfiguration().uiMode and Configuration.UI_MODE_NIGHT_MASK + return nightModeFlags != Configuration.UI_MODE_NIGHT_YES + } +} diff --git a/Simplenote/src/main/res/layout/activity_about.xml b/Simplenote/src/main/res/layout/activity_about.xml index 42e6362ad..dd447dda7 100644 --- a/Simplenote/src/main/res/layout/activity_about.xml +++ b/Simplenote/src/main/res/layout/activity_about.xml @@ -4,7 +4,8 @@ android:id="@+id/main_parent_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical"> + android:orientation="vertical" + android:fitsSystemWindows="false"> + android:orientation="vertical" + android:fitsSystemWindows="false"> diff --git a/Simplenote/src/main/res/layout/activity_note_editor.xml b/Simplenote/src/main/res/layout/activity_note_editor.xml index bc7c47c8c..3a93a6c88 100644 --- a/Simplenote/src/main/res/layout/activity_note_editor.xml +++ b/Simplenote/src/main/res/layout/activity_note_editor.xml @@ -5,13 +5,15 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_height="match_parent" - android:layout_width="match_parent"> + android:layout_width="match_parent" + android:fitsSystemWindows="false"> + android:orientation="vertical" + android:fitsSystemWindows="false"> diff --git a/Simplenote/src/main/res/layout/activity_signup.xml b/Simplenote/src/main/res/layout/activity_signup.xml index df62de391..f96187a25 100644 --- a/Simplenote/src/main/res/layout/activity_signup.xml +++ b/Simplenote/src/main/res/layout/activity_signup.xml @@ -1,11 +1,13 @@ - + android:layout_height="match_parent" + android:orientation="vertical" + android:fitsSystemWindows="false"> - + diff --git a/Simplenote/src/main/res/layout/activity_tag_add.xml b/Simplenote/src/main/res/layout/activity_tag_add.xml index 40dbe987f..efc8f7725 100644 --- a/Simplenote/src/main/res/layout/activity_tag_add.xml +++ b/Simplenote/src/main/res/layout/activity_tag_add.xml @@ -4,6 +4,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" + android:fitsSystemWindows="false" android:gravity="center" android:layout_height="match_parent" android:layout_width="match_parent"> diff --git a/Simplenote/src/main/res/layout/activity_tags.xml b/Simplenote/src/main/res/layout/activity_tags.xml index dbe2b091e..6a734d028 100644 --- a/Simplenote/src/main/res/layout/activity_tags.xml +++ b/Simplenote/src/main/res/layout/activity_tags.xml @@ -5,7 +5,8 @@ android:id="@+id/main_parent_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical"> + android:orientation="vertical" + android:fitsSystemWindows="false"> diff --git a/Simplenote/src/main/res/layout/fragment_login.xml b/Simplenote/src/main/res/layout/fragment_login.xml index 06bba18eb..4a5f7b5ef 100644 --- a/Simplenote/src/main/res/layout/fragment_login.xml +++ b/Simplenote/src/main/res/layout/fragment_login.xml @@ -4,7 +4,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="@dimen/width_layout" android:layout_height="match_parent" - android:layout_marginTop="?attr/actionBarSize" android:clipToPadding="false" android:padding="@dimen/margin_default" android:background="?mainBackgroundColor" @@ -17,7 +16,7 @@ android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginStart="@dimen/margin_default_quarter" - android:layout_marginTop="@dimen/margin_default" + android:layout_marginTop="@dimen/margin_default_quarter" android:layout_marginEnd="@dimen/margin_default_quarter" android:layout_marginBottom="@dimen/margin_default_quarter" android:hint="@string/simperium_hint_email" diff --git a/Simplenote/src/main/res/layout/fragment_magic_link_code.xml b/Simplenote/src/main/res/layout/fragment_magic_link_code.xml index df9b33834..78cd09ed6 100644 --- a/Simplenote/src/main/res/layout/fragment_magic_link_code.xml +++ b/Simplenote/src/main/res/layout/fragment_magic_link_code.xml @@ -5,7 +5,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/margin_default" - android:layout_marginTop="?attr/actionBarSize" android:background="?mainBackgroundColor" android:orientation="vertical" > diff --git a/Simplenote/src/main/res/layout/fragment_signup.xml b/Simplenote/src/main/res/layout/fragment_signup.xml index 8ec971ae3..356dc9447 100644 --- a/Simplenote/src/main/res/layout/fragment_signup.xml +++ b/Simplenote/src/main/res/layout/fragment_signup.xml @@ -4,7 +4,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="@dimen/width_layout" android:layout_height="match_parent" - android:layout_marginTop="?attr/actionBarSize" android:clipToPadding="false" android:padding="@dimen/margin_default" tools:layout_width="match_parent"> @@ -16,7 +15,7 @@ android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginStart="@dimen/margin_default_quarter" - android:layout_marginTop="@dimen/margin_default" + android:layout_marginTop="@dimen/margin_default_quarter" android:layout_marginEnd="@dimen/margin_default_quarter" android:layout_marginBottom="@dimen/margin_default_quarter" android:hint="@string/simperium_hint_email" diff --git a/Simplenote/src/main/res/layout/toolbar.xml b/Simplenote/src/main/res/layout/toolbar.xml index 08ea6c2c7..31dc6e8d3 100644 --- a/Simplenote/src/main/res/layout/toolbar.xml +++ b/Simplenote/src/main/res/layout/toolbar.xml @@ -5,6 +5,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_height="wrap_content" android:layout_width="match_parent" + android:background="?attr/toolbarColor" + android:fitsSystemWindows="false" android:theme="@style/ToolbarTheme.AppBarOverlay"> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Simplenote/src/main/res/values-v35/styles.xml b/Simplenote/src/main/res/values-v35/styles.xml new file mode 100644 index 000000000..cb02acce4 --- /dev/null +++ b/Simplenote/src/main/res/values-v35/styles.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Wear/build.gradle b/Wear/build.gradle index dee8b2523..04a93c555 100644 --- a/Wear/build.gradle +++ b/Wear/build.gradle @@ -21,7 +21,7 @@ android { defaultConfig { applicationId "com.automattic.simplenote" minSdkVersion 23 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 2 versionName "1.1.0" }