FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(android): nested fragment disappears on parent fragment removal (… · NativeScript/NativeScript@c084660 · GitHub

Commit c084660

Browse files
authored
fix(android): nested fragment disappears on parent fragment removal (#6677)
1 parent 43dddbb commit c084660

6 files changed

Lines changed: 43 additions & 20 deletions

File tree

‎tns-core-modules/ui/frame/fragment.android.ts‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { AndroidFragmentCallbacks, setFragmentCallbacks, setFragmentClass } from "./frame";
22

33
@JavaProxy("com.tns.FragmentClass")
4-
class FragmentClass extends android.support.v4.app.Fragment {
4+
class FragmentClass extends org.nativescript.widgets.FragmentBase {
55
// This field is updated in the frame module upon `new` (although hacky this eases the Fragment->callbacks association a lot)
66
private _callbacks: AndroidFragmentCallbacks;
7-
7+
88
constructor() {
99
super();
1010
return global.__native(this);
@@ -15,8 +15,7 @@ class FragmentClass extends android.support.v4.app.Fragment {
1515
}
1616

1717
public onCreateAnimator(transit: number, enter: boolean, nextAnim: number): android.animation.Animator {
18-
let result = this._callbacks.onCreateAnimator(this, transit, enter, nextAnim, super.onCreateAnimator);
19-
return result;
18+
return this._callbacks.onCreateAnimator(this, transit, enter, nextAnim, super.onCreateAnimator);
2019
}
2120

2221
public onStop(): void {

‎tns-core-modules/ui/frame/fragment.transitions.android.ts‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,20 @@ export function _setAndroidFragmentTransitions(
8686
name = navigationTransition.name ? navigationTransition.name.toLowerCase() : "";
8787
}
8888

89-
let useLollipopTransition = name && (name.indexOf("slide") === 0 || name === "fade" || name === "explode") && sdkVersion() >= 21;
89+
let useLollipopTransition = !!(name && (name.indexOf("slide") === 0 || name === "fade" || name === "explode") && sdkVersion() >= 21);
90+
// [nested frames / fragments] force disable lollipop transitions in case nested fragments
91+
// are detected as applying dummy animator to the nested fragment with the same duration as
92+
// the exit animator of the removing parent fragment as a workaround for
93+
// https://code.google.com/p/android/issues/detail?id=55228 works only if custom animations are
94+
// used
95+
// NOTE: this effectively means you cannot use Explode transition in nested frames scenarios as
96+
// we have implementations only for slide, fade, and flip
97+
if (currentFragment &&
98+
currentFragment.getChildFragmentManager() &&
99+
currentFragment.getChildFragmentManager().getFragments().toArray().length > 0) {
100+
useLollipopTransition = false;
101+
}
102+
90103
if (!animated) {
91104
name = "none";
92105
} else if (transition) {

‎tns-core-modules/ui/frame/frame-common.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
457457
}
458458

459459
public _onRootViewReset(): void {
460-
this._removeFromFrameStack();
461460
super._onRootViewReset();
461+
this._removeFromFrameStack();
462462
}
463463

464464
get _childrenCount(): number {

‎tns-core-modules/ui/frame/frame.android.ts‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,12 @@ export class Frame extends FrameBase {
209209
}
210210

211211
public _onRootViewReset(): void {
212-
this.disposeCurrentFragment();
213212
super._onRootViewReset();
213+
214+
// call this AFTER the super call to ensure descendants apply their rootview-reset logic first
215+
// i.e. in a scenario with nested frames / frame with tabview let the descendandt cleanup the inner
216+
// fragments first, and then cleanup the parent fragments
217+
this.disposeCurrentFragment();
214218
}
215219

216220
onUnloaded() {
@@ -223,11 +227,6 @@ export class Frame extends FrameBase {
223227
}
224228

225229
private disposeCurrentFragment(): void {
226-
// when interacting with nested fragments it seems Android is smart enough
227-
// to automatically remove child fragments when parent fragment is removed;
228-
// however, we must add a fragment.isAdded() guard as our logic will try to
229-
// explicitly remove the already removed child fragment causing an
230-
// IllegalStateException: Fragment has not been attached yet.
231230
if (!this._currentEntry ||
232231
!this._currentEntry.fragment ||
233232
!this._currentEntry.fragment.isAdded()) {
@@ -742,7 +741,13 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
742741
}
743742

744743
@profile
745-
public onCreateAnimator(fragment: android.support.v4.app.Fragment, transit: number, enter: boolean, nextAnim: number, superFunc: Function): android.animation.Animator {
744+
public onCreateAnimator(fragment: org.nativescript.widgets.FragmentBase, transit: number, enter: boolean, nextAnim: number, superFunc: Function): android.animation.Animator {
745+
// HACK: FragmentBase class MUST handle removing nested fragment scenario to workaround
746+
// https://code.google.com/p/android/issues/detail?id=55228
747+
if (!enter && fragment.getRemovingParentFragment()) {
748+
return superFunc.call(fragment, transit, enter, nextAnim);
749+
}
750+
746751
let nextAnimString: string;
747752
switch (nextAnim) {
748753
case AnimationType.enterFakeResourceId: nextAnimString = "enter"; break;

‎tns-core-modules/ui/tab-view/tab-view.android.ts‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function initializeNativeClasses() {
4545
return;
4646
}
4747

48-
class TabFragmentImplementation extends android.support.v4.app.Fragment {
48+
class TabFragmentImplementation extends org.nativescript.widgets.FragmentBase {
4949
private tab: TabView;
5050
private index: number;
5151

@@ -55,7 +55,6 @@ function initializeNativeClasses() {
5555
}
5656

5757
static newInstance(tabId: number, index: number): TabFragmentImplementation {
58-
5958
const args = new android.os.Bundle();
6059
args.putInt(TABID, tabId);
6160
args.putInt(INDEX, index);
@@ -79,10 +78,6 @@ function initializeNativeClasses() {
7978

8079
return tabItem.view.nativeViewProtected;
8180
}
82-
83-
public onDestroyView() {
84-
super.onDestroyView();
85-
}
8681
}
8782

8883
const POSITION_UNCHANGED = -1;
@@ -560,8 +555,13 @@ export class TabView extends TabViewBase {
560555
}
561556

562557
public _onRootViewReset(): void {
563-
this.disposeCurrentFragments();
564558
super._onRootViewReset();
559+
560+
// call this AFTER the super call to ensure descendants apply their rootview-reset logic first
561+
// i.e. in a scenario with tab frames let the frames cleanup their fragments first, and then
562+
// cleanup the tab fragments to avoid
563+
// android.content.res.Resources$NotFoundException: Unable to find resource ID #0xfffffff6
564+
this.disposeCurrentFragments();
565565
}
566566

567567
private disposeCurrentFragments(): void {

‎tns-platform-declarations/android/org.nativescript.widgets.d.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@
164164
public verticalAlignment: VerticalAlignment;
165165
}
166166

167+
export class FragmentBase extends android.support.v4.app.Fragment {
168+
constructor();
169+
170+
public getRemovingParentFragment(): android.support.v4.app.Fragment;
171+
}
172+
167173
export enum Stretch {
168174
none,
169175
aspectFill,

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL