I am using SLiding menu at My App and according to menu item , I am changing always the fragment at activity which have binded already to menu. But There is performance issue. it is freezing when i am attaching the fragments. but after the wiew created. the performance is normal. I am replacing the fragments after call the toggle function at menu.
is there anyone to have any opinion about it ?
just call it as:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (item.getItemId() == R.id.evnetCalender) {
if (!isToggle) {
item.setIcon(R.drawable.ic_view_list_white_24dp);
setFragment(caldroidCalendarFragment);
isToggle = true;
} else {
item.setIcon(R.drawable.ic_event_white_24dp);
setFragment(scheduleEventFragment);
isToggle = false;
}
}
and set your fragment when you toggle it
private void setFragment(Fragment fragment1) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content, fragment1);
fragmentTransaction.commit();
}
this content identifier is your frame layout id in which your fragment take place
Related
I have a simple BottomNavigationView with two menu items (Home Fragment, Settings Fragment) in an activity.
I have implemented onNavigationItemSelectedListener and onNavigationItemSelected.
Also bottomNavigationView.setOnNavigationItemSelectedListener(this);
App page lands on the Home Fragment.
onNavigationItemSelected is being called when I switch between menu items but When I first launch the app and tap on the same menu Item i.e. Home Fragment, onNavigationItemSelected is not being called.
I would need to show a toast whenever the user clicks on the home page when user is already in home page but onNavigationItemSelected event is not triggered.
As Mike M mentioned,
setOnNavigationItemReselectedListener did the trick.
First of all we do this in the MainActivity
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int v = item.getItemId();
if(v==R.id.home)
{
getSupportActionBar().setTitle("Home");
Fragment fragment = new HomeFragment();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.frame_layout, fragment).commit();
}
else if (v==R.id.dash_board)
{
getSupportActionBar().setTitle("Dashboard");
Fragment fragment = new DashboardFragment();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.frame_layout, fragment).commit();
}
return true;
}
};
This is a example here
If you want to know in detail then click here
I'm currently developing a Android studio App using fragment and a bottom navigation bar.
When I click on a navigation bar's item, it's replacing the current fragment by another one which correspond the fragment I wanted for this item.
The problem is, the objects in my fragment are all reset after replacing fragment.
I'm not removing the fragment from the container so I don't really understand why all the objects are reset after doing this.
Here is my code to add and replace fragment to my FrameLayout :
private void setFragment(Fragment fragment) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.fade_out);
if (getSupportFragmentManager().findFragmentById(R.id.main_frame) == null) {
fragmentTransaction.add(R.id.main_frame, fragment);
}
else
{
fragmentTransaction.replace(R.id.main_frame, fragment);
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
and here is the bottom navigation bar code to execute the previous function and change the displayed fragment:
homeFragment = new HomeFragment();
programFragment = new ProgramFragment();
bluetoothFragment = new BluetoothFragment();
mMainNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
test = mMainNav.getMenu().getItem(2);
switch (item.getItemId()) {
case R.id.nav_home:
//mMainNav.setItemBackgroundResource(R.color.colorPrimary);
HQ_logo_IV.setVisibility(View.VISIBLE);
setFragment(homeFragment);
return true;
case R.id.nav_program:
//mMainNav.setItemBackgroundResource(R.color.colorAccent);
HQ_logo_IV.setVisibility(View.INVISIBLE);
setFragment(programFragment);
return true;
case R.id.nav_bluetooth:
//mMainNav.setItemBackgroundResource(R.color.colorPrimaryDark);
HQ_logo_IV.setVisibility(View.INVISIBLE);
setFragment(bluetoothFragment);
return true;
default:
return false;
}
}
});
I found the way to stop this thing.
I used an AsyncTask to refresh my fragment state.
I just put new "yourAsyncTaskName"().execute() at the beginning of my onCreate() method to refresh the fragment when it's created or replaced.
Hope this will help.
I have Base Activity including NavigationView with 2 menu items. On start it loads Home fragment having background image inside it. Each loads specific fragment. When I select Terms & Conditions menu item, it loads T&C fragment & when I press back button it simply kills it.
However, when I select About Us menu item, it loads About Us fragment but I need to press BACK button twice to kill it. I need to know why does it happen?
Part of Code in AppBaseActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
HomeFragment homeFragment = new HomeFragment();
fragmentTransaction.add(R.id.body_container, homeFragment, "");
fragmentTransaction.commit();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
navigationView.getMenu().findItem(item.getItemId()).setChecked(true);
switch (item.getItemId()) {
case R.id.nav_terms :
fragmentTransaction = fragmentManager.beginTransaction();
TCFragment tcFragment = new TCFragment();
fragmentTransaction.replace(R.id.body_container, tcFragment, "");
fragmentTransaction.commit();
break;
case R.id.nav_about_us :
fragmentTransaction = fragmentManager.beginTransaction();
AboutUsFragment aboutUsFragment = new AboutUsFragment();
fragmentTransaction.replace(R.id.body_container, aboutUsFragment, "");
fragmentTransaction.commit();
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
All fragments simply have overridden onCreateView() by inflating respected xml only. No code is written in both fragments yet.
You can stop back hardware navigation if you want.
Simply using onBackPressed() without super.onBackPressed()
#Override
public void onBackPressed() {
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
I have a navigation drawer and clicking on items shows/hides/creates full screen fragments.
For the most part, this code works great. But sometimes, maybe 1% of the time, I will get crazy full screen fragment overlapping when opening the app while it has already been running.
Is the problem with my code..? Or maybe something else in Android where it does not recognize I have the fragments with the tags already created?
Here is the relevant code for how I show/hide/create fragments:
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Get to drawer layout so we can interact with it
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// Get the fragment manager to remove/add fragments
FragmentManager fragmentManager = getSupportFragmentManager();
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_profile) {
// Hide visible fragment
fragmentManager.beginTransaction().hide(getVisibleFragment()).commit();
// Check if the fragment exists first.
if(fragmentManager.findFragmentByTag("profileFragment") != null) {
// If the fragment exists, show it (no reason to recreate it).
fragmentManager.beginTransaction()
.show(fragmentManager.findFragmentByTag("profileFragment"))
.commit();
} else {
// If the fragment does not exist, add it to fragment manager with a tag to identify it.
// Create new fragment instance with required argument(s).
ProfileFragment fragment = ProfileFragment.newInstance();
fragmentManager.beginTransaction()
.add(R.id.content_frame, fragment, "profileFragment")
.commit();
}
// Set the title
mToolbarTitleTextView.setText(R.string.title_activity_profile);
} else if (id == R.id.nav_feed) {
// Hide visible fragment
fragmentManager.beginTransaction().hide(getVisibleFragment()).commit();
// Check if the fragment exists first.
if(fragmentManager.findFragmentByTag("feedFragment") != null) {
// If the fragment exists, show it (no reason to recreate it).
fragmentManager.beginTransaction()
.show(fragmentManager.findFragmentByTag("feedFragment"))
.commit();
} else {
// If the fragment does not exist, add it to fragment manager with a tag to identify it.
fragmentManager.beginTransaction()
.add(R.id.content_frame, new feedFragment(), "feedFragment")
.commit();
}
// Set the title
mToolbarTitleTextView.setText(R.string.title_activity_feed);
} else if (id == R.id.nav_notifications) {
// Hide visible fragment
fragmentManager.beginTransaction().hide(getVisibleFragment()).commit();
// Hide the post button
mPostButton.setVisibility(View.GONE);
// Check if the fragment exists first.
if(fragmentManager.findFragmentByTag("notificationsFragment") != null) {
// If the fragment exists, show it (no reason to recreate it).
fragmentManager.beginTransaction()
.show(fragmentManager.findFragmentByTag("notificationsFragment"))
.commit();
} else {
// If the fragment does not exist, add it to fragment manager with a tag to identify it.
fragmentManager.beginTransaction()
.add(R.id.content_frame, new NotificationsFragment(), "notificationsFragment")
.commit();
}
// Set the title
mToolbarTitleTextView.setText(R.string.title_activity_notifications);
}
mDrawerLayout.closeDrawer(GravityCompat.START);
return true;
}
// Useful method to hide the currently visible fragment
public Fragment getVisibleFragment(){
FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
List<Fragment> fragments = fragmentManager.getFragments();
if(fragments != null){
for(Fragment fragment : fragments){
if(fragment != null && fragment.isVisible())
return fragment;
}
}
return null;
}
EDIT: It is really hard to reproduce this error which makes it hard to debug. It seems to randomly happen.
Why hide and keep all the fragments with fragmentManager.beginTransaction().add(); you can avoid this error by keeping only one fragment in memory and avoiding the hassle of hiding fragments by using fragmentManager.beginTransaction().replace() and using the fragment lifecycle methods to store the fragment state if necessary.
Here is how I solved the problem. In my MainActivity I did this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
setContentView(R.layout.activity_main);
}
Basically what was happening is if I had 1+ fragments on the screen, if the android system ran low on resources while the app was in the background and shut it down, when restored, MainActivity.onCreate() would be called and it would re-instantiate all the fragments with the call
super.onCreate(savedInstanceState);
So I just made it null and this prevents from all those fragments to be recreated.
The reason they are overlapping is because they were all getting shown at once.
Definitely not the correct way to do it, but it solves my problem right now =P
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?