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 variableselected
, 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
'sOnCreate()
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
Updated Sdk Version, Getting Classnotfoundexception: Android.Support.V4.View.Viewpager
Android App Integrated with Ok Google
How to Return String or JSONobject from Asynchronous Callback Using Retrofit
Floatingactionbutton Doesn't Hide
Okhttp Library - Networkonmainthreadexception on Simple Post
Android Studio- "Sdk Tools Directory Is Missing"
Android Sharedpreferences , How to Save a Simple Int Variable
How to Add a Hint in Spinner in Xml
Firebase: How to Set Default Notification Channel in Android App
Cannot Deserialize Instance of Object Out of Start_Array Token in Spring Webservice
How to Check If Running on UI Thread in Android
Android Studio Cannot Resolve R in Imported Project
How to Use Default Android Drawables
Why Is Listview.Getcheckeditempositions() Not Returning Correct Values