I try to dynamically replace fragments, if I create an object, it works. I try to get a fragment by its id, returns null. I do not see what is the error.

MainActivity.java

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { item1 it1; FragmentTransaction ft; FragmentManager fm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.setDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); it1 = new item1(); } @Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); ft = getSupportFragmentManager().beginTransaction(); ft.commit(); return super.onOptionsItemSelected(item); } @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { int id = item.getItemId(); fm = getSupportFragmentManager(); ft = getSupportFragmentManager().beginTransaction(); switch(id){ case R.id.nav_item1: ft.replace(R.id.containter, (item1) fm.findFragmentById(R.id.fragment_item1)); break; //case R.id.nav_item1: ft.replace(R.id.containter, it1); break; <-- так работает } ft.addToBackStack(null); ft.commit(); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; } 

}

item1.java

 public class item1 extends Fragment { private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; public static final String TAG = "item1Tag"; private String mParam1; private String mParam2; private OnFragmentInteractionListener mListener; public item1() { } public static item1 newInstance(String param1, String param2) { item1 fragment = new item1(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } setRetainInstance(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d("qqq","item2 "+this); return inflater.inflate(R.layout.fragment_item1, container, false); } public void onButtonPressed(Uri uri) { if (mListener != null) { mListener.onFragmentInteraction(uri); } } @Override public void onDetach() { super.onDetach(); mListener = null; } public interface OnFragmentInteractionListener { // TODO: Update argument type and name void onFragmentInteraction(Uri uri); } } 

fragment_item1.xml

 <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:id="@+id/fragment_item1" tools:context="com.example.robot.test.fragments.item1" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"></FrameLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_weight="1"> <TextView style="@style/textViewFr1" android:text="@string/_1" android:background="#F00" android:id="@+id/textView2" /> <TextView style="@style/textViewFr1" android:text="@string/_2" android:background="#0F0" android:id="@+id/textView3" /> <TextView style="@style/textViewFr1" android:text="@string/_3" android:background="#00F" android:id="@+id/textView4" /> </LinearLayout> </LinearLayout> 

    2 answers 2

    First, in one of the places you generally commit an empty transaction:

     @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); ft = getSupportFragmentManager().beginTransaction(); //Здесь предполагается что-то делать с фрагментами: add, replace, remove, etc ft.commit(); return super.onOptionsItemSelected(item); } 

    Secondly, in another place, where you have a switch , you are trying to replace the fragment with another one that has already been added to the activation, which will lead to a java.lang.IllegalStateException: Fragment already added error java.lang.IllegalStateException: Fragment already added . Arguments in the add and replace methods should be fragments that are not currently added to the activation, most often these are only fragments created.

    Thirdly, as a parameter of the findFragmentById method, findFragmentById must specify the fragment container id , and not the fragment root id , as you have done. That is, you need fm.findFragmentById(R.id.containter) , not fm.findFragmentById(R.id.fragment_item1) . But, once again, this will result in an IllegalStateException . You need to re-create the fragment (with the help of new ) or take the cached fragment if you are sure that it is not added to the activation (for such a fragment isAdded() == false ).

      What are you trying to get a fragment with fm , if you don’t add it there (in the container)? By creating the Instance of your fragment, and so you can dynamically replace fragments. I only advise you to use the fragment's newInstance(String param1, String param2) to initialize it, instead of the item1() constructor. This will avoid unnecessary duplication of the same fragment.

      That is, the fragment initialization should look like this: it1 = newInstance("", "") . Replacing a fragment in a container will look exactly the same as it is written on your line, which is placed in the comment.

      And, as pointed out by another commentator, you have an empty transaction in the onOptionsItemSelected(MenuItem item) .