Changing content_main.xml onNavigationItemSelected - android

Is it possible to use multiple content_main.xml to change the MainActivity onNavigationItemSelected or is there a better way to do this?

the right way to It would be using multiple fragments in the main activity
GO to android studio and create a new project select the navigation drawer template you will get an example code now create fragments and add them on the navigation menu onNavigationItemSelected event.

If what you are looking for is to have different layouts for your items in
NavigationDrawer. Better consider using Fragments.
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_list) {
ListFragment fragment = new ListFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
} else if (id == R.id.nav_gallery) {
GalleryFragment fragment = new GalleryFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
return true;
}
this would help you to navigate to different fragment in your NavigationItem.
Hope it helps.

Related

Android Show Hide Fragment BottomNavigationView First Added Item Not Visible

I have a setup of 3 Fragments inside my main activity and want to navigate them using the BottomNavigationView. I want to add them once and then just switch between them without actually destroying the Fragments. Everything works fine except that the first fragment added to the SupportFragmentManager always disappears (tried changing the order so the problem is not with the Fragments themselves). Actually, it doesn't disappear but the last Fragment that occupied the container shows up.
Eg. I go to position 3, Fragment 3 shows up in the container and then click on position 1, Fragment 3 will still occupy the container. But if I tap position 2 Fragment 2 will appear. How I'm adding the Fragments:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, fragment1); //whatever gets added here ends up being invisible
ft.commitAllowingStateLoss();
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, fragment2);
ft.commitAllowingStateLoss();
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, fragment3);
ft.commitAllowingStateLoss();
How I'm switching between them using the OnNavigationItemSelectedListener:
private BottomNavigationView.OnNavigationItemSelectedListener navigation_listener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
Fragment previousFragment = getSupportFragmentManager().findFragmentById(R.id.container);
switch(item.getItemId()){
case R.id.bottom_navigation_bar_position1:
selectedFragment = fragment1;
break;
case R.id.bottom_navigation_bar_position2:
selectedFragment = fragment2;
break;
case R.id.bottom_navigation_bar_position3:
selectedFragment = fragment3;
break;
}
getSupportFragmentManager().beginTransaction().hide(previousFragment).commit();
getSupportFragmentManager().beginTransaction().show(selectedFragment).commit();
return true;
}
};
The XML menu navigation:
<item
android:id="#+id/bottom_navigation_bar_position1"
android:title="Title1"
android:icon="#drawable/ic1"
/>
<item
android:id="#+id/bottom_navigation_bar_position2"
android:title="Title2"
android:icon="#drawable/ic2"
/>
<item
android:id="#+id/bottom_navigation_bar_position3"
android:title="Title3"
android:icon="#drawable/ic3"
/>
Btw. just using replace() instead of show and hide works but that's not the goal...
I've also tested whether the first added Fragment exits (and doesn't get destroyed) and it indeed exists...
Thanks!
Instead of trying to show and hide fragment I solved the problem by managing the Fragments using a ViewPager and a SectionsPageAdapter. Once you link these two, use ViewPager.setOffscreenPageLimit(3) to make sure no Fragments get destroyed. My BottomNavigationView.OnNavigationItemSelectedListener looks like this now:
private BottomNavigationView.OnNavigationItemSelectedListener navigation_listener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.bottom_navigation_bar_position1:
tab_view_pager.setCurrentItem(0);
return true;
case R.id.bottom_navigation_bar_position2:
tab_view_pager.setCurrentItem(1);
return true;
case R.id.bottom_navigation_bar_position3:
tab_view_pager.setCurrentItem(2);
return true;
}
return false;
}
};
You have to set 0th position item selected for BottomNavigationView.OnNavigationItemSelectedListener. Find Menu bottom_navigation_bar_position1
I used this in my code, please refactor according to your needs
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(this);
Menu menu = navigation.getMenu();
this.onNavigationItemSelected(menu.findItem(R.id.navigation_doc));

Fragments overlapping while using replace() [duplicate]

I have a fragment inside a group activity and I want to replace it with another fragment:
FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
SectionDescriptionFragment bdf = new SectionDescriptionFragment();
ft.replace(R.id.book_description_fragment, bdf);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
It works fine when it is done as a seperate project without using activity group, every thing works fine in log cat as control goes inside getview(), but no view is visible, not even any exception arises, I want the book detail fragment to be replaced by section detail fragment.
Xml of book detail fragment has id book_description_fragment and xml for section description fragment has id section_description_fragment.
The above code is in onClick method of an item, I want that when user taps on an item in horizontal scroll view, then the fragment changes.
Fragments that are hard coded in XML, cannot be replaced. If you need to replace a fragment with another, you should have added them dynamically, first of all.
Note: R.id.fragment_container is a layout or container of your choice in the activity you are bringing the fragment to.
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Please see this Question
You can only replace a "dynamically added fragment".
So, if you want to add a dynamic fragment, see this example.
I've made a gist with THE perfect method to manage fragment replacement and lifecycle.
It only replace the current fragment by a new one, if it's not the same and if it's not in backstack (in this case it will pop it).
It contain several option as if you want the fragment to be saved in backstack.
=> See Gist here
Using this and a single Activity, you may want to add this to your activity:
#Override
public void onBackPressed() {
int fragments = getSupportFragmentManager().getBackStackEntryCount();
if (fragments == 1) {
finish();
return;
}
super.onBackPressed();
}
Use the below code in android.support.v4
FragmentTransaction ft1 = getFragmentManager().beginTransaction();
WebViewFragment w1 = new WebViewFragment();
w1.init(linkData.getLink());
ft1.addToBackStack(linkData.getName());
ft1.replace(R.id.listFragment, w1);
ft1.commit();
Use ViewPager. It's work for me.
final ViewPager viewPager = (ViewPager) getActivity().findViewById(R.id.vp_pager);
button = (Button)result.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(1);
}
});
hope you are doing well.when I started work with Android Fragments then I was also having the same problem then I read about
1- How to switch fragment with other.
2- How to add fragment if Fragment container does not have any fragment.
then after some R&D, I created a function which helps me in many Projects till now and I am still using this simple function.
public void switchFragment(BaseFragment baseFragment) {
try {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
if (getSupportFragmentManager().findFragmentById(R.id.home_frame) == null) {
ft.add(R.id.home_frame, baseFragment);
} else {
ft.replace(R.id.home_frame, baseFragment);
}
ft.addToBackStack(null);
ft.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
enjoy your code time :)
you can use simple code its work for transaction
Fragment newFragment = new MainCategoryFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame_NavButtom, newFragment);
ft.commit();
You Can Use This code
((AppCompatActivity) getActivity()).getSupportFragmentManager().beginTransaction().replace(R.id.YourFrameLayout, new YourFragment()).commit();
or You Can This Use Code
YourFragment fragments=(YourFragment) getSupportFragmentManager().findFragmentById(R.id.FrameLayout);
if (fragments==null) {
getSupportFragmentManager().beginTransaction().replace(R.id.FrameLayout, new Fragment_News()).commit();
}
I change fragment dynamically in single line code
It is work in any SDK version and androidx
I use navigation as BottomNavigationView
BottomNavigationView btn_nav;
FragmentFirst fragmentFirst;
FragmentSecond fragmentSecond;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
fragmentFirst = new FragmentFirst();
fragmentSecond = new FragmentSecond ();
changeFragment(fragmentFirst); // at first time load the fragmentFirst
btn_nav = findViewById(R.id.bottomNav);
btn_nav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch(menuItem.getItemId()){
case R.id.menu_first_frag:
changeFragment(fragmentFirst); // change fragmentFirst
break;
case R.id.menu_second_frag:
changeFragment(fragmentSecond); // change fragmentSecond
break;
default:
Toast.makeText(SearchActivity.this, "Click on wrong bottom SORRY!", Toast.LENGTH_SHORT).show();
}
return true;
}
});
}
public void changeFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_layout_changer, fragment).commit();
}
In kotlin you can do:
// instantiate the new fragment
val fragment: Fragment = ExampleFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.book_description_fragment, fragment)
transaction.addToBackStack("transaction_name")
// Commit the transaction
transaction.commit()
This will work if you're trying to change the fragment from another fragment.
Objects.requireNonNull(getActivity()).getSupportFragmentManager()
.beginTransaction()
.replace(R.id.home_fragment_container,new NewFragment())
NOTE As stated in the above answers, You need to have dynamic fragments.
You can use fragment-ktx
// If you are in fragmet
childFragmentManager.beginTransaction()
// or if you are in activiry
supportFragmentManager.beginTransaction()
// Create and commit a new transaction
supportFragmentManager.commit {
setReorderingAllowed(true)
// Replace whatever is in the fragment_container view with this fragment
replace<ExampleFragment>(R.id.fragment_container)
}
To replace a fragment with another one do this, Note that R.id.fragment comes from the id that you give to the first tag of the fragment in the XML.
barAudioPlaying.setOnClickListener(view -> {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment,new HomeFragment())
.commit();

How to prevent opening a fragment from navigation drawer if that fragment is already opened

How to prevent opening a fragment from navigation drawer if that fragment is already opened, when the fragment is opened and click in the NavigationDrawer item the fragment reCreates again, So how to check if the fragment is already opened?
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (id == R.id.fragmentA) {
{ FragmentA fragment = new FragmentA();
transaction.add(R.id.main_screen, fragment1, "MainFrag").addToBackStack(null);
}
} else if (id == R.id.fragmentB) {
FragmentB fragment = new FragmentB();
transaction.add(R.id.main_screen, fragment).addToBackStack(null);
} else if (id == R.id.fragmentC) {
FragmentC fragment = new FragmentC();
transaction.replace(R.id.main_screen, fragment).addToBackStack(null);
}
I solved it in this way:
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (id == R.id.n_1 && !(f instanceof MainFragment)) {
MainFragment fragment = new MainFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
} }
for example I am in the fragment B, And when I click in fragment B
again from the NavigationDrawer it recreates, so how to check if the
fragment is already shown in the screen or not?
If you have reference to Fragment B from the NavigationDrawer, you can call mFragmentB.isAdded() to know whether it's already shown or not.
While adding fragment use tags to replace it.
transaction.replace(R.id.main_screen, fragment, tag);
Now, when menu items are clicked use fragment manager to get the visible fragment using tag :
public boolean isFragmentCurrentlyVisible(String fragmentTag){
Fragment fragmentToTest;
fragmentToTest = fragmentManager.findFragmentByTag(fragmentTag);
if(fragmentToTest!=null && fragmentToTest.isVisible())
return true;
return false;
}
Depending on value returned by above method you can add the fragment if not already added.
I have also struggled with this for a while, I am using navigation components and Kotlin, so finally I got it sorted out. It might not be the best solution, but it's simple and works, so I wanted to share it with you:
when (menuItem.itemId) {
R.id.nav_board -> {
if(findNavController(R.id.nav_host_fragment).currentDestination?.label != "listFragment")
findNavController(R.id.nav_host_fragment)
.navigate(R.id.action_global_listFragment)
}
The label is the destination label given in the navigation.xml
<navigation 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/navigation"
app:startDestination="#id/listFragment">
<fragment
android:id="#+id/listFragment"
android:name="at.example.app.ui.ListFragment"
android:label="listFragment"
tools:layout="#layout/fragment_list">
...
So this basically just checks if the current destination (where we're at) is the one that should not be re-opened and only navigates if the current destination is a different one.

Replaced fragment visible behind the "new" fragment

I use a mainActivity which contains a frameLayout.
In this framelayout i load different fragments (by clicking on a menuitem in a navigation drawer) When i switch between fragments with a static layout (.xml layout file) everything works fine. 1 fragment has a dynamic created layout (which is created in the onCreateView method). When i navigate to this fragment and navigate back to another fragment i can still see the "old" fragment with the dynamic created controls trough the "new" fragment.
The code what i use to switch between the fragment is:
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.fr_content_container,new AlertOverviewFragment()).commit();
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
mDrawerLayout.closeDrawers();
if (menuItem.getItemId() == R.id.nav_item_alerts) {
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fr_content_container, new AlertOverviewFragment()).commit();
}
if (menuItem.getItemId() == R.id.nav_item_news) {
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fr_content_container, new NewsFragment()).commit();
}
if (menuItem.getItemId() == R.id.nav_item_add_country) {
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fr_content_container, new AddCountryFragment()).commit();
}
return false;
}
});
I can give the background of the new activity a background color so the old fragment isn't visible anymore but i think this is not the best practice solution. The old fragment will then still exist. What is the best way to solve this problem?
AND when i have this problem with this fragmen, are there then also other fragments that still exist in the background after navigate to another fragment? when yes, do i need to "destroy" these before switch to the new fragment or something?
I read something about the live cycles and understand this but i thought Android manages these states by him self?

Understanding fragment stack

I have a action bar (actionbarsherlock) with tab navigation and I have a couple of action items as well. One of my action items displays a ListFragment and here is how I call it:
case R.id.menuitem_info:
// Create new fragment and transaction
SherlockListFragment aboutListFragment = new AboutListFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
ft.replace(R.id.root, aboutListFragment);
ft.addToBackStack(null);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// Commit the transaction
ft.commit();
return true;
My problem is that when I hit the back button, I get an IllegalArgumentException. I'm not sure how to remove the fragment from the view and display the previous view?
Here is my home button code:
case android.R.id.home:
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
}
return true;
Any suggestions would be appreciated!
I did the following in case android.R.id.home:
case android.R.id.home:
FragmentManager fm = getSupportFragmentManager();
if(fm.getBackStackEntryCount()>0){
onBackPressed();
}
return true;
I hope this help you, for me works like a charm

Categories

Resources