I am developing an Android Application with navigation activity and there are some list of options in navigation drawer and my First page is also in this activity. I am navigating to another page through the options present in the navigation drawer which are Fragment classes. I need to come back to the first page if I press back button on device. But it goes to pages which I visited before. My Target is to come back to First page from the respective Fragment class.
At times when I hit back button, it also comes to my splash screen, Kindly help me to fix this. Thanks in advance.
This is the code of my FirstPage from where I am navigating to another pages through drawer. I need to come back to this same page again from the drawer (FirsPage)
public void selectDrawerItem(MenuItem menuItem) {
switch(menuItem.getItemId()) {
//1.User Profile
case R.id.navigation_item_attachment:
fragmentClass = ProfileTab.class;
// finish();
break;
//2.FeedBack
//case R.id.navigation_item_images:
/* fragmentClass = SearchHistoryTab.class;
break;*/
case R.id.navigation_refer:
fragmentClass = ReferFrndz.class;
// finish();
break;
case R.id.navigation_daily:
fragmentClass = DailyUsage.class;
break;
//4.About Us
case R.id.navigation_about:
fragmentClass = AboutJc.class;
break;
//4.Contact Us
case R.id.navigation_item_location:
fragmentClass = ContactJc.class;
break;
default:
break;
}
try {
fragment = (Fragment) fragmentClass.newInstance();
}
catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.search_layout, fragment).commit();
menuItem.setChecked(true);
setTitle(menuItem.getTitle());
mDrawerLayout.closeDrawers();
}
I used Finish() but it didn't work. It terminating my entire application.
Splash Screen Code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread mythread = new Thread() {
public void run(){
try{
sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
finally {
.....
}
}
}
};
mythread.start();
}
Update your Fragmenttransaction code to add ProfileTab (FirstPage) in backstack entry.' So you get ProfileTab (FirstPage) back after click back button.
FragmentManager fragmentManager = getSupportFragmentManager();
if(fragment.equals(ProfileTab.class)){
fragmentManager.beginTransaction().replace(R.id.search_layout, fragment).addToBackStack("fragment_tag").commit();
//Only add backstack entry for first page so you get after click on back button
}
else
{
fragmentManager.beginTransaction().replace(R.id.search_layout, fragment).commit();
}
menuItem.setChecked(true);
setTitle(menuItem.getTitle());
mDrawerLayout.closeDrawers();
Use this solution and share your feedback with replay will help us to improve solution.
Related
I have a situation, I´m not good enough in android dev to implement a way to pass data between Bottom Navigation destinations.
I would need to get text from EditText from CreateFragment to a RecipesFragment, where I would add a new item in the database and the RecyclerView would update (I´m using LiveData + MVVM) based on this data.
My Bottom Navigation Bar
So, I´m asking for a way. I couldn´t find any proper/specific explanation and I think that passing data between fragments in Bottom Navigation or Navigation Drawer is important feauture but hard i guess for beginners like me :(.
Additional info: I host a FrameLayout(id-fragment_container) in my MainActivity in what I change fragments based on location in Bottom Nav selected. (check code)
MainActivity.java
public class MainActivity extends AppCompatActivity {
private BottomNavigationView bottomNavigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(navListener);
// Keeps the current fragment opened when the device rotates
if (savedInstanceState == null) {
// Sets the default selected item in NavigationView
bottomNavigationView.setSelectedItemId(R.id.nav_home);
}
}
// Handles switching the view based on NavigationView item selected
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.nav_home:
selectedFragment = new HomeFragment();
break;
case R.id.nav_recipes:
selectedFragment = new RecipesFragment();
break;
case R.id.nav_create:
selectedFragment = new CreateFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
selectedFragment).commit();
return true;
}
};
CreateFragment.java
private void saveRecipe() { //trigered on floating button press
String title = edit_title.getText().toString();
String ingredients = edit_ingredients.getText().toString();
if (title.trim().isEmpty() || ingredients.trim().isEmpty()) {
Toast.makeText(getActivity(), "Please insert a title and description", Toast.LENGTH_SHORT).show();
return;
}
// THIS SHOULD PASS DATA TO RecipesFragment INTO RECYCLERVIEW
// TODO
//
}
RecipesFragment.java
public void getRecipeFromCreateFragment() {
// THERE SHOULD BE PASSED DATA FROM CREATE ACTIVITY
// TODO
//
Recipe recipe =
new Recipe("hh", "title", "ingredients", "instructions", "ss", "image");
recipeViewModel.insert(recipe);
Toast.makeText(getActivity(), "Recipe saved", Toast.LENGTH_SHORT).show();
}
UPDATE: Okay, I got help from a fellow redditer and the solution was really easy and I shouldn´t had even thought about passing data between fragments in my case.
The solution is to simply add the recipe to the database via ViewModel in the CreateFragment, there´s really no need to pass the data to the RecipesFragment and then add it there.
HOWEVER, if someone know a better, more recommended way to pass data between fragments in Navigation View (Navigation Drawer) it would be really helpful for the future.
Thanks.
I'm making an app that has launches with a Swiping Tabs Fragment, but I also want to have a Preferences menu using Fragment Transaction. When I press the Settings button in my app, the preferences menu does appear and is interactive, but the layout seems to be transparent showing the Tabs below. Is there anything that can be done to fix this, or is there a better method?
Code that calls the Preferences Menu from the Options:
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getFragmentManager().popBackStackImmediate();
break;
case R.id.logout:
FirebaseAuth.getInstance().signOut();
finish();
startActivity(new Intent(this, Activity_Main.class));
break;
case R.id.action_settings:
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new Fragment_Settings()).addToBackStack(null)
.commit();
break;
}
return true;
}
Code that calls Tabs Fragments:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new Fragment_Flower();
case 1:
// Games fragment activity
return new Fragment_Overview();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 2;
}
}
Initialising Transaction in onCreate:
startService(new Intent(this, SensorListener.class));
if (b == null) {
// Create new fragment and transaction
Fragment newFragment = new Fragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
//Replace whatever is in the fragment_container view with this
// fragment,
// and add the transaction to the back stack
transaction.replace(android.R.id.content, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
Any help will be greatly appreciated!
Just set background color in your layout file. It may avoid transparent backgound.
My problem is almost the same as this Stop AsyncTask in Fragments when Back Button is pressed
But I want to stop my AsyncTask when the back arrow is clicked. I have a code in stoping asynctask and it works when I implemented it in another way. I tried what I researched so far but I still got errors. Please help me with this.
I tried this code
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id=item.getItemId();
if(id==android.R.id.home)
{
Intent returnIntent = new Intent();
returnIntent.putExtra("flag",userid);
setResult(Activity.RESULT_OK,returnIntent);
finish();
return true;
}}
UPDATED:
I am using this code to go to another fragment.
Fragment2 fragmentChild = new Fragment2 ();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.content, fragmentChild);
transaction.addToBackStack(null);
transaction.commit();
I have no problem in my backtrack when I go to another fragment. Then I'm using this code (getSupportActionBar().setDisplayHomeAsUpEnabled(true)) in my (Drawer.java) to show the back arrow. Now I want to add event when I clicked back arrow.
EDIT: (Drawer.java)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
final View.OnClickListener originalToolbarListener = toggle.getToolbarNavigationClickListener();
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
toggle.setDrawerIndicatorEnabled(false);
toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getSupportFragmentManager().popBackStack();
}
});
} else {
toggle.setDrawerIndicatorEnabled(true);
toggle.setToolbarNavigationClickListener(originalToolbarListener);
}
}
});
If you properly setup the action bar, then you should be able to achive that with the following:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// Add the code to stop the task
break;
}
return super.onOptionsItemSelected(item);
}
EDIT: After you are able to handle the back button event, you can add the code to close the tasks in fragments. First of all, I created an interface that is implement by all fragments that should be able to close this tasks.
public interface TaskCancelFragment {
void cancelTask();
}
The implementation in fragments should look something like this:
#Override
public void cancelTask() {
//Add the code to cancel the task
Toast.makeText(getContext(), "The task is canceled", Toast.LENGTH_SHORT).show();
}
The final step is to send the event from activity to fragment. Here I will assume some things since I don't have access to your code to see how you add/find the fragments, but fortunately this doesn't matter so much and is easy to change. In addition to the initial answer, I created a new method in activity to find the current fragment and close the task.
private void cancelTasks() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.placeholder);
if (fragment instanceof TaskCancelFragment) {
((TaskCancelFragment) fragment).cancelTask();
}
}
And in the end, the case android.R.id.home looks like this:
case android.R.id.home:
cancelTasks();
onBackPressed(); // I think that you want to close the activity too
break;
In my app, am using a navigation drawer (in Fragment A) to navigate to fragments:
public void displayView(int viewId){
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (viewId) {
case R.id.nav_menu:
fragment = new MenuFragment();
title = getString(R.string.menu_title);
viewIsAtHome = false;
break;
case R.id.nav_reservation:
fragment = new ReservationFragment();
title = getString(R.string.reservation_title);
viewIsAtHome = false;
break;
...
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
// set the toolbar title
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
}
displayView() is called in onNavigationItemSelected:
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
displayView(item.getItemId());
return true;
}
Now, in ReservationFragment I am displaying a list of reservations and a FloatingActionButton to start Activity B where the user can add a reservation if there are no reservations. When the user is done adding a reservation, I want to display it in the Reservation fragment. This requires me to "go back" to the Fragment.How do I accomplish this since Activity B knows nothing about Activity A?
What I've tried:
I tried creating a method in Activity A like this:
public void navigateToFragment(int viewId) {
displayView(R.id.nav_reservation);
}
and then called this method from Activity B:
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new MainActivity().navigateToFragment(R.id.nav_reservation);
//MainActivity is Activity A
}
});
the app crashes due to a nullPointerException in displayView() from the line:
String title = getString(R.string.app_name);
This isn't surprising since am creating a new MainActivity object that knows nothing about the previous state of the Activity, right?
This question mirrors my problem but is based on Settings so I can't really use the answer in my case.
How do I accomplish this task?
There are three quick methods that come to my mind. First you can start activityB with startActivityForResult and handle the result in activityA after user does what he wants in activityB. Second you can set activityA as singleTop and before finishing activityB you can startActivityA with clearTop an intent flag called clear_top(https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP).
Last but not the least, you can connect two activity by binding service in both activities and communicate via that service that you bound.
I'm confused how to open my different fragments by clicking on one Item in my navigation drawer.
In MainActivity I use the following Code:
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Fragment fragment;
int id = item.getItemId();
if (id == R.id.nav_listview) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment, new ListFragment());
ft.commit();
} else if (id == R.id.nav_add_data) {
} else if (id == R.id.nav_settings) {
} else if (id == R.id.nav_legal_information) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
First of all I want to try to open my ListFragment:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ListFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_list, container, false);
}
}
In my content main.xml I created the following fragment which should be replaced when clicking on the specific Items in the Navigation Drawer.
<fragment
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fragment" />
But it isnt working...
Can anyone help me?
Rastaman
To get what you want try this ,I was also held up with this somewhat complex looking code but its more of a easy way to use
Here's detailed explanation and walk through to this issue:
(Its seems Long But You can easily relate your work asap)
When you first create the Navigation Drawer Activity, there are 5 files we’ll look at:
MainActivity.java - this is the code behind for everything in our app.
activity_main.xml - this is the layout for the app including the nav drawer and an include for the app_bar_main.
app_bar_main.xml - this is the layout with the toolbar (at the top), a floating action button (at the bottom right), and an include for content_main.
content_main.xml - this is the layout for the content of the main page.
nav_header_main.xml - this is the UI for the top part of the nav drawer.
Step 1:
open up the app_bar_main.xml, comment out the include and add a new FrameLayout:
<!--<include layout="#layout/content_main" />-->
<FrameLayout
android:id="#+id/Fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"/>
This FrameLayout is what we’ll use to load our fragments into.
Step 2:
Next, you’ll want to add a few fragments
To do so, right click on your project, or go to File –> New and from the Fragment list choose Fragment (Blank) or others
Step 3:
The next step is to load a fragment when the app first launches. Go to the MainActivity’s onCreate method and put the following in after the call to setSupportActionBar:
Fragment fragment = null;
Class fragmentClass = null;
fragmentClass = FragmentOne.class;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.Fragment_container, fragment).commit();
Step 4:
You’ll then need to add OnFragmentInteractionListener to the interfaces your MainActivity implements and also implement the onFragmentInteraction method.Like this
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, FragmentOne.OnFragmentInteractionListener ,FragmentTwo.OnFragmentInteractionListener,FragmentThree.OnFragmentInteractionListener {
Step 5:
Finally, in the onNavigationItemSelected method, you can add the ability to load different fragments when menu items are tapped:
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Fragment fragment = null;
Class fragmentClass = null;
if (id == R.id.nav_camera) {
fragmentClass = FragmentOne.class;
} else if (id == R.id.nav_gallery) {
fragmentClass = FragmentTwo.class;
} else if (id == R.id.nav_slideshow) {
fragmentClass = FragmentThree.class;
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Here I’m just loading one of the two fragments I’ve added to my app. Note that because I have two different fragments, I had to implement the interfaces for both FragmentOne.OnFragmentInteractionListener and FragmentTwo.OnFragmentInteractionListener.
That’s all you need to do to implement fragment loading in your Navigation Drawer.
What the user taps a menu item, the drawer will slide back in smoothly and the new fragment will have already started / finished loading. This also prevents any possible jankiness that you could see when launching a new activity.
EXTRA
One last thing to note is that if you switch to a different fragment and then rotate the device or cause another recreation of the activity, the code above will cause the first fragment to be reloaded. One easy way to deal with that is to wrap the fragment block in the onCreate method in a check to see if the savedInstanceState is not null like this:
protected void onCreate(Bundle savedInstanceState) {
...
if (savedInstanceState == null) {
//Fragment load code
}
...
}
Try this Code
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Fragment fragment=null;
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
int id = item.getItemId();
if (id == R.id.nav_listview) {
fragment= new ListFragment();
} else if (id == R.id.nav_add_data) {
} else if (id == R.id.nav_settings) {
} else if (id == R.id.nav_legal_information) {
}
ft.replace(R.id.container, fragment);
ft.addToBackStack(null);
ft.commit();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/container" />
Please Change The name of your fragment class ListFragment Because ListFragment is already Sub Class of Fragments in android.app package android OS
Mhmm I found an answer. But I am confused.
If I use:
if (id == R.id.nav_listview) {
fragment= new com.thomas.testapp.ListFragment();
It works. But I only have to use the package name if I want to open my ListFragment. Why?
I suggest to Create codes More Dynamic
first of all, if you have custom class to create Navigation Drawer, use listener to call methods from your activity
there is class call HomeFragment extends Fragment, so we have :
if(condition){
fragment = new HomeFragment();
// if there is Listener
if(mListener != null){
mListener.someMethod
}
// Other Settings And Codes
}
public class MainActivity extends AppCompatActivity {
// ...
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...From section above...
// Find our drawer view
nvDrawer = (NavigationView) findViewById(R.id.nvView);
// Setup drawer view
setupDrawerContent(nvDrawer);
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}
public void selectDrawerItem(MenuItem menuItem) {
// Create a new fragment and specify the fragment to show based on nav item clicked
Fragment fragment = null;
Class fragmentClass;
switch(menuItem.getItemId()) {
case R.id.nav_first_fragment:
fragmentClass = FirstFragment.class;
break;
case R.id.nav_second_fragment:
fragmentClass = SecondFragment.class;
break;
case R.id.nav_third_fragment:
fragmentClass = ThirdFragment.class;
break;
default:
fragmentClass = FirstFragment.class;
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
// Highlight the selected item has been done by NavigationView
menuItem.setChecked(true);
// Set action bar title
setTitle(menuItem.getTitle());
// Close the navigation drawer
mDrawer.closeDrawers();
}
// ...
}