ncapdevi / FragNav

An Android library for managing multiple stacks of fragments
1.5k stars 220 forks source link

Fragment defined in XML issue #46

Closed finneapps closed 7 years ago

finneapps commented 7 years ago

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

ncapdevi commented 7 years ago

@finneapps This is an interesting one. Could you tell me a little bit more about your use case and what you're trying to accomplish? The XML here seems wrong to me. You have two elements that are trying to fill up the entire space of the screen(both have width/height = match_parent ) :

    <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" />

This would make it so that you couldn't use the FragNavController as the view is being covered by the other fragment that is being displayed on top of the FrameLayout that you've indicated the fragments will be going in. Not sure I understand what you're trying to do.

finneapps commented 7 years ago

My code was just an example from your sample app where I quickly wanted to reproduce my nullpointer exception. In my current app that I am working on, I have reused some code from the Android Universal MusicPlayer app: https://github.com/googlesamples/android-UniversalMusicPlayer/blob/master/mobile/src/main/java/com/example/android/uamp/ui/BaseActivity.java

If you look at the onStart method, there is a findFragmentById method call. After I added the NavFrag that method returned null: here is the xml: https://github.com/googlesamples/android-UniversalMusicPlayer/blob/master/mobile/src/main/res/layout/activity_player.xml

ncapdevi commented 7 years ago

@finneapps Sorry for the delay on this one, I was on vacation for the last few days. I see now what you're referring to, thanks for the feedback. You are correct, as is the library won't work with XML based fragments, nor is it intended to. It's an interesting concept to explore, but would create some non-trivial challenges (I think, or maybe it's easy, I'd need to spend some more time on it actually).

That being said, is there any specific reason that you absolutely need to imbed the the fragment in the XML? There may be some advantages that I'm unaware of here, but this can all be done without embedding the fragment. Essentially all you'd need is something like:

 XMLFragment fragment = new XMLFragment();
        mNavController =
                new FragNavController(savedInstanceState, getSupportFragmentManager(), R.id.container,fragment);

Where you are creating the fragment on your own and passing it into the controller. Hope this helps!

finneapps commented 7 years ago

Hi. I don't need it to be imbedded in the Fragment, but I think it was worth mentioning. I have decided to continue to use your library and just create the Fragment in the Activity onCreate method instead. Thank you for your response.

ncapdevi commented 7 years ago

I'm actually going to mark this as an enhancement because it's worth looking into. Thanks for the feedback.