The issue occurs when I attempt to switch from the Second Fragment to the First Fragment. I am using ActionBar Option Menu Icons to navigate back and forth between the different fragments.
Each fragment has its own menu that is associated with the individual option menu items. I cannot seem to figure out why I am able to transition from one the First Fragment to the Second Fragment, but am unable to do the reverse.
Does anything in my code stand out that would disable me from being able to navigate back to the previous fragment?
I was able to switch between the fragments without any issues in the past, but after I incorporated these option menu items to do the navigation, it stopped working.
Starting Fragment
public class SearchFragmentActivity extends Fragment implements OnClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.activity_search_fragment,
container, false);
btnBasketball = (ImageButton) view.findViewById(R.id.btnBasketball);
btnBasketball.setOnClickListener(this);
setHasOptionsMenu(true);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Add your menu entries here
menu.clear();
inflater.inflate(R.menu.navigation_search_event, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_more:
// do something with a dropdown
break;
}
return true;
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.btnBasketball:
changeFragment("Basketball");
break;
}
}
public void changeFragment(String sportName) {
Bundle bundle = new Bundle();
bundle.putString("SPORTNAME", sportName);
Fragment fragment = new SearchDetailsFragmentActivity();
fragment.setArguments(bundle);
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.cell_left_in,
R.anim.cell_right_out);
transaction.replace(R.id.searchFragment, fragment);
transaction.commit();
}
}
Second Fragment
public class SearchDetailsFragmentActivity extends Fragment {
TextView tvSportsName;
GridView gView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.activity_search_details_fragment,
container, false);
String sportsName = getArguments().getString("SPORTNAME");
tvSportsName = (TextView) view.findViewById(R.id.tvSportsName);
tvSportsName.setText(sportsName);
// SportAdapter sAdapter = new SportAdapter(getActivity(), lstSports);
gView = (GridView) view.findViewById(R.id.gridViewSearch);
setHasOptionsMenu(true);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Add your menu entries here
menu.clear();
inflater.inflate(R.menu.navigation_search_details_event, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_cancel:
changeFragment();
break;
}
return true;
}
public void changeFragment() {
Fragment fragment = new SearchFragmentActivity();
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.cell_left_in,
R.anim.cell_right_out);
transaction.replace(R.id.searchDetailsFragment, fragment);
transaction.commit();
}
}
Options Menu associated with Second Fragment
<?xml version="1.0" encoding="utf-8"?>
<menu 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" >
<item
android:id="#+id/action_cancel"
android:icon="#drawable/ic_content_remove"
android:orderInCategory="100"
android:title="#string/action_settings"
app:showAsAction="always"/>
</menu>
UPDATES
These changes allow me to navigate backwards from the SearchDetailsFragmentActivity >> SearchFragmentActivity using the SoftKey Back Button.
Changes to the changeFragment() method inside SearchDetailsFragmentActivity
public void changeFragment() {
Fragment fragment = new SearchFragmentActivity();
FragmentManager fm = getFragmentManager();
//FragmentTransaction transaction = fm.beginTransaction();
//transaction.setCustomAnimations(R.anim.cell_left_in,
//R.anim.cell_right_out);
//transaction.replace(R.id.searchDetailsFragment, fragment);
//transaction.commit();
fm.popBackStack();
}
inside the SearchFragmentActivity
public void changeFragment(String sportName) {
Bundle bundle = new Bundle();
bundle.putString("SPORTNAME", sportName);
Fragment fragment = new SearchDetailsFragmentActivity();
fragment.setArguments(bundle);
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.cell_left_in,
R.anim.cell_right_out);
transaction.replace(R.id.searchFragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
UPDATE 2
I placed a Log.e inside the OnOptionItemSelected() to see if the button was even firing properly and it appears as if it is not. There is nothing that is getting logged.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_cancel:
Log.e("IS THIS WORKING", "THIS IS WORKING"); <<< NOT FIRING
changeFragment();
break;
}
return true;
}
When replacing a fragment, you need to indicate whether or not that transaction is reversable (i.e. whether or not it goes onto the backstack). For the first fragment transaction, you usually won't want to do this (wouldn't want to pop to an empty view). For fragment replacements, you want to specify addToBackStack() with an optional tag (which can be later used with popBackStack(String)).
For example, in between these lines:
transaction.replace(R.id.searchDetailsFragment, fragment);
transaction.commit();
add:
transaction.replace(R.id.searchDetailsFragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
Related
I have 3 fragments, Home, Menu and orders they can be loaded by bottomnavigtioview items and the title shown by it as well
once navigate from Home to Orders then if you want to go back to Home From Orders the title still "Orders"
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment fragment;
switch (item.getItemId()) {
case R.id.navigation_home:
toolbar.setTitle(getResources().getString(R.string.title_home));
fragment = new HomeFragment();
loadFragment(fragment);
return true;
case R.id.navigation_menu:
toolbar.setTitle(getResources().getString(R.string.fragment_title_menu));
fragment = new ProductFragment();
loadFragment(fragment);
return true;
case R.id.navigation_orders:
toolbar.setTitle(getResources().getString(R.string.title_orders));
fragment = new OrdersFragment();
loadFragment(fragment);
return true;
}
return false;
}
};
private void loadFragment(Fragment fragment) {
// load fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
// attaching bottom sheet behaviour - hide / show on scroll
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) navigation.getLayoutParams();
layoutParams.setBehavior(new BottomNavigationBehavior());
toolbar.setTitle(getResources().getString(R.string.title_home));
Fragment f = HomeFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_container, f)
.commit();
}`
I have Also Tried this but its not working
`
fragmentmanger.addOnBackStackChangedListener -> public void onBackStackChanged() {
}`
Instead of calling toolbar.setTitle in your onNavigationItemSelected method, move it to onCreateView of each fragment. When you navigate back to a Fragment, onCreateView is executed again.
It worked for me when calling it in onResume like this in each fragment:
if(getActivity()!=null) {
((MainActivity)getActivity()).setActionBarTitle
(context.getResources().getString(R.string.YOUR_TITLE));
this is the function setActionBarTitle in MainActivity
public void setActionBarTitle(String title) {
toolbar.setTitle(title);
}
I implemented a bottom Navigation that should be filled with three different Fragment classes.
My Problem is that if i start the activity the first Fragment layout is not shown, only if i go to tab2 and return to tab1.
I think it is a Problem with the LifeCycle but i have no idea how i can fix it.
my bottom Navigation class that handle the Navigation:
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
fragment = new RequestFragment();
break;
case R.id.navigation_dashboard:
fragment = new ResponseFragment();
break;
case R.id.navigation_notifications:
fragment = new LogfileFragment();
break;
}
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
return true;
And my Fragment class:
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_request, container, false);
you should add the first fragment when activity start. you just set first fragment on onNavigationItemSelected() method and it never called even you click on navigation View. you should add these lines in onCreate() method:
fragment = new RequestFragment();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
You have to initialize the fragment inside onCreate() method.
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity);
...
fragment = new RequestFragment();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
}
This will display the fragment in the container inside the view when your activity starts. Keep your onNavigationItemSelected method as it is.
I have an issue with onOptionsItemSelected event.
My application consist of Activity, main fragment, multiple function fragments.
Activity's FragmentManager contains only one Fragment (MainFragment).
MainFragment's ChildFragmentManager contains up to 5 fragments.
All fragments are added by method:
public void addFragment(Fragment fragment) {
FragmentManager fm = getChildFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.frame, fragment);
ft.addToBackStack(fragment.getClass().getSimpleName());
ft.commit();
}
All child fragments have their own menus. Every fragment has the same superclass with
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
setHasOptionsMenu(true);
...
}
And it's own
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.some_menu, menu);
...
}
and
#Override
public boolean onOptionsItemSelected(MenuItem item) {
...
}
All Menus are inflated properly, but onOptionsItemSelected(MenuItem item) is always called for the first fragment in backstack:
Let's say that I have:
MainFragment (getChildFragmentManager)
DetailsFragment
EditFragment
SelectionFragment
Menu is inflated from SelectionFragment, but when I press menu button, it calls DetailsFragment.onOptionsItemSelected...
MainActivity does not have Menu (none of mentioned methods).
How can I solve this issue?
Regards
Jakub
I'm working on go-back function with my fragments. I use the action bar as return button but the function onOptionsItemSelected does not work (the function may be even not called)
This code is in my FragmentActivity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
getActionBar().setHomeButtonEnabled(false);//disable the back button
this.getFragmentManager().popBackStack();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bottom_tab);
FragmentTabHost tabHost = (FragmentTabHost)findViewById(R.id.bottom_tab_host);
tabHost.setup(this, getSupportFragmentManager(), R.id.bottom_tab_content);
//tabHost.addTab(tabHost.newTabSpec("explore").setIndicator("explore"), ListTabWidget.class, null);
tabHost.addTab(tabHost.newTabSpec("browse").setIndicator("browse"), SearchList.class, null);
}
And this code is in my Fragment(A):
public class SearchList extends Fragment implements SearchView.OnQueryTextListener{
FragmentActivity searchActivity;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
searchActivity = (FragmentActivity) this.getActivity();
View searchView = inflater.inflate(R.layout.search_list, container, false);
SearchView searchBar = (SearchView)searchView.findViewById(R.id.browse_search);
searchBar.setIconifiedByDefault(false); //Showing text field in search
searchBar.setSubmitButtonEnabled(true);
searchBar.setOnQueryTextListener(this);
return searchView;
}
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
/*Intent intent = new Intent(Intent.ACTION_SEARCH, null, searchActivity, BrowseGrid.class);
intent.putExtra(SearchManager.QUERY, query);
startActivity(intent);*/
Bundle args = new Bundle();
args.putString("search_query", query);
BrowseGrid browseFragment = new BrowseGrid();
browseFragment.setArguments(args);
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.bottom_tab_content, browseFragment);
transaction.addToBackStack(null);
transaction.commit();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
}
and Fragment(B):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.grid_list, container, false);
gridView = (GridView)view.findViewById(R.id.gridView);
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
return view;
}
The aim is very simple. Pressing the back button, Fragment goes back from B to A.
Am I missing something?
As I found that the stack actually has nothing to pop(I wanna know why...), I choose an alternative to do so.
I don't know whether it is the best solution but it seems work.
replace
getFragmentManager().popBackStack();
to
FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount()>0){
//Log.d("Bottom Tab", "popping backstack");
fm.popBackStack();
} else {
//Log.d("Bottom Tab", "nothing can pop");
super.onBackPressed();
}
Even the stack has nothing, it will override the onBackPressed() to go back.
How about try using the SupportFragmentManager on both Activity and Fragment(A)
currently the Fragment (A) is using
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
While in you activity onOptionsItemSelected is using
this.getFragmentManager().popBackStack();
change it to:
getSupportFragmentManager().popBackStack();
Change this line , as you are handling the FragmentTransaction from Fragment class not Activity itself. You need to get getParentFragment() first.
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
To
FragmentTransaction transaction = getActivity().getParentFragment().getFragmentManager().beginTransaction();
transaction.replace(R.id.bottom_tab_content, browseFragment);
Here is my code snippet:
I want to create a new fragment initially, but if the fragment is already created the i want to show the previous fragment;
But every time a new fragment is initialise.
#Override
protected void onCreate(Bundle savedInstanceState) {
.
.
showFragment(FRAGMENT_ADD_DETAILS);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if(currentFragment==FRAGMENT_ADD_DETAILS){
finish();
}else{
showFragment(FRAGMENT_ADD_DETAILS);
}
break;
case R.id.menu_action_next:
showFragment(FRAGMENT_INVITE_FRIENDS);
break;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
.
.
return true;
}
private void showFragment(int fragmentType) {
Log.d(TAG,"showFragment : "+fragmentType);
FragmentManager fragmentManager = getFragmentManager();
Fragment prevFragment = fragmentManager.findFragmentByTag(String.valueOf(fragmentType));
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (prevFragment == null) { //create a fresh instance of fragment
Log.d(TAG,"Initialize new fragment");
Fragment newFragment;
if (fragmentType == FRAGMENT_ADD_DETAILS) {
newFragment = new NewDetailsFragment();
} else {
newFragment = new NewInviteFragment();
}
fragmentTransaction.replace(R.id.ant_container_layout, newFragment);
fragmentTransaction.addToBackStack(String.valueOf(fragmentType));
} else {//just reuse the previous fragment
Log.d(TAG,"Re-Using previous fragment");
fragmentTransaction.replace(R.id.ant_container_layout, prevFragment);
}
fragmentTransaction.commit();
}
Please Help!
You never add any tags to your fragments, so you cannot find them by using findFragmentByTag().
When you replace a fragment, instead of
fragmentTransaction.replace(R.id.ant_container_layout, newFragment);
use the overloaded method that accepts a tag:
fragmentTransaction.replace(R.id.ant_container_layout, newFragment, String.valueOf(fragmentType));
You try to restore your fragments in onCreate() of your activity but it seems that you haven't retained your fragments. They are thus destroyed together with the activity and when the activity is created again, new fragments are created.