Switching Between Fragment View

Switching between Fragment view

You should use a FrameLayout for that, that way you don't have to specify the fragment class in the XML and that way it is not limited to one class.

<FrameLayout 
android:id="@+id/contentFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />

and than you can set the fragment in the code like this

Fragment fragment = new YourFragment();

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.contentFragment, fragment);
transaction.commit();

How to switch between fragments during onclick?

Not sure what's the minimal fix to get your code working, but have you looked at using a Navigation Drawer to switch between the fragments? It looks to me like the example in the official docs matches pretty much exactly what you want to achieve.

A key is to have some kind of container for the currently displayed fragment (instead of using <fragment> like in your XML). For example:

 <FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />

Then, switching fragments goes something like this:

Fragment fragment = new Fragment2();
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();

Further reading: Add a Fragment to an Activity at Runtime in Android developer docs.

How can I switch between Fragments without destroying and re-creating them? (in a static-like way)

This is how I solved the problem succesfully:

  • First of all, all of the Fragments are declared as fields inside MainActivity class, as well as the variable selected, which will be used later:
public class MainActivity extends AppCompatActivity {

public KeyboardFragment keyboard_fragment = new KeyboardFragment();
public CameraFragment camera_fragment = new CameraFragment();
public SettingsFragment settings_fragment = new SettingsFragment();

Fragment selected = teclado_fragment;`

//...
  • Then, the following methods are defined inside the class too, where R.id.container is the FrameLayout or whatever view that is being used to display the inflated Fragments:
    private void createFragment(Fragment fragment){
getSupportFragmentManager().beginTransaction()
.add(R.id.container, fragment)
.hide(fragment)
.commit();
}
private void showFragment(Fragment fragment){
getSupportFragmentManager().beginTransaction()
.show(fragment)
.commit();
}
private void hideFragment(Fragment fragment){
getSupportFragmentManager().beginTransaction()
.hide(fragment)
.commit();
}
  • Finally, whatever menu's listener is defined this way inside MainActivity's OnCreate() method:
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

switch (item.getItemId()){
case R.id.camera:
hideFragment(selected);
selected = camera_fragment;
showFragment(seleccionado);
break;
case R.id.keyboard:
hideFragment(selected);
selected = keyboard_fragment;
showFragment(seleccionado);
break;
case R.id.settings:
hideFragment(selected);
selected = settings_fragment;
showFragment(seleccionado);
break;
}

return true;

}
};

This way, the menu just hides and shows Fragments visually, and they are only declared once not to be destroyed until the app closes, thus mantaining all their fields and views in memory as long as the app is running.

Switching between fragments in a layout with BottomNavigationView

You need to add the FrameLayout container within the layout file of the MainActivity(activity_main), onclick of the buttons in BottomNavigationView replace with the fragment. In this way you have a Activity and the fragments are shown within the activity, on click of each menu item you can invoke to replace it with the fragments.
This should resolve your problem.

You need to change the layout as below in activity_main.xml.

<android.support.constraint.ConstraintLayout 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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.main.MainActivity">

<FrameLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/navigation" />
</android.support.constraint.ConstraintLayout>

In the MainActivity code, you need to change as below:

case R.id.navigation_services:
// mTextMessage.setText(R.string.title_services);
CategoriesListFragment categoriesListFragment = new CategoriesListFragment();
fragmentTransaction.replace(R.id.frame, categoriesListFragment);
fragmentTransaction.commit();
return true;

In the fragment layout file change to LinearLayout:

<LinearLayout
android:id="@+id/categories_list_fragment"
android:name="com.alsowaygh.getitdone.view.services.CategoriesListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp">

<ListView
android:id="@+id/categoriesList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp" />

</LinearLayout>

EDIT

In the fragment code, change the layout to the name of the fragment layout file(R.layout.fragment_layout_name).

View rootView = inflater.inflate(R.layout.fragment_layout_name, container, false);
//initializing ListView
categoriesListView = rootView.findViewById(R.id.categoriesList);

Switching between Fragments with button

You missed a very important part is setContentView and before using replace you should have an existing fragment. So in onCreate change:

// set desired fragment for the first time
setFragment(this, new Fragment1());

Should be changed to:

   setContentView(R.layout.main_activity);//then
// set desired fragment for the first time
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();

// The id specified here identifies which ViewGroup to
// append the Fragment to.
ft.add(R.id.fragment_placeHolder, new Fragment1());
ft.commit();

Try to replace:

... activity.getFragmentManager()

With:

... getSupportFragmentManager()

and remove:

<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment1"
/>
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment2"
/>

Finally, change the switch_fragment to:

public void switch_fragment(View view) {
Fragment newFragment = null;
switch (view.getID()) {
case R.id.btn_2:
newFragment = new Fragment1();
break;
case R.id.btn_1:
newFragment = new Fragment2();
break;
}
setFragment(this, newFragment);
}

Switching between Fragments in a single Activity

Personally, I would not have any <fragment> elements.

Step #1: Populate your activity layout with a <FrameLayout> for the variable piece of the wizard, plus your various buttons.

Step #2: In onCreate() of the activity, run a FragmentTransaction to load the first wizard page into the FrameLayout.

Step #3: On the "next" click, run a FragmentTransaction to replace the contents of the FrameLayout with the next page of the wizard.

Step #4: Add in the appropriate smarts for disabling the buttons when they are unusable (e.g., back on the first wizard page).

Also, you will want to think about how the BACK button should work in conjunction with any on-screen "back" button in the wizard. If you want them to both behave identically, you will need to add each transaction to the back stack and pop stuff off the back stack when you handle the "back" button.

Someday, if nobody beats me to it, I'll try to create a wizard-by-way-of-fragments example, or perhaps a reusable component.

Saving list view items when switching between fragments

There are 2 parts to this answer

1) because you channelList = new ArrayList<>(); in onViewCreated every time onViewCreated is called you are wiping the list. Don't create a new list at this point, create empty list when you define the variable as a member of the class e.g. where the define what type channelList variable is.

When you switch to a new fragment it is usual for the old fragment instance to be put to the backstack and then re-used when you go back to it.

That new in onViewCreated is wiping the list when you are returning from the backstack at the moment.

e.g. the code will be something like

public class ChannelFragment extends Fragment {
private ArrayList<Channel> channelList = new ArrayList<>();
....

2)
Make you Channel object Parcelable

A tutorial https://www.vogella.com/tutorials/AndroidParcelable/article.html

You can then use onSaveInstanceState() and onRestoreInstanceState()

To use writeParcelableList or writeTypedList to store the list of channels if the Fragment gets destroyed

See https://www.dev2qa.com/android-fragment-save-retrieve-instance-state-example/



Related Topics



Leave a reply



Submit