diff --git a/apps/toolbox/src/app.css b/apps/toolbox/src/app.css
index 8589cefaa..0e77e788e 100644
--- a/apps/toolbox/src/app.css
+++ b/apps/toolbox/src/app.css
@@ -201,4 +201,24 @@ Button {
.a11y-demo-page .a11y-state-checked {
a11y-state: checked;
+}
+
+.switch-demo-page Switch.custom-switch {
+ color: #ddd;
+ background-color: #65adf1;
+}
+
+.switch-demo-page Switch.custom-switch:checked {
+ color: #111;
+ background-color: #65adf1;
+}
+
+.switch-demo-page Switch.custom-switch:disabled {
+ color: #777;
+ background-color: #ddd;
+}
+
+.switch-demo-page Switch.custom-switch:disabled:checked {
+ color: #ddd;
+ background-color: #777;
}
\ No newline at end of file
diff --git a/apps/toolbox/src/main-page.xml b/apps/toolbox/src/main-page.xml
index 667e9e9a5..34a1d1a22 100644
--- a/apps/toolbox/src/main-page.xml
+++ b/apps/toolbox/src/main-page.xml
@@ -6,15 +6,16 @@
-
-
-
+
-
-
+
+
+
+
+
diff --git a/apps/toolbox/src/pages/switch.ts b/apps/toolbox/src/pages/switch.ts
new file mode 100644
index 000000000..22b45bdb1
--- /dev/null
+++ b/apps/toolbox/src/pages/switch.ts
@@ -0,0 +1,14 @@
+import { Observable, EventData, Page } from '@nativescript/core';
+
+let page: Page;
+
+export function navigatingTo(args: EventData) {
+ page = args.object;
+ page.bindingContext = new SwitchModel();
+}
+
+export class SwitchModel extends Observable {
+ constructor() {
+ super();
+ }
+}
diff --git a/apps/toolbox/src/pages/switch.xml b/apps/toolbox/src/pages/switch.xml
new file mode 100644
index 000000000..232c598ad
--- /dev/null
+++ b/apps/toolbox/src/pages/switch.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/core/ui/switch/index.android.ts b/packages/core/ui/switch/index.android.ts
index a5671b0c2..f57169c93 100644
--- a/packages/core/ui/switch/index.android.ts
+++ b/packages/core/ui/switch/index.android.ts
@@ -58,13 +58,16 @@ export class Switch extends SwitchBase {
private setNativeBackgroundColor(value: string | number | Color) {
if (value instanceof Color) {
- this.nativeViewProtected.getTrackDrawable().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_IN);
+ // todo: use https://developer.android.com/reference/androidx/core/graphics/BlendModeColorFilterCompat
+ this.nativeViewProtected.getTrackDrawable().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_OVER);
} else {
this.nativeViewProtected.getTrackDrawable().clearColorFilter();
}
}
_onCheckedPropertyChanged(newValue: boolean) {
+ super._onCheckedPropertyChanged(newValue);
+
if (this.offBackgroundColor) {
if (!newValue) {
this.setNativeBackgroundColor(this.offBackgroundColor);
@@ -86,7 +89,8 @@ export class Switch extends SwitchBase {
}
[colorProperty.setNative](value: number | Color) {
if (value instanceof Color) {
- this.nativeViewProtected.getThumbDrawable().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_IN);
+ // todo: use https://developer.android.com/reference/androidx/core/graphics/BlendModeColorFilterCompat
+ this.nativeViewProtected.getThumbDrawable().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_ATOP);
} else {
this.nativeViewProtected.getThumbDrawable().clearColorFilter();
}
diff --git a/packages/core/ui/switch/index.ios.ts b/packages/core/ui/switch/index.ios.ts
index dcb9b2525..0841d7617 100644
--- a/packages/core/ui/switch/index.ios.ts
+++ b/packages/core/ui/switch/index.ios.ts
@@ -1,10 +1,12 @@
import { SwitchBase, checkedProperty, offBackgroundColorProperty } from './switch-common';
import { colorProperty, backgroundColorProperty, backgroundInternalProperty } from '../styling/style-properties';
import { Color } from '../../color';
-import { layout } from '../../utils';
+import { iOSNativeHelper, layout } from '../../utils';
export * from './switch-common';
+const majorVersion = iOSNativeHelper.MajorVersion;
+
@NativeClass
class SwitchChangeHandlerImpl extends NSObject {
private _owner: WeakRef;
@@ -55,6 +57,37 @@ export class Switch extends SwitchBase {
super.disposeNativeView();
}
+ private setNativeBackgroundColor(value: UIColor | Color) {
+ if (value) {
+ this.nativeViewProtected.onTintColor = value instanceof Color ? value.ios : value;
+ this.nativeViewProtected.tintColor = value instanceof Color ? value.ios : value;
+ this.nativeViewProtected.backgroundColor = value instanceof Color ? value.ios : value;
+ this.nativeViewProtected.layer.cornerRadius = this.nativeViewProtected.frame.size.height / 2;
+ } else {
+ this.nativeViewProtected.onTintColor = null;
+ this.nativeViewProtected.tintColor = null;
+ this.nativeViewProtected.backgroundColor = null;
+ this.nativeViewProtected.layer.cornerRadius = 0;
+ }
+ }
+
+ _onCheckedPropertyChanged(newValue: boolean) {
+ // only add :checked pseudo handling on supported iOS versions
+ // ios <13 works but causes glitchy animations when toggling
+ // so we decided to keep the old behavior on older versions.
+ if (majorVersion >= 13) {
+ super._onCheckedPropertyChanged(newValue);
+
+ if (this.offBackgroundColor) {
+ if (!newValue) {
+ this.setNativeBackgroundColor(this.offBackgroundColor);
+ } else {
+ this.setNativeBackgroundColor(this.backgroundColor instanceof Color ? this.backgroundColor : new Color(this.backgroundColor));
+ }
+ }
+ }
+ }
+
// @ts-ignore
get ios(): UISwitch {
return this.nativeViewProtected;
@@ -82,14 +115,29 @@ export class Switch extends SwitchBase {
return this.nativeViewProtected.thumbTintColor;
}
[colorProperty.setNative](value: UIColor | Color) {
- this.nativeViewProtected.thumbTintColor = value instanceof Color ? value.ios : value;
+ const color: UIColor = value instanceof Color ? value.ios : value;
+ this.nativeViewProtected.thumbTintColor = color;
+
+ if (color && this.nativeViewProtected.subviews.count > 0) {
+ const alpha = new interop.Reference(1.0);
+ const res = color.getRedGreenBlueAlpha(null, null, null, alpha);
+
+ this.nativeViewProtected.subviews[0].alpha = (res && alpha.value) ?? 1;
+ }
}
[backgroundColorProperty.getDefault](): UIColor {
return this.nativeViewProtected.onTintColor;
}
[backgroundColorProperty.setNative](value: UIColor | Color) {
- this.nativeViewProtected.onTintColor = value instanceof Color ? value.ios : value;
+ if (majorVersion >= 13) {
+ if (!this.offBackgroundColor || this.checked) {
+ this.setNativeBackgroundColor(value);
+ }
+ } else {
+ // old behavior on unsupported iOS versions
+ this.nativeViewProtected.onTintColor = value instanceof Color ? value.ios : value;
+ }
}
[backgroundInternalProperty.getDefault](): any {
@@ -103,10 +151,17 @@ export class Switch extends SwitchBase {
return this.nativeViewProtected.backgroundColor;
}
[offBackgroundColorProperty.setNative](value: Color | UIColor) {
- const nativeValue = value instanceof Color ? value.ios : value;
+ if (majorVersion >= 13) {
+ if (!this.checked) {
+ this.setNativeBackgroundColor(value);
+ }
+ } else {
+ // old behavior on unsupported iOS versions...
+ const nativeValue = value instanceof Color ? value.ios : value;
- this.nativeViewProtected.tintColor = nativeValue;
- this.nativeViewProtected.backgroundColor = nativeValue;
- this.nativeViewProtected.layer.cornerRadius = this.nativeViewProtected.frame.size.height / 2;
+ this.nativeViewProtected.tintColor = nativeValue;
+ this.nativeViewProtected.backgroundColor = nativeValue;
+ this.nativeViewProtected.layer.cornerRadius = this.nativeViewProtected.frame.size.height / 2;
+ }
}
}
diff --git a/packages/core/ui/switch/switch-common.ts b/packages/core/ui/switch/switch-common.ts
index b4484be6a..3fc1c7af8 100644
--- a/packages/core/ui/switch/switch-common.ts
+++ b/packages/core/ui/switch/switch-common.ts
@@ -12,7 +12,11 @@ export class SwitchBase extends View implements SwitchDefinition {
public offBackgroundColor: Color;
_onCheckedPropertyChanged(newValue: boolean) {
- //
+ if (newValue) {
+ this.addPseudoClass('checked');
+ } else {
+ this.deletePseudoClass('checked');
+ }
}
}