mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
disable recycling on specific button (#4527)
* disable recycling on specific button add more thorough test for view recycling fix memory leak with android ActionBar improve padding reset when view is recycled improve reset of several controls * stopping local animations when view is recycled fix tns-ios version in tests/package.json * Fix isClickable on android when reusing nativeView
This commit is contained in:
committed by
Alexander Vakrilov
parent
f092a6ecae
commit
09535627b9
@@ -133,8 +133,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
public static loadedEvent = "loaded";
|
||||
public static unloadedEvent = "unloaded";
|
||||
|
||||
public recycleNativeView: boolean;
|
||||
|
||||
private _recycleNativeView: boolean;
|
||||
private _iosView: Object;
|
||||
private _androidView: Object;
|
||||
private _style: Style;
|
||||
@@ -204,6 +203,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
public _defaultPaddingRight: number;
|
||||
public _defaultPaddingBottom: number;
|
||||
public _defaultPaddingLeft: number;
|
||||
private _isPaddingRelative: boolean;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -216,6 +216,14 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
return types.getClass(this);
|
||||
}
|
||||
|
||||
get recycleNativeView(): boolean {
|
||||
return this._recycleNativeView;
|
||||
}
|
||||
|
||||
set recycleNativeView(value: boolean) {
|
||||
this._recycleNativeView = typeof value === "boolean" ? value : booleanConverter(value);
|
||||
}
|
||||
|
||||
get style(): Style {
|
||||
return this._style;
|
||||
}
|
||||
@@ -630,6 +638,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
if (this._styleScope === view._styleScope) {
|
||||
view._setStyleScope(null);
|
||||
}
|
||||
|
||||
if (view.isLoaded) {
|
||||
view.onUnloaded();
|
||||
}
|
||||
@@ -662,9 +671,13 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
|
||||
private resetNativeViewInternal(): void {
|
||||
const nativeView = this.nativeView;
|
||||
if (nativeView && this.recycleNativeView && isAndroid) {
|
||||
if (nativeView && this._recycleNativeView && isAndroid) {
|
||||
resetNativeView(this);
|
||||
nativeView.setPadding(this._defaultPaddingLeft, this._defaultPaddingTop, this._defaultPaddingRight, this._defaultPaddingBottom);
|
||||
if (this._isPaddingRelative) {
|
||||
nativeView.setPaddingRelative(this._defaultPaddingLeft, this._defaultPaddingTop, this._defaultPaddingRight, this._defaultPaddingBottom);
|
||||
} else {
|
||||
nativeView.setPadding(this._defaultPaddingLeft, this._defaultPaddingTop, this._defaultPaddingRight, this._defaultPaddingBottom);
|
||||
}
|
||||
this.resetNativeView();
|
||||
}
|
||||
if (this._cssState) {
|
||||
@@ -689,7 +702,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
|
||||
let nativeView;
|
||||
if (isAndroid) {
|
||||
if (this.recycleNativeView) {
|
||||
if (this._recycleNativeView) {
|
||||
nativeView = <android.view.View>getNativeView(context, this.typeName);
|
||||
}
|
||||
|
||||
@@ -699,6 +712,10 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
|
||||
this._androidView = nativeView;
|
||||
if (nativeView) {
|
||||
if (this._isPaddingRelative === undefined) {
|
||||
this._isPaddingRelative = nativeView.isPaddingRelative();
|
||||
}
|
||||
|
||||
let result: android.graphics.Rect = (<any>nativeView).defaultPaddings;
|
||||
if (result === undefined) {
|
||||
result = org.nativescript.widgets.ViewHelper.getPadding(nativeView);
|
||||
@@ -789,7 +806,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
}
|
||||
|
||||
const nativeView = this.nativeView;
|
||||
if (nativeView && this.recycleNativeView && isAndroid) {
|
||||
if (nativeView && this._recycleNativeView && isAndroid) {
|
||||
const nativeParent = isAndroid ? (<android.view.View>nativeView).getParent() : (<UIView>nativeView).superview;
|
||||
if (!nativeParent) {
|
||||
putNativeView(this._context, this);
|
||||
@@ -979,7 +996,7 @@ export const idProperty = new Property<ViewBase, string>({ name: "id", valueChan
|
||||
idProperty.register(ViewBase);
|
||||
|
||||
export function booleanConverter(v: string): boolean {
|
||||
let lowercase = (v + '').toLowerCase();
|
||||
const lowercase = (v + '').toLowerCase();
|
||||
if (lowercase === "true") {
|
||||
return true;
|
||||
} else if (lowercase === "false") {
|
||||
|
||||
@@ -50,15 +50,17 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
private _measuredWidth: number;
|
||||
private _measuredHeight: number;
|
||||
|
||||
private _isLayoutValid: boolean;
|
||||
private _cssType: string;
|
||||
|
||||
private _localAnimations: Set<am.Animation>;
|
||||
|
||||
_currentWidthMeasureSpec: number;
|
||||
_currentHeightMeasureSpec: number;
|
||||
|
||||
_setMinWidthNative: (value: Length) => void;
|
||||
_setMinHeightNative: (value: Length) => void;
|
||||
|
||||
private _isLayoutValid: boolean;
|
||||
private _cssType: string;
|
||||
|
||||
public _gestureObservers = {};
|
||||
|
||||
observe(type: GestureTypes, callback: (args: GestureEventData) => void, thisArg?: any): void {
|
||||
@@ -714,8 +716,35 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
|
||||
public createAnimation(animation: any): am.Animation {
|
||||
ensureAnimationModule();
|
||||
if (!this._localAnimations) {
|
||||
this._localAnimations = new Set();
|
||||
}
|
||||
animation.target = this;
|
||||
return new animationModule.Animation([animation]);
|
||||
const anim = new animationModule.Animation([animation]);
|
||||
this._localAnimations.add(anim);
|
||||
return anim;
|
||||
}
|
||||
|
||||
public _removeAnimation(animation: am.Animation): boolean {
|
||||
const localAnimations = this._localAnimations;
|
||||
if (localAnimations && localAnimations.has(animation)) {
|
||||
localAnimations.delete(animation);
|
||||
if (animation.isPlaying) {
|
||||
animation.cancel();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public resetNativeView(): void {
|
||||
if (this._localAnimations) {
|
||||
this._localAnimations.forEach(a => this._removeAnimation(a));
|
||||
}
|
||||
|
||||
super.resetNativeView();
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
|
||||
@@ -70,6 +70,7 @@ function initializeTouchListener(): void {
|
||||
}
|
||||
|
||||
export class View extends ViewCommon {
|
||||
private _isClickable: boolean;
|
||||
private touchListenerIsSet: boolean;
|
||||
private touchListener: android.view.View.OnTouchListener;
|
||||
|
||||
@@ -94,6 +95,7 @@ export class View extends ViewCommon {
|
||||
if (this.touchListenerIsSet) {
|
||||
this.nativeView.setOnTouchListener(null);
|
||||
this.touchListenerIsSet = false;
|
||||
this.nativeView.setClickable(this._isClickable);
|
||||
}
|
||||
|
||||
this._cancelAllAnimations();
|
||||
@@ -104,6 +106,11 @@ export class View extends ViewCommon {
|
||||
return this._gestureObservers && Object.keys(this._gestureObservers).length > 0
|
||||
}
|
||||
|
||||
public initNativeView(): void {
|
||||
super.initNativeView();
|
||||
this._isClickable = this.nativeView.isClickable();
|
||||
}
|
||||
|
||||
private setOnTouchListener() {
|
||||
if (this.nativeView && this.hasGestureObservers()) {
|
||||
this.touchListenerIsSet = true;
|
||||
|
||||
4
tns-core-modules/ui/core/view/view.d.ts
vendored
4
tns-core-modules/ui/core/view/view.d.ts
vendored
@@ -558,6 +558,10 @@ export abstract class View extends ViewBase implements ApplyXmlAttributes {
|
||||
* @private
|
||||
*/
|
||||
_redrawNativeBackground(value: any): void;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_removeAnimation(animation: Animation): boolean
|
||||
//@endprivate
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user