mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00

* chore: move tns-core-modules to nativescript-core * chore: preparing compat generate script * chore: add missing definitions * chore: no need for http-request to be private * chore: packages chore * test: generate tests for tns-core-modules * chore: add anroid module for consistency * chore: add .npmignore * chore: added privateModulesWhitelist * chore(webpack): added bundle-entry-points * chore: scripts * chore: tests changed to use @ns/core * test: add scoped-packages test project * test: fix types * test: update test project * chore: build scripts * chore: update build script * chore: npm scripts cleanup * chore: make the compat pgk work with old wp config * test: generate diff friendly tests * chore: create barrel exports * chore: move files after rebase * chore: typedoc config * chore: compat mode * chore: review of barrels * chore: remove tns-core-modules import after rebase * chore: dev workflow setup * chore: update developer-workflow * docs: experiment with API extractor * chore: api-extractor and barrel exports * chore: api-extractor configs * chore: generate d.ts rollup with api-extractor * refactor: move methods inside Frame * chore: fic tests to use Frame static methods * refactor: create Builder class * refactor: use Builder class in tests * refactor: include Style in ui barrel * chore: separate compat build script * chore: fix tslint errors * chore: update NATIVESCRIPT_CORE_ARGS * chore: fix compat pack * chore: fix ui-test-app build with linked modules * chore: Application, ApplicationSettings, Connectivity and Http * chore: export Trace, Profiling and Utils * refactor: Static create methods for ImageSource * chore: fix deprecated usages of ImageSource * chore: move Span and FormattedString to ui * chore: add events-args and ImageSource to index files * chore: check for CLI >= 6.2 when building for IOS * chore: update travis build * chore: copy Pod file to compat package * chore: update error msg ui-tests-app * refactor: Apply suggestions from code review Co-Authored-By: Martin Yankov <m.i.yankov@gmail.com> * chore: typings and refs * chore: add missing d.ts files for public API * chore: adress code review FB * chore: update api-report * chore: dev-workflow for other apps * chore: api update * chore: update api-report
159 lines
6.1 KiB
TypeScript
159 lines
6.1 KiB
TypeScript
import {
|
|
ImageSource, ImageBase, stretchProperty, imageSourceProperty, tintColorProperty, srcProperty, layout, Color,
|
|
traceEnabled, traceWrite, traceCategories
|
|
} from "./image-common";
|
|
|
|
export * from "./image-common";
|
|
|
|
export class Image extends ImageBase {
|
|
nativeViewProtected: UIImageView;
|
|
private _imageSourceAffectsLayout: boolean = true;
|
|
private _templateImageWasCreated: boolean;
|
|
|
|
public createNativeView() {
|
|
const imageView = UIImageView.new();
|
|
imageView.contentMode = UIViewContentMode.ScaleAspectFit;
|
|
imageView.userInteractionEnabled = true;
|
|
|
|
return imageView;
|
|
}
|
|
|
|
public initNativeView(): void {
|
|
super.initNativeView();
|
|
this._setNativeClipToBounds();
|
|
}
|
|
|
|
private setTintColor(value: Color) {
|
|
if (value && this.nativeViewProtected.image && !this._templateImageWasCreated) {
|
|
this.nativeViewProtected.image = this.nativeViewProtected.image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);
|
|
this._templateImageWasCreated = true;
|
|
} else if (!value && this.nativeViewProtected.image && this._templateImageWasCreated) {
|
|
this._templateImageWasCreated = false;
|
|
this.nativeViewProtected.image = this.nativeViewProtected.image.imageWithRenderingMode(UIImageRenderingMode.Automatic);
|
|
}
|
|
this.nativeViewProtected.tintColor = value ? value.ios : null;
|
|
}
|
|
|
|
public _setNativeImage(nativeImage: UIImage) {
|
|
this.nativeViewProtected.image = nativeImage;
|
|
this._templateImageWasCreated = false;
|
|
this.setTintColor(this.style.tintColor);
|
|
|
|
if (this._imageSourceAffectsLayout) {
|
|
this.requestLayout();
|
|
}
|
|
}
|
|
|
|
_setNativeClipToBounds() {
|
|
// Always set clipsToBounds for images
|
|
this.nativeViewProtected.clipsToBounds = true;
|
|
}
|
|
|
|
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
|
// We don't call super because we measure native view with specific size.
|
|
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
|
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
|
|
|
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
|
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
|
|
|
const nativeWidth = this.imageSource ? layout.toDevicePixels(this.imageSource.width) : 0;
|
|
const nativeHeight = this.imageSource ? layout.toDevicePixels(this.imageSource.height) : 0;
|
|
|
|
let measureWidth = Math.max(nativeWidth, this.effectiveMinWidth);
|
|
let measureHeight = Math.max(nativeHeight, this.effectiveMinHeight);
|
|
|
|
const finiteWidth: boolean = widthMode !== layout.UNSPECIFIED;
|
|
const finiteHeight: boolean = heightMode !== layout.UNSPECIFIED;
|
|
|
|
this._imageSourceAffectsLayout = widthMode !== layout.EXACTLY || heightMode !== layout.EXACTLY;
|
|
|
|
if (nativeWidth !== 0 && nativeHeight !== 0 && (finiteWidth || finiteHeight)) {
|
|
const scale = Image.computeScaleFactor(width, height, finiteWidth, finiteHeight, nativeWidth, nativeHeight, this.stretch);
|
|
const resultW = Math.round(nativeWidth * scale.width);
|
|
const resultH = Math.round(nativeHeight * scale.height);
|
|
|
|
measureWidth = finiteWidth ? Math.min(resultW, width) : resultW;
|
|
measureHeight = finiteHeight ? Math.min(resultH, height) : resultH;
|
|
|
|
if (traceEnabled()) {
|
|
traceWrite("Image stretch: " + this.stretch +
|
|
", nativeWidth: " + nativeWidth +
|
|
", nativeHeight: " + nativeHeight, traceCategories.Layout);
|
|
}
|
|
}
|
|
|
|
const widthAndState = Image.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
|
const heightAndState = Image.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
|
|
|
this.setMeasuredDimension(widthAndState, heightAndState);
|
|
}
|
|
|
|
private static computeScaleFactor(measureWidth: number, measureHeight: number, widthIsFinite: boolean, heightIsFinite: boolean, nativeWidth: number, nativeHeight: number, imageStretch: string): { width: number; height: number } {
|
|
let scaleW = 1;
|
|
let scaleH = 1;
|
|
|
|
if ((imageStretch === "aspectFill" || imageStretch === "aspectFit" || imageStretch === "fill") &&
|
|
(widthIsFinite || heightIsFinite)) {
|
|
|
|
scaleW = (nativeWidth > 0) ? measureWidth / nativeWidth : 0;
|
|
scaleH = (nativeHeight > 0) ? measureHeight / nativeHeight : 0;
|
|
|
|
if (!widthIsFinite) {
|
|
scaleW = scaleH;
|
|
}
|
|
else if (!heightIsFinite) {
|
|
scaleH = scaleW;
|
|
}
|
|
else {
|
|
// No infinite dimensions.
|
|
switch (imageStretch) {
|
|
case "aspectFit":
|
|
scaleH = scaleW < scaleH ? scaleW : scaleH;
|
|
scaleW = scaleH;
|
|
break;
|
|
case "aspectFill":
|
|
scaleH = scaleW > scaleH ? scaleW : scaleH;
|
|
scaleW = scaleH;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return { width: scaleW, height: scaleH };
|
|
}
|
|
|
|
[stretchProperty.setNative](value: "none" | "aspectFill" | "aspectFit" | "fill") {
|
|
switch (value) {
|
|
case "aspectFit":
|
|
this.nativeViewProtected.contentMode = UIViewContentMode.ScaleAspectFit;
|
|
break;
|
|
|
|
case "aspectFill":
|
|
this.nativeViewProtected.contentMode = UIViewContentMode.ScaleAspectFill;
|
|
break;
|
|
|
|
case "fill":
|
|
this.nativeViewProtected.contentMode = UIViewContentMode.ScaleToFill;
|
|
break;
|
|
|
|
case "none":
|
|
default:
|
|
this.nativeViewProtected.contentMode = UIViewContentMode.TopLeft;
|
|
break;
|
|
}
|
|
}
|
|
|
|
[tintColorProperty.setNative](value: Color) {
|
|
this.setTintColor(value);
|
|
}
|
|
|
|
[imageSourceProperty.setNative](value: ImageSource) {
|
|
this._setNativeImage(value ? value.ios : null);
|
|
}
|
|
|
|
[srcProperty.setNative](value: any) {
|
|
this._createImageSourceFromSrc(value);
|
|
}
|
|
}
|