ncapdevi / fragnav Goto Github PK
View Code? Open in Web Editor NEWAn Android library for managing multiple stacks of fragments
An Android library for managing multiple stacks of fragments
Hi Nick,
In attempting to integrate your library i've come across two issues that I was hoping you'd be able to fix.
First, the FravNavController constructor doesn't allow for passing in a TransactionListener, so when the initial fragment stack is selected the listener.onTabTransaction
method is never invoked. This is because the transactionListener
is null in the initialize
function.
Second, I'm attempting to place the construction of the FragNavController in the onCreate
function of a base activity. I'm running into issues where a child class instantiates some class variables that are needed by the root fragment, but since getRootFragment(i)
is called immediately after instantiating the FragNavController my root fragment is created with null data; The child activity's onCreate
hasn't had a chance to run yet. It would be great if we could set the starting index to -1
so that no fragment is instantiated allowing us to call switchTab
at a point when we're ready to show the initial fragment.
I hacked something together to verify it works, but would love for you to take a look at it since you know the library better than I do.
Thanks!
Nick
You already ran out of sync between releases and master branch again. That's quite annoying since I like to see a branch, which is in the same state as the current release. Otherwise, it's difficult to track the actual state of the release and look something up in the correct version of the sample app.
I'd suggest only merging to master if you make a release. Or alternatively, use a distinct release branch.
Hi,
Is there a way I can show a full screen sized fragment (like showing a full screen image for example) when a button is clicked on one of the child fragments?
I'm using Roughike's BottomBar along with FragNav.
Thank You
Hi ncapdevi,
FragNavController with onSaveInstanceState function
I'm using FragNav together with bottmbar:
compile 'com.roughike:bottom-bar:1.3.4'
I updated from your former master branch state (something after version 1.0.3) to 1.2.2.
I did that by only exting the constructor call by the starting index.
navController = new FragNavController( savedInstanceState, getSupportFragmentManager(), R.id.container, fragments, INDEX_1 );
Now, when I press the back button on "base fragment" of a tab, I see an "empty fragment".
My onBackPressed implementation:
@Override
public void onBackPressed()
{
if ( popFragment() )
{
return;
}
super.onBackPressed();
}
@Override
public boolean popFragment()
{
if ( navController != null && navController.getCurrentStack() != null && !navController.getCurrentStack().empty() )
{
navController.pop();
return true;
}
return false;
}
If I select another tab, and then select the "empty" tab again. I run into this crash:
java.lang.IllegalStateException: Either you haven't past in a fragment at this index in your constructor, or you haven'tprovided a way to create it while via your RootFragmentListener.getRootFragment(index)
at com.ncapdevi.fragnav.FragNavController.getRootFragment(FragNavController.java:417)
at com.ncapdevi.fragnav.FragNavController.switchTab(FragNavController.java:204)
at com.anfema.kidswatch.activities.MainActivity$1.onMenuTabSelected(MainActivity.java:260)
I did not implement getRootFragment
in my app because I pass the base fragments through the constructor call.
I found that it will detach fragment once switch tabs, if so, fragments will recreate view while attach and some operation like data load will be performed every time.
can we have a option to not detach/attach just hide/show fragment?
Work:
fragNavController.pushFragment(f);
Not work:
fragNavController.replaceFragment(f);
Crash Log:
03-15 15:29:59.557 10878-10878/com.dante.diary E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dante.diary, PID: 10878
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getVisibility()' on a null object reference
at android.support.v4.app.FragmentTransitionCompat21.captureTransitioningViews(FragmentTransitionCompat21.java:364)
at android.support.v4.app.FragmentTransition.configureEnteringExitingViews(FragmentTransition.java:901)
at android.support.v4.app.FragmentTransition.access$100(FragmentTransition.java:37)
at android.support.v4.app.FragmentTransition$2.run(FragmentTransition.java:367)
at android.support.v4.app.OneShotPreDrawListener.onPreDraw(OneShotPreDrawListener.java:64)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2055)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Thx!
Hi I just want to let you know that if you add a Fragment inside the XML layout and try to instantiate it after you have created an instance of FragNavController, then the Fragment is null when you do this :
XMLFragment fragment = (XMLFragment)getSupportFragmentManager().findFragmentById(R.id.xml_fragment);
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<fragment
android:id="@+id/xml_fragment"
android:name="com.ncapdevi.sample.fragments.XMLFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottomBar" />
<com.roughike.bottombar.BottomBar
android:id="@+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:background="@color/colorPrimary"
app:bb_tabXmlResource="@xml/menu_bottombar" />
</RelativeLayout>
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.ncapdevi.sample.R.layout.activity_bottom_tabs);
mBottomBar = (BottomBar) findViewById(R.id.bottomBar);
mBottomBar.selectTabAtPosition(INDEX_NEARBY);
mNavController =
new FragNavController(savedInstanceState, getSupportFragmentManager(), R.id.container,this,5, INDEX_NEARBY);
mNavController.setTransactionListener(this);
XMLFragment fragment = (XMLFragment)getSupportFragmentManager().findFragmentById(R.id.xml_fragment);
}
but it works as expected when you do this:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.ncapdevi.sample.R.layout.activity_bottom_tabs);
mBottomBar = (BottomBar) findViewById(R.id.bottomBar);
mBottomBar.selectTabAtPosition(INDEX_NEARBY);
XMLFragment fragment = (XMLFragment)getSupportFragmentManager().findFragmentById(R.id.xml_fragment);
mNavController =
new FragNavController(savedInstanceState, getSupportFragmentManager(), R.id.container,this,5, INDEX_NEARBY);
mNavController.setTransactionListener(this);
}
My app was crashing because of this
I've recently stumbled upon this library and just started using it because it suits my needs. Given the fact I am a beginner I wanted to know if you can provide some sample or code snippet of how I can use onTabTransaction
and onFragmentTransaction
?
For example, in one of the tabs I am pushing a second fragment
. If I go to the hardware back button, it does what it is supposed to do, pops the fragment
. But, I also have a custom toolbar
in that particular fragment
which has a back button. I would like to pop the fragment
when I click the button. How can I implement this functionality? Also, something like if the fragment
is an instance of the root fragment
but it's not the root, I would like to show a back button.
I am interested on how to use these kind of functionalities. if it's not hassle please provide some more information.
Cheers!
hi I use the lib and can't show bottombar title
Hi,
is it possible to iterate through all fragments ? I know I can use getCurrentStack()
and then loop for the Fragment
s into the current stack but how can I access other stacks too?
Thanks!
:processDebugManifest
/AndroidManifest.xml:11:13-40 Error:
Attribute application@supportsRtl value=(false) from AndroidManifest.xml:11:13-40
is also present at [com.ncapdevi:frag-nav:1.0.2] AndroidManifest.xml:14:9-35 value=(true).
Suggestion: add 'tools:replace="android:supportsRtl"' to <application> element at AndroidManifest.xml:8:5-25:19 to override.
See http://g.co/androidstudio/manifest-merger for more information about the manifest merger.
:processDebugManifest FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':processDebugManifest'.
> Manifest merger failed : Attribute application@supportsRtl value=(false) from AndroidManifest.xml:11:13-40
is also present at [com.ncapdevi:frag-nav:1.0.2] AndroidManifest.xml:14:9-35 value=(true).
Suggestion: add 'tools:replace="android:supportsRtl"' to <application> element at AndroidManifest.xml:8:5-25:19 to override.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 1.963 secs
This forced me to add android:supportsRtl="true"
to my app's manifest.
Could you provide some animation when switching fragment? Like fadein and slidein, these could be very useful.
Using version 2.0.0 and trying to get popFragment to perform a transition. So far, I can only get pushFragment to display a transition.
public void pushMyFragment(Fragment fragment, int tabIndex) {
FragNavTransactionOptions.Builder transactionOptionsBuilder =
FragNavTransactionOptions.newBuilder()
.customAnimations(R.anim.slide_in_right, R.anim.do_not_move);
FragNavTransactionOptions transactionOptions = transactionOptionsBuilder.build();
closeDrawer();
selectTab(tabIndex);
if (navController.getCurrentStackIndex() != tabIndex) {
navController.switchTab(tabIndex);
}
navController.pushFragment(fragment, transactionOptions);
}
public void popMyFragment(int tabIndex) {
FragNavTransactionOptions.Builder transactionOptionsBuilder =
FragNavTransactionOptions.newBuilder()
.customAnimations(R.anim.do_not_move, R.anim.slide_out_left);
FragNavTransactionOptions transactionOptions = transactionOptionsBuilder.build();
selectTab(tabIndex);
if (navController.getCurrentStackIndex() != tabIndex) {
navController.switchTab(tabIndex);
}
navController.popFragment(transactionOptions);
}
Always, when popping, the fragment just dissapears. Any ideas?
Is it possible to add support for default transition animations ?
Hi,
I'm using your library and I'm trying to implement it with my app. But I've a problem with the onBackPressed() implementation.
I've for example 1 rootfragment and 1 normal fragment. When I click on a button on the rootfragment for example, I use pushfrangment() to add the normal fragment. But when I click on back, I can't come back to the rootfragment ? It seems you use this :
public boolean canPop() {
return this.getCurrentStack().size() > 1;
}
Why 1 ? is it of purpose ?
Sorry if my english is not very good ^^
Thanks in advance.
Could you provide method to add sharedElement when using pushFragment
?
By now, I use:
Fragment fragment = ViewerFragment.newInstance(url);
fragment.setSharedElementEnterTransition(new AutoTransition());
getFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack("")
.addSharedElement(sharedView, sharedName)
.commit();
```
Is this working properly on the version 2 of bottombar?
i get back a white bar when trying to remove it ..
Hello
Thank for your library. I use this compile 'com.ncapdevi:frag-nav:1.0.3'
But I want use last version with savedInstant and other fix
#21
How can I use last merge?
I set navigationListener, but suprisingly both methods are not called. My implementation:
mNavController.setNavListener(new FragNavController.NavListener() {
@Override
public void onTabTransaction(Fragment fragment, int index) {
Logger.d("onTabTransaction: %s, index: %d", fragment.getClass().getCanonicalName(), index);
fragment.onResume();
}
@Override
public void onFragmentTransaction(Fragment fragment) {
Logger.d("onTabTransaction: %s", fragment.getClass().getCanonicalName());
fragment.onResume();
}
});
After upgrading to 1.2.4
version from 1.0.3
, I get exceptions in my app sometimes when the application started from the background (minimized, then opened after some time):
java.lang.RuntimeException: Unable to start activity ComponentInfo{my.app.debug/my.app.ui.activity.MainActivity}: java.lang.NullPointerException: Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.NullPointerException: Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim' on a null object reference
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:770)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:594)
at com.ncapdevi.fragnav.FragNavController.executePendingTransactions(FragNavController.java:498)
at com.ncapdevi.fragnav.FragNavController.clearFragmentManager(FragNavController.java:514)
at com.ncapdevi.fragnav.FragNavController.initialize(FragNavController.java:387)
at com.ncapdevi.fragnav.FragNavController.<init>(FragNavController.java:120)
at my.app.ui.activity.MainActivity.initFragments(MainActivity.java:203)
at my.app.ui.activity.MainActivity.initViews(MainActivity.java:139)
at my.app.ui.activity.MainActivity.init(MainActivity.java:130)
at my.app.ui.activity.MainActivity.onCreate(MainActivity.java:97)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
... 9 more
My initialization of FragNavController:
mNavController = new FragNavController(savedInstanceState, getSupportFragmentManager(), R.id.container, fragments, FragNavController.TAB1);
Thank you!
Any solution for this please? Basically the fragments are re-creating each time I do that, adding the new fragment to the bottom of the screen/fragment.
Hello,
I really like FragNav it's working great in my app. My confusions come in when I need to find a fragment in a stack. Right now I have two fragments (Fragment A and B). I created an interface in Fragment B which will pass data back to Fragment A. My Activity implements the Listener created in Fragment B, but I run into the issue of finding Fragment A in the stack to pass the data to it.
Anyway to access the getSupportFragmentManager()
in FragNav to findViewById()
?
Hi!
Excuse my curiosity but is there any reason to setup minSdkVersion to 15? Why it isn't 14?
How would I go about navigating to a fragment that's not in my bottom bar menu?
For example, my bottom bar has 5 options, but I also have a settings button I display at the top of the page. Currently, on clicking that button I push the settings fragment.
Say I'm on Fragment1, and I click settings. I get taken to the settings fragment.
I then use the bottom bar to go to Fragment2. If I now hit the tab on the bottom bad for fragment1, I see the settings page again, instead of fragment1. How do I pop the settings fragment when I leave it to navigate to another bottom bar tab?
I have used : -
FragNavController.setTransitionMode();
but can't succeed. It's due to library or i am doing something wrong ,can't guess.
An error occurs stating that.
Non-static method 'setTransition()' cannot be referenced from static context
And i have also not found any example to show it's working state.
Can you assist me ?
Hi I was wondering why didn't you use the child fragment managers but you decided to keep track of the stacks of fragments yourself. Wouldn't it be good if for each tab you have a child fragment manager that takes care of the stacks ?
What does push mean? Does it mean add
?
If so, I think to use the same name of official fragment API would be better.
This library could be very useful to manage Navigation Drawer, but there is a limitation of 5 "tab fragments".
Could you provide a way to override this please ?
How do I navigate through the basefragments using onBackPressed without closing the BottomActivity?
When I use setReenterTransition
, I found that reenter transition wasn't shown.
Then I find pushFragment
may not work as I expect.
I use following:
private void add(Fragment f) {
activity.getSupportFragmentManager().beginTransaction()
.hide(this)
.add(R.id.container, f)
.addToBackStack("")
.commit();
}
I read the source code of PushFragment, found that it detach
the current fragment. Why detach
?
When back pressed, I want to return the old fragment and old state. Any method?
@ncapdevi: Great library!
I'm looking to implement FragNav into a single activity application with tabs, and was wondering if you'd given any thought to more complex transitions, or FragmentTransaction behavior in general? Specifically, I'm interested in utilizing shared element transitions as explained here: https://medium.com/@bherbst/fragment-transitions-with-shared-elements-7c7d71d31cbb#.y6g2ft1sv.
The immediate fix for this could be to overload the pushFragment and popFragment methods to allow passing in a List
of Pair
s of shared elements, but then you go down the slippery slope of adding new params for every property on a FragmentTransaction. To make things more extensible I thought about passing in a callback that takes in a FragmentTransaction and let's the caller modify properties on it before the FragNavController commits the transaction. This, however, opens up the possibility for a developer to completely screw themselves.
Do you have any thoughts on this?
Thanks!
Nick
Hi, I'm not a very experienced Android developer. I'm trying to use your library together with BottomBar for 3 Fragments.
The fragments are loaded. But it seems that it always stays on the first fragment. How should I create my fragments to make it work properly? Right now all 3 fragments extend that Fragment class from the Android support library.
null pointer
I've got a question: if I have a fragment backstack and want to pop to particular fragment in this backstack. Is there any possibility to find this particular fragment and return to this point within current backstack?
My code for this:
String accountTag = AccountsFragment.class.getSimpleName();
AccountsFragment fragment = (AccountsFragment) getSupportFragmentManager().findFragmentByTag(accountTag);
if (mainPresenter.hasLocallySavedUsers()) {
if (fragment != null) {
getSupportFragmentManager().popBackStackImmediate(accountTag, 0);
} else {
String welcomeTag = WelcomeFragment.class.getSimpleName();
WelcomeFragment welcomeFragment = (WelcomeFragment) getSupportFragmentManager().findFragmentByTag(welcomeTag);
if (welcomeFragment != null) {
getSupportFragmentManager().popBackStackImmediate(welcomeTag, 0);
} else {
startAccounts(accountsButton);
}
}
} else {
startAccounts(accountsButton);
}
Hello I am using this Material Drawer library to create drawer & I have BottomNavigationView in first fragment of drawer.
So I am using this to handle back but not able to maintain back it with BottomNavigationView child fragment. Please help me on this
@Override
public void onBackPressed() {
if (mDrawer != null && mDrawer.isDrawerOpen()) {
mDrawer.closeDrawer();
} else if (mNavController.getCurrentStack().size() > 1) {
mNavController.popFragment();
} else {
super.onBackPressed();
}
}
@Override
public Fragment getRootFragment(int i) {
switch (i) {
case INDEX_RECENTS:
return ExploreBaseFragment.newInstance(0); //this is fragment with BottomNavigationView having 3 child fragment
case INDEX_FAVORITES:
return MyUploadsFragment.newInstance(0);
case INDEX_NEARBY:
return CategoryFragment.newInstance(0);
}
throw new IllegalStateException("Need to send an index that we know");
}
Specifically this occurs on line 84 in the BottomTabsActivity and line 76 in the NavDrawerActivity.
What is the purpose of this? And why is it broken in these places in the sample app? Commenting them out allows the app to still run.
After the long awaited release, I could finally get rid of frag-nav as a locale module and include it as a dependency. Thank you for that! :)
Unfortunately, I found an issue occurring in both versions 1.1.0 and 1.2.0:
Previously I could click on a tab, which already was selected, and go back to the first fragment of the tab's stack. No matter if there were one or multiple fragments on the stack.
Now, I just see an empty fragment.
I assume this is a bug or must the library be used differently now?
Hi, your library on jcenter don't have the last commits (Support For onSaveInstanceState)
Can you add example about use shared element ? I add shared element and transition to FragNavTransactionOptions but animation doesn't shown.
Update your sample app and library, because it's without onSaveInstanceState
Is there a possibility to save the current state and the current fragment etc. when onSaveInstanceState is called in the activity?
This happens on line 55 in NavDrawerActivity and on line 39 in BottomTabsActivity. However, simply removing the savedInstanceState parameter altogether from both locations allows the app to compile and run.
What's the purpose of trying to pass in this parameter?
How to accomplish something like in Google example where they click on Kodaline album in Music tab, and then new view is showing on top without disappearing bottom bar?
Is it possible to keep the current fragment state?
Btw this library is awesome! It saved me a couple of hours coding...
I use roughike BottomBar library
any idea how to solve this ??
I'm currently checking the demo app and more precisely the sample with the Bottom bar and I don't understand one thing:
I read in BottomTabsActivity
's code :
mNavController =
new FragNavController(savedInstanceState, getSupportFragmentManager(), R.id.container,this,5, INDEX_NEARBY)
where INDEX_NEARBY corresponds to the 3rd tab but when I run the app the initially selected tab is the 1st one (The one named Recents
) and not the third tab.
I think there is something wrong with the doc or I'm reading it wrongly :
startingIndex - The initial tab index to be used must be in range of rootFragments size
Please review it and let me know,
Thanks
I am testing the Bottom Tab demo and there is something that I don't quite understand. If I have opened 4 sub-fragments and then press on the back button, then onCreateView will be called on the previous Fragment, but the View is already created. So the Views are being created twice. The mBotton is already created before mButton = (Button) view.findViewById(R.id.button); is called. Is this the expected behaviour?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.