mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(switch): :checked pseudo and color fixes (#9790)
This commit is contained in:
committed by
Nathan Walker
parent
716b831523
commit
6437352fed
@@ -201,4 +201,24 @@ Button {
|
|||||||
|
|
||||||
.a11y-demo-page .a11y-state-checked {
|
.a11y-demo-page .a11y-state-checked {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -6,15 +6,16 @@
|
|||||||
<StackLayout class="p-20">
|
<StackLayout class="p-20">
|
||||||
<ScrollView class="h-full">
|
<ScrollView class="h-full">
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Button text="list-page" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
|
||||||
<Button text="box-shadow" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
|
||||||
<Button text="root-layout" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
|
||||||
<Button text="a11y" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="a11y" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
|
<Button text="box-shadow" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="css-playground" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="css-playground" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="visibility-vs-hidden" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
|
||||||
<Button text="image-async" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
<Button text="image-async" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
<Button text="vector-image" 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="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="vector-image" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
|
<Button text="visibility-vs-hidden" tap="{{ viewDemo }}" class="btn btn-primary btn-view-demo" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|||||||
14
apps/toolbox/src/pages/switch.ts
Normal file
14
apps/toolbox/src/pages/switch.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Observable, EventData, Page } from '@nativescript/core';
|
||||||
|
|
||||||
|
let page: Page;
|
||||||
|
|
||||||
|
export function navigatingTo(args: EventData) {
|
||||||
|
page = <Page>args.object;
|
||||||
|
page.bindingContext = new SwitchModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SwitchModel extends Observable {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
75
apps/toolbox/src/pages/switch.xml
Normal file
75
apps/toolbox/src/pages/switch.xml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
|
||||||
|
<Page.actionBar>
|
||||||
|
<ActionBar title="Switch" icon="" class="action-bar">
|
||||||
|
</ActionBar>
|
||||||
|
</Page.actionBar>
|
||||||
|
|
||||||
|
<GridLayout padding="20" class="switch-demo-page">
|
||||||
|
<ScrollView>
|
||||||
|
<StackLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Default + Checked + Enabled" />
|
||||||
|
<Switch checked="true" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Default + UnChecked + Enabled" />
|
||||||
|
<Switch checked="false" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Default + Checked + Disabled" />
|
||||||
|
<Switch checked="true" isEnabled="false" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Default + UnChecked + Disabled" />
|
||||||
|
<Switch checked="false" isEnabled="false" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + Checked + Enabled" />
|
||||||
|
<Switch class="custom-switch" checked="true" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + UnChecked + Enabled" />
|
||||||
|
<Switch class="custom-switch" checked="false" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + Checked + Disabled" />
|
||||||
|
<Switch class="custom-switch" checked="true" isEnabled="false" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + UnChecked + Disabled" />
|
||||||
|
<Switch class="custom-switch" checked="false" isEnabled="false" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + Checked + Enabled + offBgColor" />
|
||||||
|
<Switch class="custom-switch" checked="true" backgroundColor="blue" offBackgroundColor="red" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + UnChecked + Enabled + offBgColor" />
|
||||||
|
<Switch class="custom-switch" checked="false" offBackgroundColor="red" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + Checked + Disabled + offBgColor" />
|
||||||
|
<Switch class="custom-switch" checked="true" isEnabled="false" offBackgroundColor="red" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<GridLayout columns="*, auto" marginTop="24">
|
||||||
|
<Label text="Custom + UnChecked + Disabled + offBgColor" />
|
||||||
|
<Switch class="custom-switch" checked="false" isEnabled="false" offBackgroundColor="red" col="1" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
</StackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
||||||
@@ -58,13 +58,16 @@ export class Switch extends SwitchBase {
|
|||||||
|
|
||||||
private setNativeBackgroundColor(value: string | number | Color) {
|
private setNativeBackgroundColor(value: string | number | Color) {
|
||||||
if (value instanceof 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 {
|
} else {
|
||||||
this.nativeViewProtected.getTrackDrawable().clearColorFilter();
|
this.nativeViewProtected.getTrackDrawable().clearColorFilter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onCheckedPropertyChanged(newValue: boolean) {
|
_onCheckedPropertyChanged(newValue: boolean) {
|
||||||
|
super._onCheckedPropertyChanged(newValue);
|
||||||
|
|
||||||
if (this.offBackgroundColor) {
|
if (this.offBackgroundColor) {
|
||||||
if (!newValue) {
|
if (!newValue) {
|
||||||
this.setNativeBackgroundColor(this.offBackgroundColor);
|
this.setNativeBackgroundColor(this.offBackgroundColor);
|
||||||
@@ -86,7 +89,8 @@ export class Switch extends SwitchBase {
|
|||||||
}
|
}
|
||||||
[colorProperty.setNative](value: number | Color) {
|
[colorProperty.setNative](value: number | Color) {
|
||||||
if (value instanceof 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 {
|
} else {
|
||||||
this.nativeViewProtected.getThumbDrawable().clearColorFilter();
|
this.nativeViewProtected.getThumbDrawable().clearColorFilter();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { SwitchBase, checkedProperty, offBackgroundColorProperty } from './switch-common';
|
import { SwitchBase, checkedProperty, offBackgroundColorProperty } from './switch-common';
|
||||||
import { colorProperty, backgroundColorProperty, backgroundInternalProperty } from '../styling/style-properties';
|
import { colorProperty, backgroundColorProperty, backgroundInternalProperty } from '../styling/style-properties';
|
||||||
import { Color } from '../../color';
|
import { Color } from '../../color';
|
||||||
import { layout } from '../../utils';
|
import { iOSNativeHelper, layout } from '../../utils';
|
||||||
|
|
||||||
export * from './switch-common';
|
export * from './switch-common';
|
||||||
|
|
||||||
|
const majorVersion = iOSNativeHelper.MajorVersion;
|
||||||
|
|
||||||
@NativeClass
|
@NativeClass
|
||||||
class SwitchChangeHandlerImpl extends NSObject {
|
class SwitchChangeHandlerImpl extends NSObject {
|
||||||
private _owner: WeakRef<Switch>;
|
private _owner: WeakRef<Switch>;
|
||||||
@@ -55,6 +57,37 @@ export class Switch extends SwitchBase {
|
|||||||
super.disposeNativeView();
|
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
|
// @ts-ignore
|
||||||
get ios(): UISwitch {
|
get ios(): UISwitch {
|
||||||
return this.nativeViewProtected;
|
return this.nativeViewProtected;
|
||||||
@@ -82,14 +115,29 @@ export class Switch extends SwitchBase {
|
|||||||
return this.nativeViewProtected.thumbTintColor;
|
return this.nativeViewProtected.thumbTintColor;
|
||||||
}
|
}
|
||||||
[colorProperty.setNative](value: UIColor | Color) {
|
[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 {
|
[backgroundColorProperty.getDefault](): UIColor {
|
||||||
return this.nativeViewProtected.onTintColor;
|
return this.nativeViewProtected.onTintColor;
|
||||||
}
|
}
|
||||||
[backgroundColorProperty.setNative](value: UIColor | Color) {
|
[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 {
|
[backgroundInternalProperty.getDefault](): any {
|
||||||
@@ -103,10 +151,17 @@ export class Switch extends SwitchBase {
|
|||||||
return this.nativeViewProtected.backgroundColor;
|
return this.nativeViewProtected.backgroundColor;
|
||||||
}
|
}
|
||||||
[offBackgroundColorProperty.setNative](value: Color | UIColor) {
|
[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.tintColor = nativeValue;
|
||||||
this.nativeViewProtected.backgroundColor = nativeValue;
|
this.nativeViewProtected.backgroundColor = nativeValue;
|
||||||
this.nativeViewProtected.layer.cornerRadius = this.nativeViewProtected.frame.size.height / 2;
|
this.nativeViewProtected.layer.cornerRadius = this.nativeViewProtected.frame.size.height / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ export class SwitchBase extends View implements SwitchDefinition {
|
|||||||
public offBackgroundColor: Color;
|
public offBackgroundColor: Color;
|
||||||
|
|
||||||
_onCheckedPropertyChanged(newValue: boolean) {
|
_onCheckedPropertyChanged(newValue: boolean) {
|
||||||
//
|
if (newValue) {
|
||||||
|
this.addPseudoClass('checked');
|
||||||
|
} else {
|
||||||
|
this.deletePseudoClass('checked');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user