Dimitris Poulopoulos
Dimitris Poulopoulos

Reputation: 1159

Android FragmentTransaction Replace method

I have a problem passing arguments down to the fragment from my main activity. getArguments method returns null but at the same time the fragment displays the arguments I'm trying to pass but in a different position. I'm sure it has to do with the container I'm replacing on the replace method.

My main activity:

public class MainActivity extends AppCompatActivity {

    private final String FRAGMENT_TAG = "fragment_tag";
    public static final String USER_NAME = "userName";
    public static final String USER_PASSWORD = "userPassword";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        User user = getIntent().getParcelableExtra(LoginActivityFragment.SERVER_MESSAGE);
        Bundle bundle = new Bundle();
        bundle.putString(USER_NAME, user.getUser_name());
        bundle.putString(USER_PASSWORD, user.getUser_password());

        if (user != null) {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            MainActivityFragment fragment = (MainActivityFragment) getSupportFragmentManager()
                    .findFragmentByTag(FRAGMENT_TAG);
            if (fragment != null) {
                ft.replace(android.R.id.content, fragment);
                ft.commit();
            } else {
                MainActivityFragment newFragment = new MainActivityFragment();
                ft.replace(android.R.id.content, newFragment, FRAGMENT_TAG);
                newFragment.setArguments(bundle);
                ft.commit();
            }
        }
    }
}

My MainActivityFragment:

public class MainActivityFragment extends Fragment {

    private final String ERROR = "Error";

    public MainActivityFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        TextView username = (TextView) rootView.findViewById(R.id.username_test);
        TextView password = (TextView) rootView.findViewById(R.id.pass_test);

        Bundle bundle = getArguments();
        try {
            username.setText(bundle.getString(MainActivity.USER_NAME));
            password.setText(bundle.getString(MainActivity.USER_PASSWORD));
        } catch (Exception e) {
            Log.e(ERROR, "Error: " + e.getMessage());
        }
        return rootView;
    }
}

MainActivity Layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
    android:fitsSystemWindows="true"
    tools:context="com.msc.ebla.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay">

            <SearchView
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            </SearchView>

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

</android.support.design.widget.CoordinatorLayout>

content_main Layout

<fragment 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:id="@+id/fragment"
    android:name="com.msc.ebla.MainActivityFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:layout="@layout/fragment_main" />

MainActivityFragment Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.msc.ebla.MainActivityFragment"
    tools:showIn="@layout/activity_main">

    <TextView
        android:id="@+id/username_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="user"/>

    <TextView
        android:id="@+id/pass_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="pass"/>

    <ListView
        android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

    </ListView>


</LinearLayout>

And here is a screenshot of the emulator when I'm passing testName and testPass as arguments:

enter image description here

Upvotes: 0

Views: 1486

Answers (2)

PPartisan
PPartisan

Reputation: 8231

It looks as though you are loading two Fragments - one static, one dynamic. The static Fragment you declare in xml, and in this one getArguments() will always return null. The dynamic Fragment however should not.

I'd suggest you only use dynamic fragments. Replace:

<fragment 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:id="@+id/fragment"
    android:name="com.msc.ebla.MainActivityFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:layout="@layout/fragment_main" />

With

<FrameLayout 
    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:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:layout="@layout/fragment_main" />

And in your MainActivity, replace any reference to android.R.id.content with R.id.fragment_container

Edit:

By the way, I'd recommend using the newInstance() method to pass arguments to your Fragments as it's more reliable. Add this method declaration to MainActivityFragment:

public static MainActivityFragment newInstance(String userName, String userPassword) {

    Bundle args = new Bundle();
    args.putString(USER_NAME_KEY, userName);
    args.putString(USER_PASSWORD_KEY, userPassword);

    MainActivityFragment frag = new MainActivityFragment();
    frag.setArguments(args);

    return frag;

}

And instead of using new MainActivityFragment() to create a new instance, use MainActivityFragment.newInstance("user_name", "user_password). There's a bit more info on it here

Upvotes: 2

Hein
Hein

Reputation: 2683

For "getArgument()" return null issue:

You should set argument BEFORE calling replace() and commit(). So, change the code to something like this:

MainActivityFragment newFragment = new MainActivityFragment();
newFragment.setArguments(bundle);
ft.replace(android.R.id.content, newFragment, FRAGMENT_TAG);
ft.commit();

For Layout Issue :

Your content_main Layout is on the same level as AppBar layout. You have to put it **inside AppBar layout.**Like this:

<android.support.design.widget.CoordinatorLayout 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"
    android:fitsSystemWindows="true">

  <android.support.design.widget.AppBarLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay">

      <SearchView
          android:layout_width="match_parent"
          android:layout_height="wrap_content">

      </SearchView>



    </android.support.v7.widget.Toolbar>

    <include layout="@layout/content_main" />

  </android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>

Upvotes: 0

Related Questions