mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-18 22:01:42 +08:00
fix: android cleanup after new fragment handling
This commit is contained in:
@ -91,57 +91,6 @@ function initializeNativeClasses() {
|
||||
|
||||
return tabItem.nativeViewProtected;
|
||||
}
|
||||
|
||||
public onDestroyView() {
|
||||
const hasRemovingParent = this.getRemovingParentFragment();
|
||||
|
||||
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
|
||||
// TODO: Consider removing it when update to androidx.fragment:1.2.0
|
||||
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
|
||||
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(appResources, this.backgroundBitmap);
|
||||
this.owner._originalBackground = this.owner.backgroundColor || new Color('White');
|
||||
this.owner.nativeViewProtected.setBackgroundDrawable(bitmapDrawable);
|
||||
this.backgroundBitmap = null;
|
||||
|
||||
let thisView = this.getView();
|
||||
if (thisView) {
|
||||
let thisViewParent = thisView.getParent();
|
||||
if (thisViewParent && thisViewParent instanceof android.view.ViewGroup) {
|
||||
thisViewParent.removeView(thisView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
public onPause(): void {
|
||||
const hasRemovingParent = this.getRemovingParentFragment();
|
||||
|
||||
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
|
||||
// TODO: Consider removing it when update to androidx.fragment:1.2.0
|
||||
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
|
||||
this.backgroundBitmap = this.loadBitmapFromView(this.owner.nativeViewProtected);
|
||||
}
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private loadBitmapFromView(view: android.view.View): android.graphics.Bitmap {
|
||||
// Another way to get view bitmap. Test performance vs setDrawingCacheEnabled
|
||||
// const width = view.getWidth();
|
||||
// const height = view.getHeight();
|
||||
// const bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
|
||||
// const canvas = new android.graphics.Canvas(bitmap);
|
||||
// view.layout(0, 0, width, height);
|
||||
// view.draw(canvas);
|
||||
|
||||
view.setDrawingCacheEnabled(true);
|
||||
const bitmap = android.graphics.Bitmap.createBitmap(view.getDrawingCache());
|
||||
view.setDrawingCacheEnabled(false);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
@NativeClass
|
||||
@ -250,7 +199,7 @@ function iterateIndexRange(index: number, eps: number, lastIndex: number, callba
|
||||
@CSSType('BottomNavigation')
|
||||
export class BottomNavigation extends TabNavigationBase {
|
||||
private _contentView: org.nativescript.widgets.ContentLayout;
|
||||
private _contentViewId: number = -1;
|
||||
private _contentViewId = -1;
|
||||
private _bottomNavigationBar: org.nativescript.widgets.BottomNavigationBar;
|
||||
private _currentFragment: androidx.fragment.app.Fragment;
|
||||
private _currentTransaction: androidx.fragment.app.FragmentTransaction;
|
||||
@ -347,8 +296,8 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
const lastIndex = this.items.length - 1;
|
||||
const offsideItems = 0;
|
||||
|
||||
let toUnload = [];
|
||||
let toLoad = [];
|
||||
const toUnload = [];
|
||||
const toLoad = [];
|
||||
|
||||
iterateIndexRange(newIndex, offsideItems, lastIndex, (i) => toLoad.push(i));
|
||||
|
||||
@ -610,7 +559,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
tabItemSpec.backgroundColor = backgroundColor ? backgroundColor.android : this.getTabBarBackgroundArgbColor();
|
||||
|
||||
// COLOR
|
||||
let itemColor = this.selectedIndex === tabStripItem._index ? this._selectedItemColor : this._unSelectedItemColor;
|
||||
const itemColor = this.selectedIndex === tabStripItem._index ? this._selectedItemColor : this._unSelectedItemColor;
|
||||
const color = itemColor || titleLabel.style.color;
|
||||
tabItemSpec.color = color && color.android;
|
||||
|
||||
@ -669,7 +618,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
image = this.getFixedSizeIcon(image);
|
||||
}
|
||||
|
||||
let imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
|
||||
const imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
|
||||
|
||||
return {
|
||||
drawable: imageDrawable,
|
||||
@ -681,7 +630,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
}
|
||||
|
||||
private getIconInfo(tabStripItem: TabStripItem, color?: Color): IconInfo {
|
||||
let originalIcon = this.getOriginalIcon(tabStripItem, color);
|
||||
const originalIcon = this.getOriginalIcon(tabStripItem, color);
|
||||
|
||||
return this.getDrawableInfo(originalIcon);
|
||||
}
|
||||
@ -841,7 +790,7 @@ export class BottomNavigation extends TabNavigationBase {
|
||||
}
|
||||
|
||||
public setTabBarTextTransform(value: TextTransform): void {
|
||||
let items = this.tabStrip && this.tabStrip.items;
|
||||
const items = this.tabStrip && this.tabStrip.items;
|
||||
if (items) {
|
||||
items.forEach((tabStripItem) => {
|
||||
if (tabStripItem.label && tabStripItem.nativeViewProtected) {
|
||||
|
@ -81,7 +81,7 @@ function getAttachListener(): android.view.View.OnAttachStateChangeListener {
|
||||
export class Frame extends FrameBase {
|
||||
public _originalBackground: any;
|
||||
private _android: AndroidFrame;
|
||||
private _containerViewId: number = -1;
|
||||
private _containerViewId = -1;
|
||||
private _tearDownPending = false;
|
||||
private _attachedToWindow = false;
|
||||
private _cachedTransitionState: TransitionState;
|
||||
@ -190,7 +190,7 @@ export class Frame extends FrameBase {
|
||||
// simulated navigation (NoTransition, zero duration animator) and thus the fragment immediately disappears;
|
||||
// the user only sees the animation of the entering fragment as per its specific enter animation settings.
|
||||
// NOTE: we are restoring the animation settings in Frame.setCurrent(...) as navigation completes asynchronously
|
||||
let cachedTransitionState = getTransitionState(this._currentEntry);
|
||||
const cachedTransitionState = getTransitionState(this._currentEntry);
|
||||
|
||||
if (cachedTransitionState) {
|
||||
this._cachedTransitionState = cachedTransitionState;
|
||||
@ -425,7 +425,7 @@ export class Frame extends FrameBase {
|
||||
navigationTransition = null;
|
||||
}
|
||||
|
||||
let isNestedDefaultTransition = !currentEntry;
|
||||
const isNestedDefaultTransition = !currentEntry;
|
||||
|
||||
_setAndroidFragmentTransitions(animated, navigationTransition, currentEntry, newEntry, this._android.frameId, transaction, isNestedDefaultTransition);
|
||||
|
||||
@ -659,7 +659,7 @@ function clearEntry(entry: BackstackEntry): void {
|
||||
}
|
||||
|
||||
let framesCounter = 0;
|
||||
let framesCache = new Array<WeakRef<AndroidFrame>>();
|
||||
const framesCache = new Array<WeakRef<AndroidFrame>>();
|
||||
|
||||
class AndroidFrame extends Observable implements AndroidFrameDefinition {
|
||||
public rootViewGroup: android.view.ViewGroup;
|
||||
@ -689,7 +689,7 @@ class AndroidFrame extends Observable implements AndroidFrameDefinition {
|
||||
}
|
||||
|
||||
public get activity(): androidx.appcompat.app.AppCompatActivity {
|
||||
let activity: androidx.appcompat.app.AppCompatActivity = this.owner._context;
|
||||
const activity: androidx.appcompat.app.AppCompatActivity = this.owner._context;
|
||||
if (activity) {
|
||||
return activity;
|
||||
}
|
||||
@ -708,12 +708,12 @@ class AndroidFrame extends Observable implements AndroidFrameDefinition {
|
||||
}
|
||||
|
||||
public get actionBar(): android.app.ActionBar {
|
||||
let activity = this.currentActivity;
|
||||
const activity = this.currentActivity;
|
||||
if (!activity) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let bar = activity.getActionBar();
|
||||
const bar = activity.getActionBar();
|
||||
if (!bar) {
|
||||
return undefined;
|
||||
}
|
||||
@ -727,7 +727,7 @@ class AndroidFrame extends Observable implements AndroidFrameDefinition {
|
||||
return activity;
|
||||
}
|
||||
|
||||
let frames = _stack();
|
||||
const frames = _stack();
|
||||
for (let length = frames.length, i = length - 1; i >= 0; i--) {
|
||||
activity = frames[i].android.activity;
|
||||
if (activity) {
|
||||
@ -812,7 +812,7 @@ function startActivity(activity: androidx.appcompat.app.AppCompatActivity, frame
|
||||
function getFrameByNumberId(frameId: number): Frame {
|
||||
// Find the frame for this activity.
|
||||
for (let i = 0; i < framesCache.length; i++) {
|
||||
let aliveFrame = framesCache[i].get();
|
||||
const aliveFrame = framesCache[i].get();
|
||||
if (aliveFrame && aliveFrame.frameId === frameId) {
|
||||
return aliveFrame.owner;
|
||||
}
|
||||
@ -975,23 +975,11 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
||||
|
||||
@profile
|
||||
public onDestroyView(fragment: org.nativescript.widgets.FragmentBase, superFunc: Function): void {
|
||||
try {
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`${fragment}.onDestroyView()`, Trace.categories.NativeLifecycle);
|
||||
}
|
||||
|
||||
const hasRemovingParent = fragment.getRemovingParentFragment();
|
||||
|
||||
if (hasRemovingParent) {
|
||||
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), this.backgroundBitmap);
|
||||
this.frame._originalBackground = this.frame.backgroundColor || new Color('White');
|
||||
this.frame.nativeViewProtected.setBackgroundDrawable(bitmapDrawable);
|
||||
this.backgroundBitmap = null;
|
||||
}
|
||||
} finally {
|
||||
superFunc.call(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
@profile
|
||||
public onDestroy(fragment: androidx.fragment.app.Fragment, superFunc: Function): void {
|
||||
@ -1024,18 +1012,8 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
||||
|
||||
@profile
|
||||
public onPause(fragment: org.nativescript.widgets.FragmentBase, superFunc: Function): void {
|
||||
try {
|
||||
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
|
||||
// TODO: Consider removing it when update to androidx.fragment:1.2.0
|
||||
const hasRemovingParent = fragment.getRemovingParentFragment();
|
||||
|
||||
if (hasRemovingParent) {
|
||||
this.backgroundBitmap = this.loadBitmapFromView(this.frame.nativeViewProtected);
|
||||
}
|
||||
} finally {
|
||||
superFunc.call(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
@profile
|
||||
public onStop(fragment: androidx.fragment.app.Fragment, superFunc: Function): void {
|
||||
@ -1101,7 +1079,7 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
|
||||
// If there is savedInstanceState and moduleLoaded is false we are restarted but process was killed.
|
||||
// For now we treat it like first run (e.g. we are not passing savedInstanceState so no fragments are being restored).
|
||||
// When we add support for application save/load state - revise this logic.
|
||||
let isRestart = !!savedInstanceState && moduleLoaded;
|
||||
const isRestart = !!savedInstanceState && moduleLoaded;
|
||||
superFunc.call(activity, isRestart ? savedInstanceState : null);
|
||||
|
||||
// Try to get the rootViewId form the saved state in case the activity
|
||||
@ -1265,7 +1243,7 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
|
||||
}
|
||||
|
||||
@profile
|
||||
public onRequestPermissionsResult(activity: any, requestCode: number, permissions: Array<String>, grantResults: Array<number>, superFunc: Function): void {
|
||||
public onRequestPermissionsResult(activity: any, requestCode: number, permissions: Array<string>, grantResults: Array<number>, superFunc: Function): void {
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write('NativeScriptActivity.onRequestPermissionsResult;', Trace.categories.NativeLifecycle);
|
||||
}
|
||||
|
@ -82,49 +82,6 @@ function initializeNativeClasses() {
|
||||
|
||||
return tabItem.view.nativeViewProtected;
|
||||
}
|
||||
|
||||
public onDestroyView() {
|
||||
const hasRemovingParent = this.getRemovingParentFragment();
|
||||
|
||||
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
|
||||
// TODO: Consider removing it when update to androidx.fragment:1.2.0
|
||||
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
|
||||
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(appResources, this.backgroundBitmap);
|
||||
this.owner._originalBackground = this.owner.backgroundColor || new Color('White');
|
||||
this.owner.nativeViewProtected.setBackground(bitmapDrawable);
|
||||
this.backgroundBitmap = null;
|
||||
}
|
||||
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
public onPause(): void {
|
||||
const hasRemovingParent = this.getRemovingParentFragment();
|
||||
|
||||
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
|
||||
// TODO: Consider removing it when update to androidx.fragment:1.2.0
|
||||
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
|
||||
this.backgroundBitmap = this.loadBitmapFromView(this.owner.nativeViewProtected);
|
||||
}
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private loadBitmapFromView(view: android.view.View): android.graphics.Bitmap {
|
||||
// Another way to get view bitmap. Test performance vs setDrawingCacheEnabled
|
||||
// const width = view.getWidth();
|
||||
// const height = view.getHeight();
|
||||
// const bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
|
||||
// const canvas = new android.graphics.Canvas(bitmap);
|
||||
// view.layout(0, 0, width, height);
|
||||
// view.draw(canvas);
|
||||
|
||||
view.setDrawingCacheEnabled(true);
|
||||
const bitmap = android.graphics.Bitmap.createBitmap(view.getDrawingCache());
|
||||
view.setDrawingCacheEnabled(false);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
const POSITION_UNCHANGED = -1;
|
||||
@ -442,7 +399,7 @@ export class TabView extends TabViewBase {
|
||||
private _tabLayout: org.nativescript.widgets.TabLayout;
|
||||
private _viewPager: androidx.viewpager.widget.ViewPager;
|
||||
private _pagerAdapter: androidx.viewpager.widget.PagerAdapter;
|
||||
private _androidViewId: number = -1;
|
||||
private _androidViewId = -1;
|
||||
public _originalBackground: any;
|
||||
|
||||
constructor() {
|
||||
@ -549,8 +506,8 @@ export class TabView extends TabViewBase {
|
||||
const lastIndex = items.length - 1;
|
||||
const offsideItems = this.androidTabsPosition === 'top' ? this.androidOffscreenTabLimit : 1;
|
||||
|
||||
let toUnload = [];
|
||||
let toLoad = [];
|
||||
const toUnload = [];
|
||||
const toLoad = [];
|
||||
|
||||
iterateIndexRange(newIndex, offsideItems, lastIndex, (i) => toLoad.push(i));
|
||||
|
||||
@ -623,7 +580,7 @@ export class TabView extends TabViewBase {
|
||||
private disposeCurrentFragments(): void {
|
||||
const fragmentManager = this._getFragmentManager();
|
||||
const transaction = fragmentManager.beginTransaction();
|
||||
let fragments = <Array<any>>fragmentManager.getFragments().toArray();
|
||||
const fragments = <Array<any>>fragmentManager.getFragments().toArray();
|
||||
for (let i = 0; i < fragments.length; i++) {
|
||||
transaction.remove(fragments[i]);
|
||||
}
|
||||
@ -769,7 +726,7 @@ export class TabView extends TabViewBase {
|
||||
return getDefaultAccentColor(this._context);
|
||||
}
|
||||
[androidSelectedTabHighlightColorProperty.setNative](value: number | Color) {
|
||||
let tabLayout = this._tabLayout;
|
||||
const tabLayout = this._tabLayout;
|
||||
const color = value instanceof Color ? value.android : value;
|
||||
tabLayout.setSelectedIndicatorColors([color]);
|
||||
}
|
||||
|
Reference in New Issue
Block a user