mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(core): statusBarStyle ease of use and more control (#10859)
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page" statusBarStyle="dark">
|
||||||
<Page.actionBar>
|
<Page.actionBar>
|
||||||
<ActionBar title="Dev Toolbox" icon="" class="action-bar" iosLargeTitle="true" iosShadow="false">
|
<ActionBar title="Dev Toolbox" icon="" class="action-bar" iosLargeTitle="true" iosShadow="false">
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
@ -20,6 +20,7 @@
|
|||||||
<Button text="list-page" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="list-page" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="root-layout" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="root-layout" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="scroll-view" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="scroll-view" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
|
<Button text="status-bar" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="switch" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="switch" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="touch-animations" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="touch-animations" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="transitions" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="transitions" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
|
|||||||
22
apps/toolbox/src/pages/status-bar.ts
Normal file
22
apps/toolbox/src/pages/status-bar.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Page, Observable, EventData, Dialogs, ShowModalOptions } from '@nativescript/core';
|
||||||
|
|
||||||
|
let page: Page;
|
||||||
|
|
||||||
|
export function navigatingTo(args: EventData) {
|
||||||
|
page = <Page>args.object;
|
||||||
|
page.bindingContext = new StatusBarModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StatusBarModel extends Observable {
|
||||||
|
onOpenModal() {
|
||||||
|
page.showModal('pages/status-bar/status-bar-modal', {
|
||||||
|
fullscreen: true,
|
||||||
|
ios: {
|
||||||
|
statusBarStyle: 'dark',
|
||||||
|
},
|
||||||
|
closeCallback(args) {
|
||||||
|
// console.log('close modal callback', args);
|
||||||
|
},
|
||||||
|
} as ShowModalOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
apps/toolbox/src/pages/status-bar.xml
Normal file
11
apps/toolbox/src/pages/status-bar.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page" backgroundColor="black" statusBarStyle="light">
|
||||||
|
<!-- Note we set statusBarStyle="light" to explicitly contrast it against our black background -->
|
||||||
|
<Page.actionBar>
|
||||||
|
<ActionBar title="Status Bar" color="white">
|
||||||
|
</ActionBar>
|
||||||
|
</Page.actionBar>
|
||||||
|
<GridLayout rows="*,auto,auto,*">
|
||||||
|
<Label row="1" text="Note status bar color, then Open Modal" fontSize="12" class="text-center c-white" />
|
||||||
|
<Button row="2" text="Open Modal" tap="{{ onOpenModal }}" class="btn btn-primary btn-view-demo" marginTop="20" />
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
||||||
22
apps/toolbox/src/pages/status-bar/status-bar-modal.ts
Normal file
22
apps/toolbox/src/pages/status-bar/status-bar-modal.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Observable, ShownModallyData, LoadEventData, Page, ShowModalOptions } from '@nativescript/core';
|
||||||
|
|
||||||
|
let page: Page;
|
||||||
|
let closeCallback: Function;
|
||||||
|
export function onShownModally(args: ShownModallyData) {
|
||||||
|
closeCallback = args.closeCallback;
|
||||||
|
|
||||||
|
if (args.context) {
|
||||||
|
args.context.shownModally = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onLoaded(args: LoadEventData) {
|
||||||
|
page = args.object as Page;
|
||||||
|
page.bindingContext = new StatusBarModalPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StatusBarModalPage extends Observable {
|
||||||
|
close() {
|
||||||
|
closeCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
apps/toolbox/src/pages/status-bar/status-bar-modal.xml
Normal file
9
apps/toolbox/src/pages/status-bar/status-bar-modal.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoaded" shownModally="onShownModally" statusBarStyle="dark">
|
||||||
|
|
||||||
|
<GridLayout rows="auto,auto,auto,*" verticalAlignment="top" padding="20">
|
||||||
|
<Button text="Close" tap="{{close}}" horizontalAlignment="right" marginRight="20" />
|
||||||
|
|
||||||
|
<Label row="1" text="Status bar color changed to 'dark'." verticalAlignment="top" marginTop="20" class="text-center" fontSize="12" color="black" />
|
||||||
|
<Label row="2" text="Close and watch it change back." verticalAlignment="top" marginTop="20" class="text-center" fontSize="12" color="black" marginTop="10" />
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
||||||
2
packages/core/references.d.ts
vendored
2
packages/core/references.d.ts
vendored
@ -4,7 +4,7 @@
|
|||||||
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Darwin.d.ts" />
|
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Darwin.d.ts" />
|
||||||
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!DarwinFoundation.d.ts" />
|
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!DarwinFoundation.d.ts" />
|
||||||
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Symbols.d.ts" />
|
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Symbols.d.ts" />
|
||||||
/// <reference path="../types-android/src/lib/android-29.d.ts" />
|
/// <reference path="../types-android/src/lib/android-30.d.ts" />
|
||||||
/// <reference path="./platforms/ios/typings/objc!MaterialComponents.d.ts" />
|
/// <reference path="./platforms/ios/typings/objc!MaterialComponents.d.ts" />
|
||||||
/// <reference path="./platforms/ios/typings/objc!NativeScriptUtils.d.ts" />
|
/// <reference path="./platforms/ios/typings/objc!NativeScriptUtils.d.ts" />
|
||||||
/// <reference path="./global-types.d.ts" />
|
/// <reference path="./global-types.d.ts" />
|
||||||
|
|||||||
@ -79,6 +79,10 @@ export interface ShowModalOptions {
|
|||||||
* height of the popup dialog
|
* height of the popup dialog
|
||||||
*/
|
*/
|
||||||
height?: number;
|
height?: number;
|
||||||
|
/**
|
||||||
|
* The preferred status bar style for the modal view
|
||||||
|
*/
|
||||||
|
statusBarStyle?: 'light' | 'dark';
|
||||||
};
|
};
|
||||||
android?: {
|
android?: {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { Point, Position } from './view-interfaces';
|
import type { Point, Position } from './view-interfaces';
|
||||||
import type { GestureTypes, GestureEventData } from '../../gestures';
|
import type { GestureTypes, GestureEventData } from '../../gestures';
|
||||||
import { getNativeScriptGlobals } from '../../../globals/global-utils';
|
import { getNativeScriptGlobals } from '../../../globals/global-utils';
|
||||||
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, AndroidHelper } from './view-common';
|
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, AndroidHelper, statusBarStyleProperty } from './view-common';
|
||||||
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../../styling/style-properties';
|
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../../styling/style-properties';
|
||||||
import { Length } from '../../styling/length-shared';
|
import { Length } from '../../styling/length-shared';
|
||||||
import { layout } from '../../../utils';
|
import { layout } from '../../../utils';
|
||||||
@ -52,6 +52,10 @@ const GRAVITY_FILL_HORIZONTAL = 7; // android.view.Gravity.FILL_HORIZONTAL
|
|||||||
const GRAVITY_CENTER_VERTICAL = 16; // android.view.Gravity.CENTER_VERTICAL
|
const GRAVITY_CENTER_VERTICAL = 16; // android.view.Gravity.CENTER_VERTICAL
|
||||||
const GRAVITY_FILL_VERTICAL = 112; // android.view.Gravity.FILL_VERTICAL
|
const GRAVITY_FILL_VERTICAL = 112; // android.view.Gravity.FILL_VERTICAL
|
||||||
|
|
||||||
|
const SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
|
||||||
|
const STATUS_BAR_LIGHT_BCKG = -657931;
|
||||||
|
const STATUS_BAR_DARK_BCKG = 1711276032;
|
||||||
|
|
||||||
const modalMap = new Map<number, DialogOptions>();
|
const modalMap = new Map<number, DialogOptions>();
|
||||||
|
|
||||||
let TouchListener: TouchListener;
|
let TouchListener: TouchListener;
|
||||||
@ -920,6 +924,89 @@ export class View extends ViewCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[statusBarStyleProperty.getDefault]() {
|
||||||
|
return this.style.statusBarStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[statusBarStyleProperty.setNative](value: 'dark' | 'light' | { color: number; systemUiVisibility: number }) {
|
||||||
|
this.updateStatusBarStyle(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatusBarStyle(value: 'dark' | 'light' | { color: number; systemUiVisibility: number }) {
|
||||||
|
if (SDK_VERSION < 21) return; // nothing we can do
|
||||||
|
|
||||||
|
const window = this.getClosestWindow();
|
||||||
|
// Ensure the window draws system bar backgrounds (required to color status bar)
|
||||||
|
window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
|
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
|
|
||||||
|
const decorView = window.getDecorView();
|
||||||
|
|
||||||
|
// API 30+ path (preferred)
|
||||||
|
const controller = window.getInsetsController?.();
|
||||||
|
if (controller && SDK_VERSION >= 30) {
|
||||||
|
const APPEARANCE_LIGHT_STATUS_BARS = android.view.WindowInsetsController?.APPEARANCE_LIGHT_STATUS_BARS;
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
this.style.statusBarStyle = value;
|
||||||
|
if (value === 'light') {
|
||||||
|
// light icons/text
|
||||||
|
controller.setSystemBarsAppearance(0, APPEARANCE_LIGHT_STATUS_BARS);
|
||||||
|
} else {
|
||||||
|
// dark icons/text
|
||||||
|
controller.setSystemBarsAppearance(APPEARANCE_LIGHT_STATUS_BARS, APPEARANCE_LIGHT_STATUS_BARS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value.color != null) window.setStatusBarColor(value.color);
|
||||||
|
// No direct passthrough for systemUiVisibility on API 30+, use appearances instead
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API 23–29 path (systemUiVisibility)
|
||||||
|
if (SDK_VERSION >= 23) {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
this.style.statusBarStyle = value;
|
||||||
|
let flags = decorView.getSystemUiVisibility();
|
||||||
|
if (value === 'light') {
|
||||||
|
// Add the LIGHT_STATUS_BAR bit without clobbering other flags
|
||||||
|
flags |= android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
|
||||||
|
decorView.setSystemUiVisibility(flags);
|
||||||
|
} else {
|
||||||
|
// Remove only the LIGHT_STATUS_BAR bit
|
||||||
|
flags &= ~android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
|
||||||
|
decorView.setSystemUiVisibility(flags);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value.color != null) window.setStatusBarColor(value.color);
|
||||||
|
if (value.systemUiVisibility != null) {
|
||||||
|
// Preserve existing flags, don’t blindly overwrite to 0
|
||||||
|
const merged = (decorView.getSystemUiVisibility() & ~android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) | (value.systemUiVisibility & android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
|
decorView.setSystemUiVisibility(merged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API 21–22: you can only change the background color; icon color is fixed (light)
|
||||||
|
if (typeof value === 'object' && value.color != null) {
|
||||||
|
window.setStatusBarColor(value.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getClosestWindow(): android.view.Window {
|
||||||
|
// When it comes to modals, check parent as it may not be the modal root view itself
|
||||||
|
const view = this.parent ?? this;
|
||||||
|
const dialogFragment = (view as this)._dialogFragment;
|
||||||
|
if (dialogFragment) {
|
||||||
|
const dialog = dialogFragment.getDialog();
|
||||||
|
if (dialog) {
|
||||||
|
return dialog.getWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._context.getWindow();
|
||||||
|
}
|
||||||
|
|
||||||
[testIDProperty.setNative](value: string) {
|
[testIDProperty.setNative](value: string) {
|
||||||
this.setAccessibilityIdentifier(this.nativeViewProtected, value);
|
this.setAccessibilityIdentifier(this.nativeViewProtected, value);
|
||||||
}
|
}
|
||||||
|
|||||||
16
packages/core/ui/core/view/index.d.ts
vendored
16
packages/core/ui/core/view/index.d.ts
vendored
@ -631,6 +631,22 @@ export abstract class View extends ViewCommon {
|
|||||||
*/
|
*/
|
||||||
cssType: string;
|
cssType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets or sets the status bar style for this view.
|
||||||
|
* Platform Notes:
|
||||||
|
* - Android: When using this property throughout navigations, ensure starting views have it set as well. Ensures it will reset on back navigation.
|
||||||
|
* - iOS: You must remove Info.plist key `UIViewControllerBasedStatusBarAppearance`
|
||||||
|
* It defaults to true when not present: https://developer.apple.com/documentation/bundleresources/information-property-list/uiviewcontrollerbasedstatusbarappearance
|
||||||
|
* Or you can explicitly set it to true:
|
||||||
|
* <key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
* <true/>
|
||||||
|
*
|
||||||
|
* False value will make this property have no effect.
|
||||||
|
*
|
||||||
|
* @nsProperty
|
||||||
|
*/
|
||||||
|
statusBarStyle: 'light' | 'dark';
|
||||||
|
|
||||||
cssClasses: Set<string>;
|
cssClasses: Set<string>;
|
||||||
cssPseudoClasses: Set<string>;
|
cssPseudoClasses: Set<string>;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type { Point, Position } from './view-interfaces';
|
import type { Point, Position } from './view-interfaces';
|
||||||
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, iosGlassEffectProperty, GlassEffectType, GlassEffectVariant } from './view-common';
|
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, iosGlassEffectProperty, GlassEffectType, GlassEffectVariant, statusBarStyleProperty } from './view-common';
|
||||||
import { isAccessibilityServiceEnabled } from '../../../application';
|
import { isAccessibilityServiceEnabled } from '../../../application';
|
||||||
import { updateA11yPropertiesCallback } from '../../../application/helpers-common';
|
import { updateA11yPropertiesCallback } from '../../../application/helpers-common';
|
||||||
import { ShowModalOptions, hiddenProperty } from '../view-base';
|
import { ShowModalOptions, hiddenProperty } from '../view-base';
|
||||||
@ -560,7 +560,8 @@ export class View extends ViewCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.ios && options.ios.presentationStyle) {
|
if (options.ios) {
|
||||||
|
if (options.ios.presentationStyle) {
|
||||||
const presentationStyle = options.ios.presentationStyle;
|
const presentationStyle = options.ios.presentationStyle;
|
||||||
controller.modalPresentationStyle = presentationStyle;
|
controller.modalPresentationStyle = presentationStyle;
|
||||||
|
|
||||||
@ -568,6 +569,14 @@ export class View extends ViewCommon {
|
|||||||
this._setupPopoverControllerDelegate(controller, parent);
|
this._setupPopoverControllerDelegate(controller, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (options.ios.statusBarStyle) {
|
||||||
|
/**
|
||||||
|
* https://developer.apple.com/documentation/uikit/uiviewcontroller/modalpresentationcapturesstatusbarappearance
|
||||||
|
*/
|
||||||
|
controller.modalPresentationCapturesStatusBarAppearance = true;
|
||||||
|
this.statusBarStyle = options.ios.statusBarStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const cancelable = options.cancelable !== undefined ? !!options.cancelable : true;
|
const cancelable = options.cancelable !== undefined ? !!options.cancelable : true;
|
||||||
|
|
||||||
@ -895,6 +904,28 @@ export class View extends ViewCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[statusBarStyleProperty.getDefault]() {
|
||||||
|
return this.style.statusBarStyle;
|
||||||
|
}
|
||||||
|
[statusBarStyleProperty.setNative](value: 'light' | 'dark') {
|
||||||
|
this.style.statusBarStyle = value;
|
||||||
|
const parent = this.parent;
|
||||||
|
if (parent) {
|
||||||
|
const ctrl = parent.ios?.controller;
|
||||||
|
if (ctrl && ctrl instanceof UINavigationController) {
|
||||||
|
const navigationBar = ctrl.navigationBar;
|
||||||
|
if (!navigationBar) return;
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
console.log('here:', value);
|
||||||
|
navigationBar.barStyle = value === 'dark' ? UIBarStyle.Black : UIBarStyle.Default;
|
||||||
|
} else {
|
||||||
|
navigationBar.barStyle = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[iosGlassEffectProperty.setNative](value: GlassEffectType) {
|
[iosGlassEffectProperty.setNative](value: GlassEffectType) {
|
||||||
if (!this.nativeViewProtected || !supportsGlass()) {
|
if (!this.nativeViewProtected || !supportsGlass()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import { layout } from '../../../utils';
|
|||||||
import { isObject } from '../../../utils/types';
|
import { isObject } from '../../../utils/types';
|
||||||
import { sanitizeModuleName } from '../../../utils/common';
|
import { sanitizeModuleName } from '../../../utils/common';
|
||||||
import { Color } from '../../../color';
|
import { Color } from '../../../color';
|
||||||
import { Property, InheritedProperty } from '../properties';
|
import { Property, InheritedProperty, CssProperty } from '../properties';
|
||||||
|
import { Style } from '../../styling/style';
|
||||||
import { EventData } from '../../../data/observable';
|
import { EventData } from '../../../data/observable';
|
||||||
import { ViewHelper } from './view-helper';
|
import { ViewHelper } from './view-helper';
|
||||||
import { setupAccessibleView } from '../../../application/helpers';
|
import { setupAccessibleView } from '../../../application/helpers';
|
||||||
@ -193,6 +194,12 @@ export abstract class ViewCommon extends ViewBase {
|
|||||||
super.onLoaded();
|
super.onLoaded();
|
||||||
|
|
||||||
setupAccessibleView(this);
|
setupAccessibleView(this);
|
||||||
|
|
||||||
|
if (this.statusBarStyle) {
|
||||||
|
// reapply status bar style on load
|
||||||
|
// helps back navigation cases to restore if overridden
|
||||||
|
this.updateStatusBarStyle(this.statusBarStyle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public _closeAllModalViewsInternal(): boolean {
|
public _closeAllModalViewsInternal(): boolean {
|
||||||
@ -970,6 +977,14 @@ export abstract class ViewCommon extends ViewBase {
|
|||||||
this.style.androidDynamicElevationOffset = value;
|
this.style.androidDynamicElevationOffset = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Android only) Gets closest window parent considering modals.
|
||||||
|
*/
|
||||||
|
getClosestWindow(): android.view.Window {
|
||||||
|
// platform impl
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
//END Style property shortcuts
|
//END Style property shortcuts
|
||||||
|
|
||||||
public originX: number;
|
public originX: number;
|
||||||
@ -995,6 +1010,17 @@ export abstract class ViewCommon extends ViewBase {
|
|||||||
this._cssType = type.toLowerCase();
|
this._cssType = type.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get statusBarStyle(): 'light' | 'dark' {
|
||||||
|
return this.style.statusBarStyle;
|
||||||
|
}
|
||||||
|
set statusBarStyle(value: 'light' | 'dark') {
|
||||||
|
this.style.statusBarStyle = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatusBarStyle(value: 'dark' | 'light') {
|
||||||
|
// platform specific impl
|
||||||
|
}
|
||||||
|
|
||||||
get isLayoutRequired(): boolean {
|
get isLayoutRequired(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1288,6 +1314,15 @@ export const isUserInteractionEnabledProperty = new Property<ViewCommon, boolean
|
|||||||
});
|
});
|
||||||
isUserInteractionEnabledProperty.register(ViewCommon);
|
isUserInteractionEnabledProperty.register(ViewCommon);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property backing statusBarStyle.
|
||||||
|
*/
|
||||||
|
export const statusBarStyleProperty = new CssProperty<Style, 'light' | 'dark'>({
|
||||||
|
name: 'statusBarStyle',
|
||||||
|
cssName: 'status-bar-style',
|
||||||
|
});
|
||||||
|
statusBarStyleProperty.register(Style);
|
||||||
|
|
||||||
// Apple only
|
// Apple only
|
||||||
export const iosOverflowSafeAreaProperty = new Property<ViewCommon, boolean>({
|
export const iosOverflowSafeAreaProperty = new Property<ViewCommon, boolean>({
|
||||||
name: 'iosOverflowSafeArea',
|
name: 'iosOverflowSafeArea',
|
||||||
|
|||||||
@ -127,6 +127,20 @@ class UILayoutViewController extends UIViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
public get preferredStatusBarStyle(): UIStatusBarStyle {
|
||||||
|
const owner = this.owner?.deref();
|
||||||
|
if (owner) {
|
||||||
|
if (SDK_VERSION >= 13) {
|
||||||
|
return owner.statusBarStyle === 'dark' ? UIStatusBarStyle.DarkContent : UIStatusBarStyle.LightContent;
|
||||||
|
} else {
|
||||||
|
return owner.statusBarStyle === 'dark' ? UIStatusBarStyle.LightContent : UIStatusBarStyle.Default;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return UIStatusBarStyle.Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NativeClass
|
@NativeClass
|
||||||
|
|||||||
@ -634,6 +634,11 @@ class UINavigationControllerImpl extends UINavigationController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
public get childViewControllerForStatusBarStyle() {
|
||||||
|
return this.topViewController;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getTransitionId(nativeTransition: UIViewAnimationTransition, transitionType: string): string {
|
function _getTransitionId(nativeTransition: UIViewAnimationTransition, transitionType: string): string {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { isAccessibilityServiceEnabled } from '../../application';
|
import { isAccessibilityServiceEnabled } from '../../application';
|
||||||
import { PageBase, actionBarHiddenProperty, statusBarStyleProperty, androidStatusBarBackgroundProperty } from './page-common';
|
import { PageBase, actionBarHiddenProperty, androidStatusBarBackgroundProperty } from './page-common';
|
||||||
import { View } from '../core/view';
|
import { View } from '../core/view';
|
||||||
import { Color } from '../../color';
|
import { Color } from '../../color';
|
||||||
import { ActionBar } from '../action-bar';
|
import { ActionBar } from '../action-bar';
|
||||||
@ -10,10 +10,6 @@ import { AndroidAccessibilityEvent, getLastFocusedViewOnPage } from '../../acces
|
|||||||
|
|
||||||
export * from './page-common';
|
export * from './page-common';
|
||||||
|
|
||||||
const SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
|
|
||||||
const STATUS_BAR_LIGHT_BCKG = -657931;
|
|
||||||
const STATUS_BAR_DARK_BCKG = 1711276032;
|
|
||||||
|
|
||||||
export class Page extends PageBase {
|
export class Page extends PageBase {
|
||||||
nativeViewProtected: org.nativescript.widgets.GridLayout;
|
nativeViewProtected: org.nativescript.widgets.GridLayout;
|
||||||
|
|
||||||
@ -69,19 +65,6 @@ export class Page extends PageBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getClosestWindow() {
|
|
||||||
// When it comes to modals, check if page has a parent as it may not be the modal root view itself
|
|
||||||
const view = this.parent ?? this;
|
|
||||||
const dialogFragment = (<any>view)._dialogFragment;
|
|
||||||
if (dialogFragment) {
|
|
||||||
const dialog = dialogFragment.getDialog();
|
|
||||||
if (dialog) {
|
|
||||||
return dialog.getWindow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._context.getWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
[actionBarHiddenProperty.setNative](value: boolean) {
|
[actionBarHiddenProperty.setNative](value: boolean) {
|
||||||
// in case the actionBar is not created and actionBarHidden is changed to true
|
// in case the actionBar is not created and actionBarHidden is changed to true
|
||||||
// the actionBar will be created by updateActionBar
|
// the actionBar will be created by updateActionBar
|
||||||
@ -90,44 +73,10 @@ export class Page extends PageBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[statusBarStyleProperty.getDefault](): {
|
|
||||||
color: number;
|
|
||||||
systemUiVisibility: number;
|
|
||||||
} {
|
|
||||||
if (SDK_VERSION >= 21) {
|
|
||||||
const window = this.getClosestWindow();
|
|
||||||
const decorView = window.getDecorView();
|
|
||||||
|
|
||||||
return {
|
|
||||||
color: (<any>window).getStatusBarColor(),
|
|
||||||
systemUiVisibility: decorView.getSystemUiVisibility(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
[statusBarStyleProperty.setNative](value: 'dark' | 'light' | { color: number; systemUiVisibility: number }) {
|
|
||||||
if (SDK_VERSION >= 21) {
|
|
||||||
const window = this.getClosestWindow();
|
|
||||||
const decorView = window.getDecorView();
|
|
||||||
|
|
||||||
if (value === 'light') {
|
|
||||||
(<any>window).setStatusBarColor(STATUS_BAR_LIGHT_BCKG);
|
|
||||||
decorView.setSystemUiVisibility(SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
|
||||||
} else if (value === 'dark') {
|
|
||||||
(<any>window).setStatusBarColor(STATUS_BAR_DARK_BCKG);
|
|
||||||
decorView.setSystemUiVisibility(0);
|
|
||||||
} else {
|
|
||||||
(<any>window).setStatusBarColor(value.color);
|
|
||||||
decorView.setSystemUiVisibility(value.systemUiVisibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[androidStatusBarBackgroundProperty.getDefault](): number {
|
[androidStatusBarBackgroundProperty.getDefault](): number {
|
||||||
if (SDK_VERSION >= 21) {
|
if (SDK_VERSION >= 21) {
|
||||||
const window = this.getClosestWindow();
|
const window = this.getClosestWindow();
|
||||||
return (<any>window).getStatusBarColor();
|
return window.getStatusBarColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -136,7 +85,7 @@ export class Page extends PageBase {
|
|||||||
if (SDK_VERSION >= 21) {
|
if (SDK_VERSION >= 21) {
|
||||||
const window = this.getClosestWindow();
|
const window = this.getClosestWindow();
|
||||||
const color = value instanceof Color ? value.android : value;
|
const color = value instanceof Color ? value.android : value;
|
||||||
(<any>window).setStatusBarColor(color);
|
window.setStatusBarColor(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
packages/core/ui/page/index.d.ts
vendored
8
packages/core/ui/page/index.d.ts
vendored
@ -65,14 +65,6 @@ export declare class Page extends PageBase {
|
|||||||
*/
|
*/
|
||||||
public backgroundSpanUnderStatusBar: boolean;
|
public backgroundSpanUnderStatusBar: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets or sets the style of the status bar.
|
|
||||||
*
|
|
||||||
* @nsProperty
|
|
||||||
*/
|
|
||||||
// @ts-ignore
|
|
||||||
public statusBarStyle: 'light' | 'dark';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or sets the color of the status bar in Android.
|
* Gets or sets the color of the status bar in Android.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { isAccessibilityServiceEnabled } from '../../application';
|
|||||||
import type { Frame } from '../frame';
|
import type { Frame } from '../frame';
|
||||||
import { BackstackEntry, NavigationType } from '../frame/frame-interfaces';
|
import { BackstackEntry, NavigationType } from '../frame/frame-interfaces';
|
||||||
import { View, IOSHelper } from '../core/view';
|
import { View, IOSHelper } from '../core/view';
|
||||||
import { PageBase, actionBarHiddenProperty, statusBarStyleProperty } from './page-common';
|
import { PageBase, actionBarHiddenProperty } from './page-common';
|
||||||
|
|
||||||
import { profile } from '../../profiling';
|
import { profile } from '../../profiling';
|
||||||
import { layout } from '../../utils/layout-helper';
|
import { layout } from '../../utils/layout-helper';
|
||||||
@ -349,7 +349,11 @@ class UIViewControllerImpl extends UIViewController {
|
|||||||
public get preferredStatusBarStyle(): UIStatusBarStyle {
|
public get preferredStatusBarStyle(): UIStatusBarStyle {
|
||||||
const owner = this._owner?.deref();
|
const owner = this._owner?.deref();
|
||||||
if (owner) {
|
if (owner) {
|
||||||
|
if (SDK_VERSION >= 13) {
|
||||||
|
return owner.statusBarStyle === 'light' ? UIStatusBarStyle.LightContent : UIStatusBarStyle.DarkContent;
|
||||||
|
} else {
|
||||||
return owner.statusBarStyle === 'dark' ? UIStatusBarStyle.LightContent : UIStatusBarStyle.Default;
|
return owner.statusBarStyle === 'dark' ? UIStatusBarStyle.LightContent : UIStatusBarStyle.Default;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return UIStatusBarStyle.Default;
|
return UIStatusBarStyle.Default;
|
||||||
}
|
}
|
||||||
@ -557,21 +561,6 @@ export class Page extends PageBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[statusBarStyleProperty.getDefault](): UIBarStyle {
|
|
||||||
return UIBarStyle.Default;
|
|
||||||
}
|
|
||||||
[statusBarStyleProperty.setNative](value: string | UIBarStyle) {
|
|
||||||
const frame = this.frame;
|
|
||||||
if (frame) {
|
|
||||||
const navigationBar = (<UINavigationController>frame.ios.controller).navigationBar;
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
navigationBar.barStyle = value === 'dark' ? UIBarStyle.Black : UIBarStyle.Default;
|
|
||||||
} else {
|
|
||||||
navigationBar.barStyle = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public accessibilityScreenChanged(refocus = false): void {
|
public accessibilityScreenChanged(refocus = false): void {
|
||||||
if (!isAccessibilityServiceEnabled()) {
|
if (!isAccessibilityServiceEnabled()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -63,13 +63,6 @@ export class PageBase extends ContentView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get statusBarStyle(): 'light' | 'dark' {
|
|
||||||
return this.style.statusBarStyle;
|
|
||||||
}
|
|
||||||
set statusBarStyle(value: 'light' | 'dark') {
|
|
||||||
this.style.statusBarStyle = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get androidStatusBarBackground(): Color {
|
public get androidStatusBarBackground(): Color {
|
||||||
return this.style.androidStatusBarBackground;
|
return this.style.androidStatusBarBackground;
|
||||||
}
|
}
|
||||||
@ -214,15 +207,6 @@ export const enableSwipeBackNavigationProperty = new Property<PageBase, boolean>
|
|||||||
});
|
});
|
||||||
enableSwipeBackNavigationProperty.register(PageBase);
|
enableSwipeBackNavigationProperty.register(PageBase);
|
||||||
|
|
||||||
/**
|
|
||||||
* Property backing statusBarStyle.
|
|
||||||
*/
|
|
||||||
export const statusBarStyleProperty = new CssProperty<Style, 'light' | 'dark'>({
|
|
||||||
name: 'statusBarStyle',
|
|
||||||
cssName: 'status-bar-style',
|
|
||||||
});
|
|
||||||
statusBarStyleProperty.register(Style);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property backing androidStatusBarBackground.
|
* Property backing androidStatusBarBackground.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user