feat(ios): SF Symbol effects via symbolEffect property

This commit is contained in:
Nathan Walker
2024-06-16 14:21:09 -07:00
parent 9d6e9fe144
commit 56dda3b805
7 changed files with 78 additions and 3 deletions

View File

@@ -1,4 +1,4 @@
import { Observable, EventData, Page, ImageSource, knownFolders, path } from '@nativescript/core';
import { Observable, EventData, Page, ImageSource, knownFolders, path, ImageSymbolEffect } from '@nativescript/core';
import { create, ImagePickerMediaType } from '@nativescript/imagepicker';
let page: Page;
@@ -10,6 +10,32 @@ export function navigatingTo(args: EventData) {
export class DemoModel extends Observable {
addingPhoto = false;
symbolWiggleEffect: ImageSymbolEffect;
symbolBounceEffect: ImageSymbolEffect;
symbolBreathEffect: ImageSymbolEffect;
symbolRotateEffect: ImageSymbolEffect;
constructor() {
super();
if (__APPLE__) {
this.symbolWiggleEffect = {
effect: NSSymbolWiggleEffect.effect(),
start: true,
};
this.symbolBounceEffect = {
effect: NSSymbolBounceEffect.effect(),
start: true,
};
this.symbolBreathEffect = {
effect: NSSymbolBreatheEffect.effect(),
start: true,
};
this.symbolRotateEffect = {
effect: NSSymbolRotateEffect.effect(),
start: true,
};
}
}
pickImage() {
const context = create({

View File

@@ -5,9 +5,27 @@
</Page.actionBar>
<StackLayout class="p-20">
<Label text="Test Memory leaks with image picking and saving to device. Best to profile from platform IDE like Xcode." textWrap="true" />
<Button text="Pick and Save Image" tap="{{ pickImage }}" />
<ios>
<!-- SF Symbols with Effects -->
<ContentView height="1" width="100%" backgroundColor="#efefef" margin="10"></ContentView>
<GridLayout rows="auto,auto,auto" columns="*,*">
<Image src="sys://photo.on.rectangle.angled" width="100" tintColor="green" symbolEffect="{{symbolWiggleEffect}}" padding="8"/>
<Image col="1" src="sys://steeringwheel.and.hands" width="100" tintColor="black" symbolEffect="{{symbolWiggleEffect}}" padding="8" />
<Image row="1" src="sys://airpods.pro.chargingcase.wireless.radiowaves.left.and.right.fill" width="100" symbolEffect="{{symbolBounceEffect}}" padding="8" />
<Image row="1" col="1" src="sys://lungs.fill" width="100" symbolEffect="{{symbolBreathEffect}}" padding="8" />
<Image row="2" src="sys://clock.arrow.trianglehead.2.counterclockwise.rotate.90" width="100" symbolEffect="{{symbolRotateEffect}}" padding="8" />
<Image row="2" col="1" src="sys://square.and.arrow.up" width="100" symbolEffect="{{symbolWiggleEffect}}" padding="8" />
</GridLayout>
</ios>
</StackLayout>
</Page>

View File

@@ -2,6 +2,7 @@
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!CFNetwork.d.ts" />
/// <reference path="../types-ios/src/lib/ios/objc-x86_64/objc!CoreText.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!Symbols.d.ts" />
/// <reference path="../types-android/src/lib/android-29.d.ts" />
/// <reference path="./platforms/ios/typings/objc!MaterialComponents.d.ts" />
/// <reference path="./platforms/ios/typings/objc!NativeScriptUtils.d.ts" />

View File

@@ -186,3 +186,22 @@ export const decodeWidthProperty = new Property<ImageBase, CoreTypes.LengthType>
valueConverter: Length.parse,
});
decodeWidthProperty.register(ImageBase);
/**
* iOS only
* Symbol effects: https://developer.apple.com/documentation/symbols?language=objc
*/
export type ImageSymbolEffect = {
effect?: NSSymbolEffect;
options?: NSSymbolEffectOptions;
completion?: (context: UISymbolEffectCompletionContext) => void;
start?: boolean;
};
/**
* iOS only
*/
export const symbolEffectProperty = new Property<ImageBase, ImageSymbolEffect>({
name: 'symbolEffect',
});
symbolEffectProperty.register(ImageBase);

View File

@@ -6,6 +6,7 @@ import { Color } from '../../color';
import { Property, InheritedCssProperty } from '../core/properties';
import { CoreTypes } from '../../core-types';
export type { ImageSymbolEffect } from './image-common';
/**
* Represents a class that provides functionality for loading and streching image(s).
*/

View File

@@ -1,4 +1,4 @@
import { ImageBase, stretchProperty, imageSourceProperty, tintColorProperty, srcProperty } from './image-common';
import { ImageBase, stretchProperty, imageSourceProperty, tintColorProperty, srcProperty, symbolEffectProperty, ImageSymbolEffect } from './image-common';
import { ImageSource } from '../../image-source';
import { ImageAsset } from '../../image-asset';
import { Color } from '../../color';
@@ -194,4 +194,14 @@ export class Image extends ImageBase {
[srcProperty.setNative](value: string | ImageSource | ImageAsset) {
this._createImageSourceFromSrc(value);
}
[symbolEffectProperty.setNative](value: ImageSymbolEffect) {
if (this.nativeViewProtected) {
if (value?.start) {
this.nativeViewProtected.addSymbolEffectOptionsAnimatedCompletion(value.effect || NSSymbolScaleEffect.effect(), value.options || NSSymbolEffectOptions.optionsWithRepeating(), true, value.completion || null);
} else {
this.nativeViewProtected.removeAllSymbolEffects();
}
}
}
}

View File

@@ -31,7 +31,7 @@ export { GesturesObserver, TouchAction, GestureTypes, GestureStateTypes, SwipeDi
export type { GestureEventData, GestureEventDataWithState, TapGestureEventData, PanGestureEventData, PinchGestureEventData, RotationGestureEventData, SwipeGestureEventData, TouchGestureEventData, TouchAnimationOptions, VisionHoverOptions } from './gestures';
export { HtmlView } from './html-view';
export { Image } from './image';
export { Image, ImageSymbolEffect } from './image';
export { Cache as ImageCache } from './image-cache';
export type { DownloadError, DownloadRequest, DownloadedData } from './image-cache';
export { Label } from './label';