Skip to content

Commit 49c361c

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/list-view-sticky-headers
2 parents 27acac6 + 65c8163 commit 49c361c

File tree

32 files changed

+975
-305
lines changed

32 files changed

+975
-305
lines changed

apps/toolbox/src/pages/box-shadow.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ export class BoxShadowModel extends Observable {
1010
private _selectedBackgroundType: string;
1111
private _selectedBorderType: string;
1212
private _selectedAnimation: string;
13-
private _boxShadow: string = '0 0 2 2 rgba(200, 0, 0, 0.4)';
14-
// private _boxShadow: string = '5 5 1 1 rgba(255, 0, 0, .9)';
15-
// private _boxShadow: string = '5 5 5 10 rgba(255, 0, 0, .9)';
13+
private _boxShadow: string = '-5 -5 5 5 rgba(200, 0, 0, 0.5), 5 5 5 5 rgba(0, 99, 0, 0.5)';
1614

1715
background: string;
1816
borderColor: string;
@@ -136,7 +134,7 @@ export class BoxShadowModel extends Observable {
136134
view.animate({
137135
width: originalWidth,
138136
duration: animationDuration,
139-
})
137+
}),
140138
)
141139
.catch((err) => {
142140
console.error('animation error', err);
@@ -152,7 +150,7 @@ export class BoxShadowModel extends Observable {
152150
view.animate({
153151
height: originalHeight,
154152
duration: animationDuration,
155-
})
153+
}),
156154
)
157155
.catch((err) => {
158156
console.error('animation error', err);
@@ -173,7 +171,7 @@ export class BoxShadowModel extends Observable {
173171
rotate: 0,
174172
translate: { x: 0, y: 0 },
175173
duration: 500,
176-
})
174+
}),
177175
)
178176
.catch((err) => {
179177
console.error('animation error', err);

apps/toolbox/src/pages/glass-effects.ts

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Observable, EventData, Page, CoreTypes, GlassEffectConfig } from '@nativescript/core';
1+
import { Observable, EventData, Page, CoreTypes, GlassEffectConfig, View, Label, Animation, LiquidGlassContainer } from '@nativescript/core';
22

33
let page: Page;
44

@@ -10,7 +10,111 @@ export function navigatingTo(args: EventData) {
1010
export class GlassEffectModel extends Observable {
1111
iosGlassEffectInteractive: GlassEffectConfig = {
1212
interactive: true,
13-
tint: '#faabab',
13+
// tint: '#faabab',
1414
variant: 'clear',
1515
};
16+
currentEffect: GlassEffectConfig = {
17+
variant: 'none',
18+
interactive: false,
19+
// tint: '#ccc',
20+
};
21+
22+
toggleGlassEffect(args) {
23+
const btn = args.object as View;
24+
this.currentEffect =
25+
this.currentEffect.variant === 'none'
26+
? {
27+
variant: 'clear',
28+
interactive: true,
29+
// tint: '#faabab',
30+
}
31+
: {
32+
variant: 'none',
33+
interactive: false,
34+
// tint: '#ccc',
35+
};
36+
btn.iosGlassEffect = this.currentEffect;
37+
}
38+
39+
glassMerged = false;
40+
glassTargets = {};
41+
loadedGlass(args) {
42+
const glass = args.object as View;
43+
switch (glass.id) {
44+
case 'glass1':
45+
glass.translateX = 10;
46+
break;
47+
case 'glass2':
48+
glass.translateX = 70;
49+
50+
break;
51+
}
52+
this.glassTargets[glass.id] = glass;
53+
}
54+
55+
glassTargetLabels: { [key: string]: Label } = {};
56+
loadedGlassLabels(args) {
57+
const label = args.object as Label;
58+
this.glassTargetLabels[label.id] = label;
59+
}
60+
61+
async toggleMergeGlass(args) {
62+
if (!this.glassTargets['glass1'] || !this.glassTargets['glass2']) {
63+
return;
64+
}
65+
const container = args?.object as LiquidGlassContainer | undefined;
66+
this.glassMerged = !this.glassMerged;
67+
const glass1 = this.glassTargets['glass1'];
68+
const glass2 = this.glassTargets['glass2'];
69+
70+
// Use relative deltas for translate; the container will bake them into frames post-animation
71+
const d1 = this.glassMerged ? 25 : -25; // left bubble moves inward/outward
72+
const d2 = this.glassMerged ? -25 : 25; // right bubble moves inward/outward
73+
74+
if (!this.glassMerged) {
75+
this.glassTargetLabels['like'].text = 'Like';
76+
}
77+
78+
const animateAll = new Animation([
79+
{ target: glass1, translate: { x: d1, y: 0 }, duration: 300, curve: CoreTypes.AnimationCurve.easeOut },
80+
{ target: glass2, translate: { x: d2, y: 0 }, duration: 300, curve: CoreTypes.AnimationCurve.easeOut },
81+
{
82+
target: this.glassTargetLabels['share'],
83+
opacity: this.glassMerged ? 0 : 1,
84+
duration: 300,
85+
},
86+
]);
87+
animateAll.play().then(() => {
88+
if (this.glassMerged) {
89+
this.glassTargetLabels['like'].text = 'Done';
90+
}
91+
92+
// Ask container to stabilize frames so UIGlassContainerEffect samples correct positions
93+
setTimeout(() => container?.stabilizeLayout?.(), 0);
94+
});
95+
96+
// for testing, on tap, can see glass effect changes animating differences
97+
// this.testGlassBindingChanges();
98+
}
99+
100+
testGlassBindingChanges() {
101+
setTimeout(() => {
102+
this.iosGlassEffectInteractive = {
103+
interactive: false,
104+
variant: 'regular',
105+
// can even animate tint changes (requires starting of transparent tint)
106+
// tint: '#faabab',
107+
};
108+
this.notifyPropertyChange('iosGlassEffectInteractive', this.iosGlassEffectInteractive);
109+
setTimeout(() => {
110+
this.iosGlassEffectInteractive = {
111+
interactive: true,
112+
variant: 'clear',
113+
// by setting tint to transparent, it will animate on next change
114+
// tint: '#00000000',
115+
};
116+
this.notifyPropertyChange('iosGlassEffectInteractive', this.iosGlassEffectInteractive);
117+
}, 1500);
118+
}, 1500);
119+
}
16120
}
Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,57 @@
11
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
22
<Page.actionBar>
3-
<ActionBar title="Glass Effects" class="action-bar">
3+
<ActionBar title="Glass Effects" color="white">
44
</ActionBar>
55
</Page.actionBar>
66

7-
<GridLayout>
7+
<GridLayout backgroundColor="#000">
8+
<!-- test color changes over light/dark backgrounds for text -->
9+
<!-- <ContentView backgroundColor="#000" height="300" verticalAlignment="bottom"/> -->
10+
<Image src="res://bg1.jpg" stretch="aspectFill" iosOverflowSafeArea="true" />
811

9-
<Image src="https://cdn.wallpapersafari.com/89/64/c6MnRY.jpg" stretch="aspectFill" iosOverflowSafeArea="true" />
12+
<ScrollView backgroundColor="transparent">
13+
<StackLayout>
14+
<GridLayout rows="*,auto,auto,auto,auto,auto,*">
1015

11-
<GridLayout rows="*,auto,auto,auto,*">
16+
<Button row="2" text="Toggle Glass" tap="{{toggleGlassEffect}}" horizontalAlignment="center" verticalAlignment="middle" class="c-white font-weight-bold m-y-20 p-4" fontSize="22" borderRadius="32" width="300" height="100" touchAnimation="{{touchAnimation}}" iosGlassEffect="{{currentEffect}}"/>
1217

13-
<GridLayout row="1" width="300" height="150" iosGlassEffect="regular" horizontalAlignment="center" verticalAlignment="middle">
14-
<Label class="text-center c-white" fontWeight="bold" fontSize="18" text="Glass Effects Regular" />
15-
</GridLayout>
18+
<LiquidGlass row="3" width="300" height="100" borderRadius="32" iosGlassEffect="{{iosGlassEffectInteractive}}" >
1619

17-
<GridLayout row="2" width="300" height="150" iosGlassEffect="clear" horizontalAlignment="center" verticalAlignment="middle" class="m-t-10">
18-
<Label class="text-center c-white" fontWeight="bold" fontSize="18" text="Glass Effects Clear" />
19-
</GridLayout>
20+
<Label text="Glass Interactive" fontSize="22" class="font-weight-bold text-center c-white" />
21+
22+
</LiquidGlass>
23+
24+
25+
<LiquidGlassContainer row="4" tap="{{toggleMergeGlass}}" horizontalAlignment="left" verticalAlignment="middle" class="m-t-20" width="300" height="100" columns="*">
26+
<LiquidGlass id="glass1" loaded="{{loadedGlass}}" borderRadius="50" width="100" height="100">
27+
<Label id="share" text="Share" fontSize="22" class="font-weight-bold text-center" width="100" height="100" loaded="{{loadedGlassLabels}}" />
28+
</LiquidGlass>
29+
<LiquidGlass id="glass2" loaded="{{loadedGlass}}" borderRadius="50" width="100" height="100">
30+
<Label id="like" text="Like" fontSize="22" class="font-weight-bold text-center" loaded="{{loadedGlassLabels}}" />
31+
</LiquidGlass>
32+
</LiquidGlassContainer>
33+
</GridLayout>
34+
35+
<GridLayout rows="*,auto,auto,auto,*" class="m-t-10">
36+
<GridLayout row="1" width="300" height="100" iosGlassEffect="regular" horizontalAlignment="center" verticalAlignment="middle" borderRadius="32">
37+
<Label class="text-center c-white" fontWeight="bold" fontSize="18" text="Glass Effects Regular" />
38+
</GridLayout>
39+
40+
<GridLayout row="2" width="300" height="100" iosGlassEffect="clear" horizontalAlignment="center" verticalAlignment="middle" class="m-t-10" borderRadius="32">
41+
<Label class="text-center c-white" fontWeight="bold" fontSize="18" text="Glass Effects Clear" />
42+
</GridLayout>
43+
44+
<GridLayout row="3" width="300" height="100" iosGlassEffect="{{iosGlassEffectInteractive}}" horizontalAlignment="center" verticalAlignment="middle" class="m-t-10" borderRadius="32">
45+
<Label class="text-center c-white" fontWeight="bold" fontSize="18" text="Glass Effects Interactive" />
46+
</GridLayout>
47+
</GridLayout>
48+
49+
<!-- make scrollable to view glass on scroll -->
50+
<ContentView height="500"/>
51+
</StackLayout>
52+
53+
</ScrollView>
2054

21-
<GridLayout row="3" width="300" height="150" iosGlassEffect="{{iosGlassEffectInteractive}}" horizontalAlignment="center" verticalAlignment="middle" class="m-t-10">
22-
<Label class="text-center c-white" fontWeight="bold" fontSize="18" text="Glass Effects Interactive" />
23-
</GridLayout>
24-
</GridLayout>
2555

2656
</GridLayout>
2757
</Page>

packages/core/references.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Darwin.d.ts" />
55
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!DarwinFoundation.d.ts" />
66
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!Symbols.d.ts" />
7-
/// <reference path="../types-android/src/lib/android-30.d.ts" />
7+
/// <reference path="../types-android/src/lib/android-33.d.ts" />
88
/// <reference path="./platforms/ios/typings/objc!MaterialComponents.d.ts" />
99
/// <reference path="./platforms/ios/typings/objc!NativeScriptUtils.d.ts" />
1010
/// <reference path="./global-types.d.ts" />

packages/core/ui/button/index.ios.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProp
55
import { textAlignmentProperty, whiteSpaceProperty, textOverflowProperty } from '../text-base';
66
import { layout } from '../../utils';
77
import { CoreTypes } from '../../core-types';
8-
import { Color } from '../../color';
98

109
export * from './button-common';
1110

packages/core/ui/core/view/index.android.ts

Lines changed: 79 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,51 @@ interface DialogOptions {
7272
dismissCallback: () => void;
7373
}
7474

75+
let OnBackPressedCallback;
76+
77+
if (SDK_VERSION >= 33) {
78+
OnBackPressedCallback = (androidx.activity.OnBackPressedCallback as any).extend({
79+
handleOnBackPressed() {
80+
console.log('OnBackPressedCallback handleOnBackPressed called');
81+
const dialog = this['_dialog']?.get();
82+
83+
if (!dialog) {
84+
// disable the callback and call super to avoid infinite loop
85+
86+
this.setEnabled(false);
87+
88+
return;
89+
}
90+
91+
const view = dialog.fragment.owner;
92+
93+
const args: AndroidActivityBackPressedEventData = {
94+
eventName: 'activityBackPressed',
95+
object: view,
96+
activity: view._context,
97+
cancel: false,
98+
};
99+
100+
// Fist fire application.android global event
101+
getNativeScriptGlobals().events.notify(args);
102+
103+
if (args.cancel) {
104+
return;
105+
}
106+
107+
view.notify(args);
108+
109+
if (!args.cancel) {
110+
this.setEnabled(false);
111+
112+
dialog.getOnBackPressedDispatcher().onBackPressed();
113+
114+
this.setEnabled(true);
115+
}
116+
},
117+
});
118+
}
119+
75120
interface TouchListener {
76121
new (owner: View): android.view.View.OnTouchListener;
77122
}
@@ -121,14 +166,24 @@ function initializeDialogFragment() {
121166
}
122167

123168
@NativeClass
124-
class DialogImpl extends android.app.Dialog {
169+
class DialogImpl extends androidx.appcompat.app.AppCompatDialog {
125170
constructor(
126171
public fragment: DialogFragmentImpl,
127172
context: android.content.Context,
128173
themeResId: number,
129174
) {
130175
super(context, themeResId);
131176

177+
if (SDK_VERSION >= 33 && OnBackPressedCallback) {
178+
const callback = new OnBackPressedCallback(true);
179+
180+
callback['_dialog'] = new WeakRef(this);
181+
182+
// @ts-ignore
183+
184+
this.getOnBackPressedDispatcher().addCallback(this, callback);
185+
}
186+
132187
return global.__native(this);
133188
}
134189

@@ -138,6 +193,10 @@ function initializeDialogFragment() {
138193
}
139194

140195
public onBackPressed(): void {
196+
if (SDK_VERSION >= 33) {
197+
super.onBackPressed();
198+
return;
199+
}
141200
const view = this.fragment.owner;
142201
const args = <AndroidActivityBackPressedEventData>{
143202
eventName: 'activityBackPressed',
@@ -1448,17 +1507,23 @@ export class View extends ViewCommon {
14481507
}
14491508
}
14501509

1451-
protected _drawBoxShadow(boxShadow: BoxShadow) {
1510+
protected _drawBoxShadow(boxShadows: BoxShadow[]) {
14521511
const nativeView = this.nativeViewProtected;
1453-
const config = {
1454-
shadowColor: boxShadow.color.android,
1455-
cornerRadius: Length.toDevicePixels(this.borderRadius as CoreTypes.LengthType, 0.0),
1456-
spreadRadius: boxShadow.spreadRadius,
1457-
blurRadius: boxShadow.blurRadius,
1458-
offsetX: boxShadow.offsetX,
1459-
offsetY: boxShadow.offsetY,
1460-
};
1461-
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, JSON.stringify(config));
1512+
const valueCount = 6;
1513+
const nativeArray: number[] = Array.create('int', boxShadows.length * valueCount);
1514+
1515+
for (let i = 0, length = boxShadows.length; i < length; i++) {
1516+
const boxShadow = boxShadows[i];
1517+
const nativeIndex = i * valueCount;
1518+
1519+
nativeArray[nativeIndex + 0] = boxShadow.color.android;
1520+
nativeArray[nativeIndex + 1] = boxShadow.spreadRadius;
1521+
nativeArray[nativeIndex + 2] = boxShadow.blurRadius;
1522+
nativeArray[nativeIndex + 3] = boxShadow.offsetX;
1523+
nativeArray[nativeIndex + 4] = boxShadow.offsetY;
1524+
nativeArray[nativeIndex + 5] = boxShadow.inset ? 1 : 0;
1525+
}
1526+
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, nativeArray);
14621527
}
14631528

14641529
_redrawNativeBackground(value: android.graphics.drawable.Drawable | Background): void {
@@ -1507,15 +1572,15 @@ export class View extends ViewCommon {
15071572
// prettier-ignore
15081573
const onlyColor = !background.hasBorderWidth()
15091574
&& !background.hasBorderRadius()
1510-
&& !background.hasBoxShadow()
1575+
&& !background.hasBoxShadows()
15111576
&& !background.clipPath
15121577
&& !background.image
15131578
&& !!background.color;
15141579

15151580
this._applyBackground(background, isBorderDrawable, onlyColor, drawable);
15161581

1517-
if (background.hasBoxShadow()) {
1518-
this._drawBoxShadow(background.getBoxShadow());
1582+
if (background.hasBoxShadows()) {
1583+
this._drawBoxShadow(background.getBoxShadows());
15191584
}
15201585

15211586
// TODO: Can we move BorderWidths as separate native setter?

packages/core/ui/core/view/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ export abstract class View extends ViewCommon {
384384
*
385385
* @nsProperty
386386
*/
387-
boxShadow: string | ShadowCSSValues;
387+
boxShadow: string | ShadowCSSValues[];
388388

389389
/**
390390
* Gets or sets the minimum width the view may grow to.

0 commit comments

Comments
 (0)