feat(core): box shadow demo (#9182)

This commit is contained in:
William Tjondrosuharto
2021-01-30 07:28:07 +07:00
committed by Nathan Walker
parent b745e0c5d4
commit ad92ba567f
9 changed files with 620 additions and 281 deletions

View File

@ -5,17 +5,79 @@
The following CSS rule changes the font size of all UI
components that have the btn class name.
*/
.btn {
.btn-view-demo {
font-size: 18;
/* box-shadow: -5 -5 10 10 navy; */
box-shadow: -5 -5 rgba(0,0,0,0.5);
background-color: #add8e6;
color: navy;
/* TODO: adding border radius breaks shadow */
/* border-radius: 10; */
background-color: #65ADF1;
border-radius: 5;
font-size: 17;
padding: 15;
font-weight: bold;
}
.bold{
font-weight: bold;
}
.controls Label {
font-size: 20;
font-weight: bold;
color: #333;
margin-top: 10;
}
.controls Button {
padding: 10 15;
margin: 5;
font-size: 17;
font-weight: bold;
color: #65ADF1;
border-radius: 5;
border-width: 1;
border-color: #65ADF1;
}
.box-shadow-demo .demo-component {
font-size: 20;
font-weight: bold;
color: #555;
border-color: #555;
margin: 10;
padding: 20 25;
text-transform: uppercase;
}
.box-shadow-demo .box-shadow-prop-controls {
padding: 10;
color: #333;
font-size: 17;
}
.box-shadow-demo .box-shadow-prop-controls TextField{
margin-left: 10;
padding: 5;
border-bottom-width: 1;
border-color: #65ADF1;
}
.box-shadow-demo .controls .description {
font-size: 15;
font-weight: normal;
color: #333;
margin-bottom: 10;
}
.box-shadow-demo .controls Button[selectedAttr=true] {
background-color: #65ADF1;
color: #fff;
}
.box-shadow-prop-controls .btn-apply {
background-color: #65ADF1;
color: #fff;
padding: 10 15;
border-radius: 4;
margin-left: 10;
font-size: 17;
font-weight: bold;
}

View File

@ -0,0 +1,177 @@
import { Observable } from '@nativescript/core';
import { EventData, Page } from '@nativescript/core';
export function navigatingTo(args: EventData) {
const page = <Page>args.object;
page.bindingContext = new BoxShadowModel();
}
export class BoxShadowModel extends Observable {
private _selectedComponentType: string;
private _selectedBackgroundType: string;
private _selectedBorderType: string;
private _selectedAnimation: string;
private _boxShadow: string;
background: string;
borderWidth: number;
borderRadius: number;
appliedBoxShadow: string;
constructor() {
super();
}
get selectedComponentType(): string {
return this._selectedComponentType;
}
set selectedComponentType(value: string) {
if (this._selectedComponentType !== value) {
this._selectedComponentType = value;
this.notifyPropertyChange('selectedComponentType', value);
}
}
get selectedBackgroundType(): string {
return this._selectedBackgroundType;
}
set selectedBackgroundType(value: string) {
if (this._selectedBackgroundType !== value) {
this._selectedBackgroundType = value;
this.notifyPropertyChange('selectedBackgroundType', value);
switch (value) {
case 'solid':
this.background = '#65ADF1';
break;
case 'gradient':
this.background = 'linear-gradient(to top, #65ADF1, white)';
break;
case 'transparent':
this.background = 'transparent';
break;
default:
break;
}
this.notifyPropertyChange('background', this.background);
}
}
get selectedBorderType(): string {
return this._selectedBorderType;
}
set selectedBorderType(value: string) {
this._selectedBorderType = value;
this.notifyPropertyChange('selectedBorderType', value);
switch (value) {
case 'solid':
this.borderWidth = this.borderWidth ? 0 : 2;
break;
case 'rounded':
this.borderRadius = this.borderRadius ? 0 : 10;
break;
case 'none':
this.borderRadius = 0;
this.borderWidth = 0;
break;
default:
break;
}
this.notifyPropertyChange('borderRadius', this.borderRadius);
this.notifyPropertyChange('borderWidth', this.borderWidth);
}
selectComponentType(args): void {
this.selectedComponentType = args.object.componentType;
}
selectBackgroundType(args): void {
this.selectedBackgroundType = args.object.backgroundType;
}
selectBorderType(args): void {
this.selectedBorderType = args.object.borderType;
}
selectAnimationType(args): void {
this._selectedAnimation = args.object.animationType;
}
applyBoxShadow(): void {
if (!this._boxShadow) {
this._boxShadow = '';
}
this.appliedBoxShadow = this._boxShadow;
this.notifyPropertyChange('appliedBoxShadow', this.appliedBoxShadow);
// TODO: this is a workaround to apply shadow immediately,
// since the box-shadow logic is currently inside background.ts
this.notifyPropertyChange('background', '');
this.notifyPropertyChange('background', this.background);
}
textChange(args): void {
this._boxShadow = args.object.text;
}
toggleAnimation(args) {
const view = args.object;
const animationDuration = 500;
if (this._selectedAnimation === 'width') {
const originalWidth = args.object.getActualSize().width;
view
.animate({
width: originalWidth / 2,
duration: animationDuration,
})
.then(() =>
view.animate({
width: originalWidth,
duration: animationDuration,
})
)
.catch((err) => {
console.error('animation error', err);
});
} else if (this._selectedAnimation === 'height') {
const originalHeight = args.object.getActualSize().height;
view
.animate({
height: originalHeight / 2,
duration: animationDuration,
})
.then(() =>
view.animate({
height: originalHeight,
duration: animationDuration,
})
)
.catch((err) => {
console.error('animation error', err);
});
} else {
view
.animate({
opacity: this._selectedAnimation === 'opacity' ? 0 : 1,
scale: this._selectedAnimation === 'scale' ? { x: 0.5, y: 0.6 } : { x: 1, y: 1 },
rotate: this._selectedAnimation === 'rotate' ? 180 : 0,
translate: this._selectedAnimation === 'translate' ? { x: 100, y: 100 } : { x: 0, y: 0 },
duration: 500,
})
.then(() =>
view.animate({
opacity: 1,
scale: { x: 1, y: 1 },
rotate: 0,
translate: { x: 0, y: 0 },
duration: 500,
})
)
.catch((err) => {
console.error('animation error', err);
});
}
}
}

View File

@ -0,0 +1,179 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
<Page.actionBar>
<ActionBar title="Dev Toolbox" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<GridLayout rows="*, auto, *" class="box-shadow-demo">
<StackLayout backgroundColor="#ededed" row="0" padding="20" id="boxShadowDemo">
<!-- layouts -->
<ScrollView height="100%" visibility="{{ selectedComponentType === 'layouts' ? 'visible' : 'collapsed' }}">
<StackLayout>
<StackLayout
width="300"
height="100"
class="demo-component"
boxShadow="{{ appliedBoxShadow }}"
borderWidth="{{ borderWidth }}"
borderRadius="{{ borderRadius }}"
background="{{ background }}"
tap="{{ toggleAnimation }}"
>
<Label text="StackLayout"></Label>
</StackLayout>
<GridLayout
width="300"
height="100"
class="demo-component"
boxShadow="{{ appliedBoxShadow }}"
borderWidth="{{ borderWidth }}"
borderRadius="{{ borderRadius }}"
background="{{ background }}"
tap="{{ toggleAnimation }}"
>
<Label text="GridLayout"></Label>
</GridLayout>
<AbsoluteLayout
width="300"
height="100"
class="demo-component"
boxShadow="{{ appliedBoxShadow }}"
borderWidth="{{ borderWidth }}"
borderRadius="{{ borderRadius }}"
background="{{ background }}"
tap="{{ toggleAnimation }}"
>
<Label text="AbsoluteLayout"></Label>
</AbsoluteLayout>
<DockLayout
width="300"
height="100"
class="demo-component"
boxShadow="{{ appliedBoxShadow }}"
borderWidth="{{ borderWidth }}"
borderRadius="{{ borderRadius }}"
background="{{ background }}"
tap="{{ toggleAnimation }}"
>
<Label text="DockLayout"></Label>
</DockLayout>
<FlexboxLayout
width="300"
height="100"
class="demo-component"
boxShadow="{{ appliedBoxShadow }}"
borderWidth="{{ borderWidth }}"
borderRadius="{{ borderRadius }}"
background="{{ background }}"
tap="{{ toggleAnimation }}"
>
<Label text="FlexboxLayout"></Label>
</FlexboxLayout>
</StackLayout>
</ScrollView>
<!-- labels -->
<GridLayout
rows="*"
height="100%"
visibility="{{ selectedComponentType === 'labels' ? 'visible' : 'collapsed' }}">
<Label
horizontalAlignment="center"
verticalAlignment="center"
class="demo-component"
boxShadow="{{ appliedBoxShadow }}"
borderWidth="{{ borderWidth }}"
borderRadius="{{ borderRadius }}"
background="{{ background }}"
tap="{{ toggleAnimation }}"
text="Label"></Label>
</GridLayout>
<!-- buttons -->
<GridLayout
rows="*"
height="100%"
visibility="{{ selectedComponentType === 'buttons' ? 'visible' : 'collapsed' }}">
<Button
horizontalAlignment="center"
verticalAlignment="center"
class="demo-component"
boxShadow="{{ appliedBoxShadow }}"
borderWidth="{{ borderWidth }}"
borderRadius="{{ borderRadius }}"
background="{{ background }}"
tap="{{ toggleAnimation }}"
text="button"
></Button>
</GridLayout>
</StackLayout>
<GridLayout
row="1"
rows="auto"
columns="auto, *, auto"
class="box-shadow-prop-controls">
<Label
col="0"
verticalAlignment="center"
text="box-shadow:"></Label>
<TextField
col="1"
placeholder="box-shadow"
textChange="{{ textChange }}"
>
</TextField>
<Button
col="2"
text="APPLY"
class="btn-apply"
tap="{{ applyBoxShadow }}"></Button>
</GridLayout>
<ScrollView row="2">
<StackLayout padding="10" class="controls">
<Label text="Components"></Label>
<FlexboxLayout flexDirection="row" flexWrap="wrap">
<Button text="Layouts" componentType="layouts" tap="{{ selectComponentType }}"></Button>
<Button text="Labels" componentType="labels" selectedAttr="{{ selectedComponentType }}" tap="{{ selectComponentType }}"></Button>
<Button text="Buttons" componentType="buttons" selectedAttr="{{ selectedComponentType == 'buttons' }}" tap="{{ selectComponentType }}"></Button>
</FlexboxLayout>
<Label text="Background"></Label>
<FlexboxLayout flexDirection="row" flexWrap="wrap">
<Button text="Solid" backgroundType="solid" tap="{{ selectBackgroundType }}"></Button>
<Button text="Transparent" backgroundType="transparent" tap="{{ selectBackgroundType }}"></Button>
<Button text="Gradient" backgroundType="gradient" tap="{{ selectBackgroundType }}"></Button>
</FlexboxLayout>
<Label text="Borders"></Label>
<FlexboxLayout flexDirection="row" flexWrap="wrap">
<Button text="Solid" borderType="solid" tap="{{ selectBorderType }}"></Button>
<Button text="Rounded" borderType="rounded" tap="{{ selectBorderType }}"></Button>
<Button text="None" borderType="none" tap="{{ selectBorderType }}"></Button>
</FlexboxLayout>
<Label text="Animations"></Label>
<Label text="Tap on the component to start and stop animation" class="description"></Label>
<FlexboxLayout flexDirection="row" flexWrap="wrap">
<Button text="Width" animationType="width" tap="{{ selectAnimationType }}"></Button>
<Button text="Height" animationType="height" tap="{{ selectAnimationType }}"></Button>
<Button text="Opacity" animationType="opacity" tap="{{ selectAnimationType }}"></Button>
<Button text="Translate" animationType="translate" tap="{{ selectAnimationType }}"></Button>
<Button text="Scale" animationType="scale" tap="{{ selectAnimationType }}"></Button>
<Button text="Rotate" animationType="rotate" tap="{{ selectAnimationType }}"></Button>
</FlexboxLayout>
</StackLayout>
</ScrollView>
</GridLayout>
</Page>

View File

@ -1,86 +1,15 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
<Page.actionBar>
<ActionBar title="Dev Toolbox" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<GridLayout rows="2*, *">
<!-- background color transparent here to hide children overflow -->
<AbsoluteLayout row="0" backgroundColor="transparent">
<!-- Root layout demo -->
<RootLayout height="100%" width="100%">
<GridLayout height="100%" backgroundColor="#232652">
<Label verticalAlignment="center" textAlignment="center" fontWeight="bold" color="#fff" text="ROOT LAYOUT CONTENT"></Label>
</GridLayout>
</RootLayout>
</AbsoluteLayout>
<!-- Root layout controls -->
<StackLayout row="1">
<ScrollView height="100%">
<StackLayout class="p-15">
<Label color="#b4b6b9" fontSize="25" fontWeight="bold" text="ORANGE"></Label>
<FlexboxLayout flexDirection="row" justifyContent="space-between">
<Button flexGrow="1" text="open" tap="{{ open }}" popupIndex="0" class="btn btn-primary btn-active"/>
<Button flexGrow="1" text="front" tap="{{ bringToFront }}" popupIndex="0" class="btn btn-primary btn-active"/>
<Button flexGrow="1" text="close" tap="{{ close }}" popupIndex="0" class="btn btn-primary btn-active"/>
</FlexboxLayout>
<Label color="#b4b6b9" fontSize="25" fontWeight="bold" text="NAVY"></Label>
<FlexboxLayout flexDirection="row">
<Button flexGrow="1" text="open" tap="{{ open }}" popupIndex="1" class="btn btn-primary btn-active"/>
<Button flexGrow="1" text="front" tap="{{ bringToFront }}" popupIndex="1" class="btn btn-primary btn-active"/>
<Button flexGrow="1" text="close" tap="{{ close }}" popupIndex="1" class="btn btn-primary btn-active"/>
</FlexboxLayout>
<Label color="#b4b6b9" fontSize="25" fontWeight="bold" text="GRAY"></Label>
<FlexboxLayout flexDirection="row">
<Button flexGrow="1" text="open" tap="{{ open }}" popupIndex="2" class="btn btn-primary btn-active"/>
<Button flexGrow="1" text="front" tap="{{ bringToFront }}" popupIndex="2" class="btn btn-primary btn-active"/>
<Button flexGrow="1" text="close" tap="{{ close }}" popupIndex="2" class="btn btn-primary btn-active"/>
</FlexboxLayout>
<!-- <Button text="Button with html boxShadow" tap="{{ onTap }}" height="50" class="btn btn-primary btn-active" boxShadow="5 5 10 navy"/>
<Button text="Button with css boxShadow (rgba)" tap="{{ onTap }}" height="50" marginTop="50" class="btn btn-primary btn-active"/>
<Button text="Button with boxShadow 3 props" tap="{{ onTap }}" height="50" marginTop="50" boxShadow="5 5 navy" class="btn btn-primary btn-active"/>
<Button text="Button with boxShadow 4 props" tap="{{ onTap }}" height="50" marginTop="50" boxShadow="5 5 10 navy" class="btn btn-primary btn-active"/>
<Button text="Button with boxShadow 5 props" tap="{{ onTap }}" height="50" marginTop="50" boxShadow="5 5 10 10 navy" class="btn btn-primary btn-active"/>
<StackLayout boxShadow="10 10 rgba(0,0,0,1)" marginTop="50">
<Button text="Button with css boxShadow" tap="{{ onTap }}" height="50" borderRadius="10"/>
</StackLayout> -->
<!-- TODO: if backgroundColor is not set, it won't call background.ios.ts hence not applying the boxShadow -->
<!-- <StackLayout boxShadow="5 5 10 10 red" height="100" backgroundColor="transparent" padding="10" margin="20">
<Label text="StackLayout with transparent background"></Label>
</StackLayout> -->
<GridLayout boxShadow="10 -10 10 10 rgba(0,0,0,0.5)" height="100" backgroundColor="lightblue" padding="10" margin="20" tap="{{ toggleAnimation }}">
<Label text="GridLayout"></Label>
</GridLayout>
<StackLayout boxShadow="5 10 10 20 #000" height="100" backgroundColor="lightblue" padding="10" margin="20" tap="{{ toggleAnimation }}">
<Label text="StackLayout"></Label>
</StackLayout>
<AbsoluteLayout boxShadow="5 15 10 20 green" height="100" backgroundColor="lightblue" padding="10" margin="20" tap="{{ toggleAnimation }}">
<Label text="AbsoluteLayout"></Label>
</AbsoluteLayout>
<!-- note: the 3rd number in box shadow is currently being ignored, only the 1st, 2nd, and 4th, and color are being used-->
<FlexboxLayout boxShadow="0 0 10 25 red" height="100" backgroundColor="lightblue" padding="10" margin="20" tap="{{ toggleAnimation }}">
<Label text="FlexboxLayout"></Label>
</FlexboxLayout>
<FlexboxLayout boxShadow="15 10 10 20 #000" height="100" backgroundColor="transparent" padding="10" margin="20" tap="{{ toggleAnimation }}">
<Label text="FlexboxLayout (transparent background)"></Label>
</FlexboxLayout>
<Button marginTop="30" boxShadow="0 0 10 8 #000" backgroundColor="transparent" text="button" padding="20"></Button>
</StackLayout>
</ScrollView>
<Page.actionBar>
<ActionBar title="Dev Toolbox" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<StackLayout class="p-20">
<ScrollView class="h-full">
<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"/>
</StackLayout>
</GridLayout>
</ScrollView>
</StackLayout>
</Page>

View File

@ -1,171 +1,9 @@
import { Observable, Frame, View, StackLayout, getRootLayout, EventData, RootLayout, RootLayoutOptions } from '@nativescript/core';
import { AnimationCurve } from '@nativescript/core/ui/enums';
import { Observable, Frame } from '@nativescript/core';
export class HelloWorldModel extends Observable {
private _counter: number;
private _message: string;
constructor() {
super();
// Initialize default values.
this._counter = 42;
this.updateMessage();
}
get message(): string {
return this._message;
}
set message(value: string) {
if (this._message !== value) {
this._message = value;
this.notifyPropertyChange('message', value);
}
}
toggleAnimation(args) {
const layout = args.object as StackLayout;
if (!layout.className) {
layout.className = 'sample-animation';
} else {
layout.className = undefined;
}
}
onTap() {
this._counter--;
this.updateMessage();
}
popupViews: { view: View; options: RootLayoutOptions; extra?: any }[] = [
{
view: this.getPopup('#EA5936', 110, -30),
options: {
shadeCover: {
color: '#FFF',
opacity: 0.7,
tapToClose: true,
},
animation: {
enterFrom: {
opacity: 0,
translateY: 500,
duration: 500,
},
exitTo: {
opacity: 0,
duration: 300,
},
},
},
extra: {
customExitAnimation: {
opacity: 0,
translate: { x: 0, y: -500 },
},
},
},
{
view: this.getPopup('#232652', 110, 0),
options: {
shadeCover: {
color: 'pink',
opacity: 0.7,
tapToClose: false,
animation: {
exitTo: {
scaleX: 0,
},
},
},
},
},
{
view: this.getPopup('#E1E4E8', 110, 30),
options: {
shadeCover: {
color: '#ffffdd',
opacity: 0.5,
tapToClose: true,
ignoreShadeRestore: true,
animation: {
enterFrom: {
translateX: -1000,
duration: 500,
},
exitTo: {
rotate: -180,
duration: 500,
},
},
},
animation: {
enterFrom: {
rotate: 180,
duration: 300,
},
exitTo: {
rotate: 180,
opacity: 0,
duration: 300,
curve: AnimationCurve.spring,
},
},
},
},
];
open(args: EventData): void {
getRootLayout()
.open(this.popupViews[(<any>args.object).popupIndex].view, this.popupViews[(<any>args.object).popupIndex].options)
.then(() => console.log('opened'))
.catch((ex) => console.error(ex));
}
bringToFront(args: EventData): void {
getRootLayout()
.bringToFront(this.popupViews[(<any>args.object).popupIndex].view, true)
.then(() => console.log('brought to front'))
.catch((ex) => console.error(ex));
}
close(args: EventData): void {
if (this.popupViews[(<any>args.object).popupIndex]?.extra?.customExitAnimation) {
getRootLayout()
.close(this.popupViews[(<any>args.object).popupIndex].view, this.popupViews[(<any>args.object).popupIndex].extra.customExitAnimation)
.then(() => console.log('closed with custom exit animation'))
.catch((ex) => console.error(ex));
} else {
getRootLayout()
.close(this.popupViews[(<any>args.object).popupIndex].view)
.then(() => console.log('closed'))
.catch((ex) => console.error(ex));
}
}
getPopup(color: string, size: number, offset: number): View {
const layout = new StackLayout();
layout.height = size;
layout.width = size;
layout.marginTop = offset;
layout.marginLeft = offset;
layout.backgroundColor = color;
layout.borderRadius = 10;
return layout;
}
viewList() {
viewDemo(args) {
Frame.topmost().navigate({
moduleName: 'list-page',
moduleName: `${args.object.text}`,
});
}
private updateMessage() {
if (this._counter <= 0) {
this.message = 'Hoorraaay! You unlocked the NativeScript clicker achievement!';
} else {
this.message = `${this._counter} taps left`;
}
}
}

View File

@ -0,0 +1,122 @@
import { EventData, Page, Observable, RootLayoutOptions, getRootLayout, StackLayout, View } from '@nativescript/core';
import { AnimationCurve } from '@nativescript/core/ui/enums';
export function navigatingTo(args: EventData) {
const page = <Page>args.object;
page.bindingContext = new BoxShadowModel();
}
export class BoxShadowModel extends Observable {
popupViews: { view: View; options: RootLayoutOptions; extra?: any }[] = [
{
view: this.getPopup('#EA5936', 110, -30),
options: {
shadeCover: {
color: '#FFF',
opacity: 0.7,
tapToClose: true,
},
animation: {
enterFrom: {
opacity: 0,
translateY: 500,
duration: 500,
},
exitTo: {
opacity: 0,
duration: 300,
},
},
},
extra: {
customExitAnimation: {
opacity: 0,
translate: { x: 0, y: -500 },
},
},
},
{
view: this.getPopup('#232652', 110, 0),
options: {
shadeCover: {
color: 'pink',
opacity: 0.7,
tapToClose: false,
animation: {
exitTo: {
scaleX: 0,
},
},
},
},
},
{
view: this.getPopup('#E1E4E8', 110, 30),
options: {
shadeCover: {
color: '#ffffdd',
opacity: 0.5,
tapToClose: true,
ignoreShadeRestore: true,
animation: {
enterFrom: {
translateX: -1000,
duration: 500,
},
exitTo: {
rotate: -180,
duration: 500,
},
},
},
animation: {
enterFrom: {
rotate: 180,
duration: 300,
},
exitTo: {
rotate: 180,
opacity: 0,
duration: 300,
curve: AnimationCurve.spring,
},
},
},
},
];
open(args: EventData): void {
getRootLayout()
.open(this.popupViews[(<any>args.object).popupIndex].view, this.popupViews[(<any>args.object).popupIndex].options)
.catch((ex) => console.error(ex));
}
bringToFront(args: EventData): void {
getRootLayout()
.bringToFront(this.popupViews[(<any>args.object).popupIndex].view, true)
.catch((ex) => console.error(ex));
}
close(args: EventData): void {
if (this.popupViews[(<any>args.object).popupIndex]?.extra?.customExitAnimation) {
getRootLayout()
.close(this.popupViews[(<any>args.object).popupIndex].view, this.popupViews[(<any>args.object).popupIndex].extra.customExitAnimation)
.catch((ex) => console.error(ex));
} else {
getRootLayout()
.close(this.popupViews[(<any>args.object).popupIndex].view)
.catch((ex) => console.error(ex));
}
}
getPopup(color: string, size: number, offset: number): View {
const layout = new StackLayout();
layout.height = size;
layout.width = size;
layout.marginTop = offset;
layout.marginLeft = offset;
layout.backgroundColor = color;
layout.borderRadius = 10;
return layout;
}
}

View File

@ -0,0 +1,47 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
<Page.actionBar>
<ActionBar title="Dev Toolbox" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<GridLayout rows="2*, *">
<!-- background color transparent here to hide children overflow -->
<AbsoluteLayout row="0" backgroundColor="transparent">
<!-- Root layout demo -->
<RootLayout height="100%" width="100%">
<GridLayout height="100%" backgroundColor="#ededed">
<Label verticalAlignment="center" textAlignment="center" fontWeight="bold" color="#333" text="ROOT LAYOUT CONTENT"></Label>
</GridLayout>
</RootLayout>
</AbsoluteLayout>
<!-- Root layout controls -->
<StackLayout row="1">
<ScrollView height="100%">
<StackLayout padding="20" class="controls">
<Label text="ORANGE"></Label>
<FlexboxLayout flexDirection="row" justifyContent="space-between">
<Button flexGrow="1" text="open" tap="{{ open }}" popupIndex="0"/>
<Button flexGrow="1" text="front" tap="{{ bringToFront }}" popupIndex="0"/>
<Button flexGrow="1" text="close" tap="{{ close }}" popupIndex="0"/>
</FlexboxLayout>
<Label text="NAVY"></Label>
<FlexboxLayout flexDirection="row" justifyContent="space-between">
<Button flexGrow="1" text="open" tap="{{ open }}" popupIndex="1"/>
<Button flexGrow="1" text="front" tap="{{ bringToFront }}" popupIndex="1"/>
<Button flexGrow="1" text="close" tap="{{ close }}" popupIndex="1"/>
</FlexboxLayout>
<Label text="GRAY"></Label>
<FlexboxLayout flexDirection="row" justifyContent="space-between">
<Button flexGrow="1" text="open" tap="{{ open }}" popupIndex="2"/>
<Button flexGrow="1" text="front" tap="{{ bringToFront }}" popupIndex="2"/>
<Button flexGrow="1" text="close" tap="{{ close }}" popupIndex="2"/>
</FlexboxLayout>
</StackLayout>
</ScrollView>
</StackLayout>
</GridLayout>
</Page>

View File

@ -95,7 +95,7 @@ export namespace ad {
const boxShadow = view.style.boxShadow;
if (boxShadow) {
drawBoxShadow(nativeView, boxShadow);
drawBoxShadow(nativeView, view, boxShadow);
}
// TODO: Can we move BorderWidths as separate native setter?
@ -226,15 +226,14 @@ function createNativeCSSValueArray(css: string): native.Array<org.nativescript.w
return nativeArray;
}
function drawBoxShadow(nativeView: android.view.View, boxShadow: BoxShadow) {
function drawBoxShadow(nativeView: android.view.View, view: View, boxShadow: BoxShadow) {
const color = boxShadow.color;
const shadowOpacity = color.a;
const shadowColor = new Color(shadowOpacity, color.r, color.g, color.b);
// TODO: corner radius here should reflect the view's corner radius
const cornerRadius = 0; // this should be applied to the main view as well (try 20 with a transparent background on the xml to see the effect)
const cornerRadius = view.borderRadius; // this should be applied to the main view as well (try 20 with a transparent background on the xml to see the effect)
const config = {
shadowColor: shadowColor.android,
cornerRadius,
cornerRadius: cornerRadius,
spreadRadius: boxShadow.spreadRadius,
blurRadius: boxShadow.blurRadius,
offsetX: boxShadow.offsetX,

View File

@ -8,8 +8,6 @@ import { isDataURI, isFileOrResourcePath, layout } from '../../utils';
import { ImageSource } from '../../image-source';
import { CSSValue, parse as cssParse } from '../../css-value';
import { BoxShadow } from './box-shadow';
import { Screen } from '../../platform';
import { StackLayout } from '../layouts/stack-layout';
export * from './background-common';
@ -92,11 +90,10 @@ export namespace ios {
const boxShadow = view.style.boxShadow;
if (boxShadow) {
// this is required (if not, shadow will get cutoff at parent's dimensions)
// nativeView.clipsToBounds doesn't work
view.setProperty('clipToBounds', false);
drawBoxShadow(nativeView, boxShadow, background);
drawBoxShadow(nativeView, view, boxShadow, background);
}
}
}
@ -720,40 +717,29 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: Backg
}
// TODO: use sublayer if its applied to a layout
function drawBoxShadow(nativeView: NativeView, boxShadow: BoxShadow, background: BackgroundDefinition, useSubLayer: boolean = false) {
function drawBoxShadow(nativeView: NativeView, view: View, boxShadow: BoxShadow, background: BackgroundDefinition, useSubLayer: boolean = false) {
const layer: CALayer = nativeView.layer;
layer.masksToBounds = false;
nativeView.clipsToBounds = false;
if (!background.color.a) {
if (!background.color?.a) {
// add white background if view has a transparent background
layer.backgroundColor = UIColor.whiteColor.CGColor;
}
// shadow opacity is handled on the shadow's color instance
layer.shadowOpacity = 1;
layer.shadowRadius = boxShadow.spreadRadius;
layer.shadowRadius = layout.toDeviceIndependentPixels(boxShadow.spreadRadius);
layer.shadowColor = boxShadow.color.ios.CGColor;
// / 2 here since ios's shadow offset is bigger than android
// TODO: this is just for experimenting with the amount of offset,
// need to use some real calculation here to gain parity with android's
// implementation
const adjustedShadowOffset = {
x: boxShadow.offsetX / 2,
y: boxShadow.offsetY / 2,
x: layout.toDeviceIndependentPixels(boxShadow.offsetX),
y: layout.toDeviceIndependentPixels(boxShadow.offsetY),
};
layer.shadowOffset = CGSizeMake(adjustedShadowOffset.x, adjustedShadowOffset.y);
// this should match the view's border radius
const cornerRadius = 0;
// This doesn't handle the offsets properly
// factor in shadowRadius and the offsets so shadow don't spread too far
// layer.shadowPath = UIBezierPath.bezierPathWithRoundedRectCornerRadius(CGRectMake(
// nativeView.bounds.origin.x + boxShadow.spreadRadius + adjustedShadowOffset.x,
// nativeView.bounds.origin.y + boxShadow.spreadRadius + adjustedShadowOffset.y,
// nativeView.bounds.size.width - boxShadow.spreadRadius - adjustedShadowOffset.x,
// nativeView.bounds.size.height - boxShadow.spreadRadius - adjustedShadowOffset.y), cornerRadius).CGPath;
const cornerRadius = 0; // layout.toDeviceIndependentPixels(view.style.borderRadius);
// This has the nice glow with box shadow of 0,0
layer.shadowPath = UIBezierPath.bezierPathWithRoundedRectCornerRadius(nativeView.bounds, cornerRadius).CGPath;