Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion packages/core/application/application.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import { androidGetForegroundActivity, androidGetStartActivity, androidSetForegr
import { getImageFetcher, getNativeApp, getRootView, initImageCache, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setNativeApp, setRootView, setToggleApplicationEventListenersCallback } from './helpers-common';
import { getNativeScriptGlobals } from '../globals/global-utils';
import type { AndroidApplication as IAndroidApplication } from './application';
import { enableEdgeToEdge } from '../utils/native-helper-for-android';
import { enableEdgeToEdge, refreshEdgeToEdge } from '../utils/native-helper-for-android';
import lazy from '../utils/lazy';

declare class NativeScriptLifecycleCallbacks extends android.app.Application.ActivityLifecycleCallbacks {}
Expand Down Expand Up @@ -561,6 +561,8 @@ export class AndroidApplication extends ApplicationCommon implements IAndroidApp
this._pendingReceiverRegistrations.length = 0;
}

private edgeToEdgeAppearance: 'dark' | 'light' | null = null;

onConfigurationChanged(configuration: android.content.res.Configuration): void {
// The application context reports the app-wide configuration, which a window on a
// second display or in split-screen does not necessarily share, so the primary
Expand All @@ -572,6 +574,17 @@ export class AndroidApplication extends ApplicationCommon implements IAndroidApp
this.setLayoutDirection(primaryWindow?.layoutDirection() ?? this.getLayoutDirectionValue(configuration));
}

protected setSystemAppearance(value: 'dark' | 'light') {
super.setSystemAppearance(value);
// The activity survives the switch (uiMode is a handled config change),
// so the edge-to-edge system bar style must be applied again to pick up
// the icon appearance for the new theme.
if (this.edgeToEdgeAppearance !== value) {
this.edgeToEdgeAppearance = value;
refreshEdgeToEdge(this.foregroundActivity ?? this.startActivity);
}
}

getNativeApplication() {
let nativeApp = this.nativeApp;

Expand Down
12 changes: 12 additions & 0 deletions packages/core/utils/native-helper-for-android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,18 @@ interface ISystemColor {
}
const systemColors = new WeakMap<androidx.appcompat.app.AppCompatActivity, ISystemColor>();

export function refreshEdgeToEdge(activity: androidx.appcompat.app.AppCompatActivity): void {
if (!activity) {
return;
}
const existingColors = systemColors.get(activity);
if (existingColors) {
setEnableEdgeToEdge(activity, existingColors);
} else {
enableEdgeToEdge(activity);
}
}

function setEnableEdgeToEdge(activity: androidx.appcompat.app.AppCompatActivity, existingColors: ISystemColor) {
enableEdgeToEdge(activity, {
statusBarLightColor: existingColors.statusBarLight,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/utils/native-helper.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { IOSNativeHelper } from './native-helper.types';
import { platformCheck } from './platform-check';

// importing this helper as a separate file avoids "android" symbol clash with the global android object
import { resources, collections, getWindow, getApplication, getCurrentActivity, getApplicationContext, getResources, getPackageName, getInputMethodManager, showSoftInput, dismissSoftInput, enableEdgeToEdge, setDarkModeHandler, setNavigationBarColor, setStatusBarColor, getIgnoreEdgeToEdgeOnOlderDevices, setIgnoreEdgeToEdgeOnOlderDevices } from './native-helper-for-android';
import { resources, collections, getWindow, getApplication, getCurrentActivity, getApplicationContext, getResources, getPackageName, getInputMethodManager, showSoftInput, dismissSoftInput, enableEdgeToEdge, refreshEdgeToEdge, setDarkModeHandler, setNavigationBarColor, setStatusBarColor, getIgnoreEdgeToEdgeOnOlderDevices, setIgnoreEdgeToEdgeOnOlderDevices } from './native-helper-for-android';
export { dataSerialize, dataDeserialize } from './native-helper-for-android';

export { getWindow } from './native-helper-for-android';
Expand All @@ -20,6 +20,7 @@ export const android = {
showSoftInput,
dismissSoftInput,
enableEdgeToEdge,
refreshEdgeToEdge,
setStatusBarColor,
setNavigationBarColor,
setDarkModeHandler,
Expand Down
7 changes: 7 additions & 0 deletions packages/core/utils/native-helper.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ export const android: {
* @param options Options to set status bar color.
*/
setStatusBarColor(options?: { activity?: androidx.appcompat.app.AppCompatActivity; lightColor?: Color; darkColor?: Color }): void;
/**
* Re-applies the activity's edge-to-edge styling. The system bar icon
* appearance is decided from the theme at the time the style is applied, so
* an activity that survives a dark-mode switch keeps the old icons until this
* runs again.
*/
refreshEdgeToEdge(activity: androidx.appcompat.app.AppCompatActivity): void;
/**
* Enables edge-to-edge navigation for the provided activity.
* @param activity The activity to enable edge-to-edge navigation for.
Expand Down
Loading