I know this has to be simple and I'm probably not seeing the solution.
Here is the brief description of what I have:
SignInActivity(AppCompatActivity) - handle the Firebase authentication, on success calls the method:
private void onAuthSuccess(FirebaseUser user) {
// Go to MainActivity
startActivity(new Intent(SignInActivity.this, MainActivity.class));
finish();
}
MainActivity(AppCompatActivity) - handle the menus for the application, this menu in particular are fragments with buttons. When a button is clicked I change the fragment that contains other buttons. Something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_left)
.replace(R.id.fragmentContent, MainMenuFragment.newInstance())
.commitNow();
}
getSupportFragmentManager().addOnBackStackChangedListener(new
FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
getSupportActionBar().setHomeButtonEnabled(stackHeight > 0);
getSupportActionBar().setDisplayHomeAsUpEnabled(stackHeight > 0);
}
});
}
public void replaceFragments(Class fragmentClass, boolean isBack) {
Fragment fragment = null;
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (isBack) {
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
} else {
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
fragment = null;
e.printStackTrace();
}
if (fragment != null) {
ft.replace(R.id.fragmentContent, fragment);
ft.addToBackStack(fragmentClass.getName());
ft.commit();
}
}
MainMenuFragment(Fragment) - First set of options, several buttons on top of each other. Depending on the button clicked will call MainActivity.replaceFragment passing the next Fragment to go.
public class MainMenuFragment extends Fragment {
private static final String TAG = "MainMenuFragment";
public static MainMenuFragment newInstance() {
return new MainMenuFragment();
}
public MainMenuFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_main_menu, container, false);
final Button btnAssets = view.findViewById(R.id.btnAssets);
final Button btnAudit = view.findViewById(R.id.btnAudit);
btnAssets.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "BtnAssets_onClick");
((MainActivity)getActivity()).replaceFragments(AssetMenuFragment.class);
}
});
btnAudit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "BtnAudit_onClick");
((MainActivity)getActivity()).replaceFragments(AuditMenuFragment.class);
}
});
return view;
}
}
The AssetMenuFragment and the AuditMenuFragment are pretty much the same as the MainMenu, only the text for the buttons and some layout details changes.
When I'm using the app I first signIn, which leads me to the MainActivity, which loads the MainMenuFragment on onCreate. There I'm presented with two buttons, one to go to the AssetMenuFragment and the other to go to the AuditMenuFragment, they replace the fragment with their according layouts.
If I click the Asset button, once the fragment is replaced, because of:
getSupportActionBar().setHomeButtonEnabled(stackHeight > 0);
getSupportActionBar().setDisplayHomeAsUpEnabled(stackHeight > 0);
I'm presented with the back arrow to go back to MainMenuFragment. Everything works as expected.
Now the problem! If I'm in this AssetMenuFragment, with my beautiful back arrow showing on the ActionBar and decided to click the "Square" button on the device, which is probably run the onPause and onStop, and them click on the app again, which will run the onCreate and onStart again, my back arrow disappears, because now int stackHeight = getSupportFragmentManager().getBackStackEntryCount(); is zero.
How can I save my stack and restore it later so I can press back on the AssetMenuFragment and go back to MainMenuFragment.
It is a lot to read, but I'll appreciate the help, thanks!
In the end I knew it had to be something simple.
Both checks are correct.
getSupportActionBar().setHomeButtonEnabled(stackHeight > 0);
getSupportActionBar().setDisplayHomeAsUpEnabled(stackHeight > 0);
The problem was that I didn't check for them on onCreate, only on the getSupportFragmentManager().addOnBackStackChangedListener event.
Here is the MainActivity now:
private ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)
.replace(R.id.fragmentContent, MainMenuFragment.newInstance())
.commitNow();
}
actionBar = getSupportActionBar();
updateActionBarBackButton();
getSupportFragmentManager().addOnBackStackChangedListener(new
FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
updateActionBarBackButton();
}
});
}
private void updateActionBarBackButton() {
int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
getSupportActionBar().setHomeButtonEnabled(stackHeight > 0);
getSupportActionBar().setDisplayHomeAsUpEnabled(stackHeight > 0);
}
I am trying to retain the state of Fragment. I have MotherActivity in which I have FragmentOne,FragmentTwo,FragmentThree and inside from FragmentTwo I am calling another activity ChildActivity. Problem is that When I am pressing back button in ChildActivity it is refreshing MotherActivity and not keeping the state of my FragmentTwo instead it is showing me FragmentOne which come first time.
I only want when I am pressing BackButton from ChildActivity, on container FragmentTwo should be there:
MainAcitivity:
public class MotherActivity extends FragmentActivity {
AHBottomNavigation bottomNavigation;
Fragment selectedFragment = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigation = (AHBottomNavigation) findViewById(R.id.navigation);
bottomNavigation.addItem(item1);
bottomNavigation.addItem(item2);
bottomNavigation.addItem(item3);
bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
#Override
public boolean onTabSelected(int position, boolean wasSelected) {
if (position == 0) {
selectedFragment = FragmentOne.newInstance(bottomNavigation);
} else if (position == 1) {
selectedFragment = FragmentTwo.newInstance(bottomNavigation);
} else if (position == 2) {
selectedFragment = FragmentThree.newInstance(bottomNavigation);
}
android.app.FragmentManager fragmentManager = getFragmentManager();
android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout,selectedFragment);
fragmentTransaction.commit();
return true;
}
});
}
#Override
protected void onStart() {
super.onStart();
android.app.FragmentManager fragmentManager = getFragmentManager();
android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout, FragmentOne.newInstance(bottomNavigation));
fragmentTransaction.commit();
}
public void setNotification(){
bottomNavigation.setNotification("1", 1);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
//No call for super().
}
#Override
public void onBackPressed() {
Intent intent = new Intent();
setResult(113, intent);
finish();
return;
}
}
FragmentTwo from where I am calling childActivity:
public class FragmentTwo extends Fragment {
public static AHBottomNavigation bottomNavigation1;
Card_detail_Adapter_Footer searchabledapter;
public static boolean showAddress = false;
Fragment selectedFragment;
public static FragmentTwo newInstance(AHBottomNavigation bottomNavigation) {
FragmentTwo fragment = new FragmentTwo();
bottomNavigation1 = bottomNavigation;
showNotificationCounter(3);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_cart, container, false);
if(showAddress == true){
showAddress = false;
// From here I am calling ChildActivity
Intent intent = new Intent(getActivity(), ChildActivity.class);
startActivity(intent);
}
return view;
}
}
In ChildActivity simply calling onBackPressed()
The problem is with the onStart() method of your MotherActivity.java because when you open another activity from FragmentTwo, your MotherActivity onStop() gets called. When you press back button from ChildActivity onStart() of MotherActivity called which is replacing FragmentTwo from FragmentOne by committing transaction.
Please have a look at https://developer.android.com/guide/components/activities/activity-lifecycle.html
Put code from onStart() method into onCreate() method and check if configuration been changed:
if (savedInstanceState == null) {
android.app.FragmentManager fragmentManager = getFragmentManager();
android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frame_layout, FragmentOne.newInstance(bottomNavigation));
fragmentTransaction.commit();
}
I have a MainActivity and a HomeTabs with three tabs (A B C), i set a refresh on tab C .
My structure is when i trigger onRefresh on tab C , i will switch to MainActivity
and load the data again to show the HomeTabs.
My problem is when i click back for finish(); , the layout will show tab C.
I try to finish the Fragment use like:
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
or
((MainActivity)getActivity()).removeFragment(getActivity());
Both of them are no working , when i click back , i still can't finish the app immediately.
Some one can teach me what step i miss it , that would be appreciated.
My HomeTabs extends Fragment it use ViewPager and TabLayout add three tabs
MainActivity:
public class MainActivity extends AppCompatActivity {
private FrameLayout frameLayout;
private Toolbar toolBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
// Load the main Fragment
if (savedInstanceState == null) {
switchFragment(HomeTabs.newInstance());
}
//take the onRefresh dataļ¼send data to HomeTabs and open tab C
if (getIntent().hasExtra("refresh")) {
boolean isRefresh = getIntent().getExtras().getBoolean("refresh");
if (isRefresh) {
Bundle bundle = new Bundle();
bundle.putBoolean("refresh", isRefresh);
HomeTabs homeTabs = new HomeTabs();
homeTabs.setArguments(bundle);
switchFragment(homeTabs);
}
}
}
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frameLayout, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
// I try to finsh my tab C , it's no working
public void removeFragment(Activity activity) {
activity.onBackPressed();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
new DialogHandler(this).quickDialog(
getResources().getString(R.string.quick),
getResources().getString(R.string.confirm),
getResources().getString(R.string.cancel),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// If i onRefrsh three times , i will finsh three times... here is my issue.
finish();
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
}
return super.onKeyDown(keyCode, event);
}
}
Here is my tab C Fragment refresh call back method:
public class MyLineChart extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_line_chart, container, false);
//.....................
return view;
}
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
// Both of them are no working.
//((MainActivity)getActivity()).removeFragment(getActivity());
//getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
Intent intent = new Intent(getActivity(),MainActivity.class);
intent.putExtra("refresh", true);
startActivity(intent);
}
Finally my HomeTabs Fragment take the date and show tab C:
Bundle bundle = getArguments();
if (bundle != null) {
boolean isRefresh = bundle.getBoolean("refresh");
if (isRefresh) {
//tab C position is 2
tabLayout.getTabAt(2).select();
}
}
Try this solution to add below code when you are starting activity again on Refresh click:-
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
OR
Update your MainActivity.java
1) Add function in MainActivity
public void refreshFragment() {
Bundle bundle = new Bundle();
bundle.putBoolean("refresh", isRefresh);
HomeTabs homeTabs = new HomeTabs();
homeTabs.setArguments(bundle);
switchFragment(homeTabs);
}
Now Call that from Fragment Tab C just replacing startActivity(refresh) code:
MainActivity mainActivity = (MainActivity) getActivity();
mainActivity.refreshFragment();
you can add a listener in your fragment that can trigger a function in your parent activity
which means you need to add an interface in your fragmentC code
public class MyLineChart extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private MyLineChartListener fragmentListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_line_chart, container, false);
//.....................
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MyLineChartListener) {
fragmentListener = (MyLineChartListener) context;
} else {
// throw an error
}
}
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
// Both of them are no working.
//((MainActivity)getActivity()).removeFragment(getActivity());
//getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
fragmentListener.onSettingRefresh();
}
public interface MyLineChartListener {
void onSettingRefresh();
}
}
then you need to implement the listener in the MainActivity code as follows
public class MainActivity extends AppCompatActivity implements MyLineChart.MyLineChartListener {
private FrameLayout frameLayout;
private Toolbar toolBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
// Load the main Fragment
if (savedInstanceState == null) {
switchFragment(HomeTabs.newInstance());
}
}
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frameLayout, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
// I try to finsh my tab C , it's no working
public void removeFragment(Activity activity) {
activity.onBackPressed();
}
// this function will be called when the fragment is refreshed
#Override
public void onSettingRefresh() {
Bundle bundle = new Bundle();
bundle.putBoolean("refresh", true);
HomeTabs homeTabs = new HomeTabs();
homeTabs.setArguments(bundle);
switchFragment(homeTabs);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
new DialogHandler(this).quickDialog(
getResources().getString(R.string.quick),
getResources().getString(R.string.confirm),
getResources().getString(R.string.cancel),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// If i onRefrsh three times , i will finsh three times... here is my issue.
finish();
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
}
return super.onKeyDown(keyCode, event);
}
}
I am working on a bottom navigation bar, but I am not getting perfectly bottom navigation bar.
My MainActivity class:
public class MainActivity extends AppCompatActivity {
private static final String SELECTED_ITEM = "selected_item";
private BottomNavigationView bottomNavigationView;
private Toolbar toolbar;
private MenuItem menuItemSelected;
private int mMenuItemSelected;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
selectFragment(item);
return true;
}
});
//Always load first fragment as default
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, new AnnouncementFragment());
fragmentTransaction.commit();
if (savedInstanceState != null) {
mMenuItemSelected = savedInstanceState.getInt(SELECTED_ITEM, 0);
menuItemSelected = bottomNavigationView.getMenu().findItem(mMenuItemSelected);
} else {
menuItemSelected = bottomNavigationView.getMenu().getItem(0);
}
selectFragment(menuItemSelected);
}
private void selectFragment(MenuItem item) {
Fragment fragment = null;
Class fragmentClass;
switch (item.getItemId()) {
case R.id.action_announcement:
fragmentClass = AnnouncementFragment.class;
break;
case R.id.action_menu:
fragmentClass = MenuFragment.class;
break;
case R.id.action_menu_reports:
fragmentClass = ReportFragment.class;
break;
case R.id.action_setting:
fragmentClass = SettingFragment.class;
break;
default:
fragmentClass = AnnouncementFragment.class;
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frameLayout, fragment).commit();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(SELECTED_ITEM, mMenuItemSelected);
super.onSaveInstanceState(outState);
}
And my back pressed also not working properly:
#Override
public void onBackPressed() {
MenuItem homeItem = bottomNavigationView.getMenu().getItem(0);
if (mMenuItemSelected != homeItem.getItemId()) {
selectFragment(homeItem);
} else {
super.onBackPressed();
}
}
How should I do that because bottom menu has uneven distribution on bar. How to properly maintain the menu space without uneven distribution.
Here I am attaching my result which I obtain on AVD
According to the guidelines for Material Design
On Android, the Back button does not navigate between bottom
navigation bar views.
EDIT: Material Design link no longer mentions back button behavior.
Pressing the back button you can quit the application, which is the default behavior, such as in Google Photo...
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content, fragment);
// note: there is NOT a addToBackStack call
fragmentTransaction.commit();
...or lead the user to the home section and then, if pushed again, at the exit.
Personally I find this last pattern much better.
To get it without override onBackPressed you need to identify the home fragment and differentiate it from all the others
navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
viewFragment(new HomeFragment(), FRAGMENT_HOME);
return true;
case R.id.navigation_page_1:
viewFragment(new OneFragment(), FRAGMENT_OTHER);
return true;
case R.id.navigation_page_2:
viewFragment(new TwoFragment(), FRAGMENT_OTHER);
return true;
}
return false;
}
});
What you have to do now is write the viewfragment method that have to:
Know how many fragments there are in the stack before the commit
If the fragment is not "home type", save it to the stack before
the commit
Add an OnBackStackChangedListener that when the stack decreases,
(i.e. when I pressed back ), delete all the fragments that are
not "home type" (POP_BACK_STACK_INCLUSIVE) , bringing us to the home fragment
Below the full method with comments
private void viewFragment(Fragment fragment, String name){
final FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content, fragment);
// 1. Know how many fragments there are in the stack
final int count = fragmentManager.getBackStackEntryCount();
// 2. If the fragment is **not** "home type", save it to the stack
if( name.equals( FRAGMENT_OTHER) ) {
fragmentTransaction.addToBackStack(name);
}
// Commit !
fragmentTransaction.commit();
// 3. After the commit, if the fragment is not an "home type" the back stack is changed, triggering the
// OnBackStackChanged callback
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
// If the stack decreases it means I clicked the back button
if( fragmentManager.getBackStackEntryCount() <= count){
// pop all the fragment and remove the listener
fragmentManager.popBackStack(FRAGMENT_OTHER, POP_BACK_STACK_INCLUSIVE);
fragmentManager.removeOnBackStackChangedListener(this);
// set the home button selected
navigation.getMenu().getItem(0).setChecked(true);
}
}
});
}
Try this
#Override
public void onBackPressed() {
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
int seletedItemId = bottomNavigationView.getSelectedItemId();
if (R.id.home != seletedItemId) {
setHomeItem(MainActivity.this);
} else {
super.onBackPressed();
}
}
public static void setHomeItem(Activity activity) {
BottomNavigationView bottomNavigationView = (BottomNavigationView)
activity.findViewById(R.id.navigation);
bottomNavigationView.setSelectedItemId(R.id.home);
}
#Override
public void onBackPressed() {
BottomNavigationView mBottomNavigationView = findViewById(R.id.navigation);
if (mBottomNavigationView.getSelectedItemId() == R.id.navigation_home)
{
super.onBackPressed();
finish();
}
else
{
mBottomNavigationView.setSelectedItemId(R.id.navigation_home);
}
}
This is maybe a little late but I think the best way to do it is as simple as this.
#Override
public void onBackPressed() {
if (mBottomNavigationView.getSelectedItemId() == R.id.action_home) {
super.onBackPressed();
} else {
mBottomNavigationView.setSelectedItemId(R.id.action_home);
}
}
I hope it helps and happy coding :)
onBackPressed did not worked for me. So this I used.
#Override
protected void onResume() {
super.onResume();
bottomNavigationView.getMenu().getItem(0).setChecked(true);
}
The best way is: when in home button the app is closed and when in another button back in home button.
Below I put my code :
first i'm load home button in navigation View :
private void loadFragment(Fragment fragment) {
Toast.makeText(this, "load", Toast.LENGTH_SHORT).show();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, fragment, TAG_FRAGMENT);
transaction.commit();
}
and remember dont call addToBackStack() .
and then handle the situation by onBackPressed() :
#Override
public void onBackPressed() {
if (navigation.getSelectedItemId() == R.id.bottomAkhbar) {
super.onBackPressed();
} else {
navigation.setSelectedItemId(R.id.bottomAkhbar);
}
}
I had the same problem so I solved my problem using this method:
In my main activity, I have a bottom nav bar and a nav drawer, I need to sync items in my drawer and bottom nav:
I created a method for my main fragment and the others:
my main fragment replacer:
public void MainFragmentChanger(final Fragment fragment, final String TAG){
if (main_page_fragment != null){
fragmentTransaction = myFragmentManager.beginTransaction();
fragmentTransaction.remove(main_page_fragment).commit();
}
if (main_drawer.isDrawerOpen()){
main_drawer.closeDrawer();
}
new Handler().post(new Runnable() {
#Override
public void run() {
main_page_fragment = fragment;
main_page_fragment.setRetainInstance(true);
fragmentTransaction = myFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.main_container, main_page_fragment,TAG);
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragmentTransaction.commitAllowingStateLoss();
}
});
}
and this is for my other fragment replacer:
public void changeBottomFragment(final Fragment fragment, final String TAG){
if (main_drawer.isDrawerOpen()){
main_drawer.closeDrawer();
}
new Handler().post(new Runnable() {
#Override
public void run() {
main_page_fragment = fragment;
main_page_fragment.setRetainInstance(true);
fragmentTransaction = myFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.main_container, main_page_fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragmentTransaction.commitAllowingStateLoss();
}
});
}
so after that, I need to sync items in both drawer and bar:
Note I use material navigation drawer by Mike Penz, and com.ashokvarma.bottomnavigation.BottomNavigationBar for nav bar.
here is the method for that purpose:
public void changeNavAndBarStats(String tag){
if (tag == "flash"){
bottomNavigationBar.selectTab(2,false);
main_drawer.setSelection(flashcards.getIdentifier(),false);
}else if (tag == "dic"){
bottomNavigationBar.selectTab(3,false);
main_drawer.setSelection(dictionary.getIdentifier(),false);
}else if (tag == "Home"){
bottomNavigationBar.selectTab(0,false);
main_drawer.setSelection(home.getIdentifier(),false);
}
}
So I call my fragments Like this:
MainFragmentChanger(new MainPageFragment(),"Home");
bottomNavigationBar.selectTab(0,false);
changeBottomFragment(new FlashCardFragment(),"flash");
bottomNavigationBar.selectTab(2,false);
changeBottomFragment(new TranslateFragment(),"dic");
bottomNavigationBar.selectTab(3,false);
At the end I call changeNavAndBarStatus in my fragment's onResume method:
((MainPageActivity)getContext()).changeNavAndBarStats("flash");
That's it! you are good to go!
Try this to achieve the following:
on back press:
from home fragment exit the app.
from other fragments goto home fragment.
//On Back Press if we are at a Fragment other than the Home Fragment it will navigate back to the
// Home Fragment. From Home Fragment it will exit the App.
#Override
public void onBackPressed() {
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntryCount == 0) {
super.onBackPressed();
} else {
goHome();
}
}
public void goHome() {
//Following code will set the icon of the bottom navigation to active
final BottomNavigationView mBottomNav = findViewById(R.id.nav_view);
MenuItem homeItem = mBottomNav.getMenu().getItem(0);
mBottomNav.setSelectedItemId(homeItem.getItemId());
getSupportFragmentManager().popBackStackImmediate();
//To delete all entries from back stack immediately one by one.
int backStackEntry = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackEntry; i++) {
getSupportFragmentManager().popBackStackImmediate();
}
//To navigate to the Home Fragment
final HomeFragment homeFragment = new HomeFragment();
FragmentTransaction myFragmentTransaction = getSupportFragmentManager().beginTransaction();
myFragmentTransaction.replace(R.id.nav_host_fragment, homeFragment, "HomeFrag Tag");
myFragmentTransaction.commit();
}
You can try this /
its worked for me
public class MainActivity extends BaseActivity {
private HomeFragment homeFragment = new HomeFragment();
private CartFragment cartFragment = new CartFragment();
private ProfileFragment profileFragment = new ProfileFragment();
private BottomNavigationView bottomNavigationView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null){
setContentView(R.layout.activity_main);
bottomNavigationView = findViewById(R.id.bottom_nav);
bottomNavigationView.setSelectedItemId(R.id.btnHome);
FragmentTransaction homeFm = getSupportFragmentManager().beginTransaction();
homeFm.replace(R.id.fragment_container, homeFragment);
homeFm.commit();
setupView();
}
}
private void setupView() {
bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
{
switch (item.getItemId()) {
case R.id.btnHome:
loadFragment(homeFragment);
return true;
case R.id.btnCart:
loadFragment(cartFragment);
return true;
case R.id.btnProfile:
loadFragment(profileFragment);
return true;
}
return false;
}
});
}
private void loadFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onBackPressed() {
if (bottomNavigationView.getSelectedItemId() == R.id.btnHome)
{
finish();
}
else
{
bottomNavigationView.setSelectedItemId(R.id.btnHome);
}
}}
Use addToBackStack Method when calling a fragment like this,
getSupportFragmentManager().beginTransaction().addToBackStack(null).add(R.id.content_home_nav,newFragment).commit();
Use this code in your onBackPressed Method
if (getSupportFragmentManager().getBackStackEntryCount() > 0 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
For your requirement you would be working with fragments on navigation for this you can use Tablayout with view pager and make bottom navigation.
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="60dp"></android.support.design.widget.TabLayout>
and then setup viewpager with tab layout and add icon to tablayout in your activity
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
viewPager = (ViewPager) findViewById(R.id.controller_pager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
viewPager.setOffscreenPageLimit(4);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.selector_home);
tabLayout.getTabAt(1).setIcon(R.drawable.selector_contact);
tabLayout.getTabAt(2).setIcon(R.drawable.selector_profile);
tabLayout.getTabAt(3).setIcon(R.drawable.selector_settings);
now handle all things on the click of tablayout and it will work fine
tabLayout.addOnTabSelectedListener(this);
I was facing the same problem but after doing this I got the solution
First Paste this code in your main activity (where you are using Bottom navigation bar)
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
And then create a class named BottomNavigationViewHelper and paste the following code.
public class BottomNavigationViewHelper {
public static void disableShiftMode(BottomNavigationView view) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
shiftingMode.setAccessible(true);
shiftingMode.setBoolean(menuView, false);
shiftingMode.setAccessible(false);
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
//noinspection RestrictedApi
item.setShiftingMode(false);
// set once again checked value, so view will be updated
//noinspection RestrictedApi
item.setChecked(item.getItemData().isChecked());
}
} catch (NoSuchFieldException e) {
Log.e("BNVHelper", "Unable to get shift mode field", e);
} catch (IllegalAccessException e) {
Log.e("BNVHelper", "Unable to change value of shift mode", e);
}
}
}
Hope It helps
Try this.
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
// Gets the previous global stack count
int previousStackCount = mPreviousStackCount;
// Gets a FragmentManager instance
FragmentManager localFragmentManager = getSupportFragmentManager();
// Sets the current back stack count
int currentStackCount = localFragmentManager.getBackStackEntryCount();
// Re-sets the global stack count to be the current count
mPreviousStackCount = currentStackCount;
boolean popping = currentStackCount < previousStackCount;
if(popping){
bottomNavigationView.getMenu().getItem(0).setChecked(true);
}
}
});
Please try this solution.
I have made changes in your code given in question.
I have assumed that on back pressing first time your app will come back to home fragment (in your case Announcement fragment) and if you back press again, the app will close.
This flow will also reflect in bottom navigation bar.
public class MainActivity extends AppCompatActivity {
private static final String BACK_STACK_ROOT_TAG = "root_home_fragment";
private static final String SELECTED_ITEM = "selected_item";
private Fragment fragment;
private FragmentManager fragmentManager;
private BottomNavigationView bottomNavigationView;
private Toolbar toolbar;
private MenuItem menuItemSelected;
private int mMenuItemSelected;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
boolean selected = false;
switch (item.getItemId()) {
case R.id.action_announcement:
fragment = AnnouncementFragment.newInstance();
selected = true;
break;
case R.id.action_menu:
fragment = MenuFragment.newInstance();
selected = true;
break;
case R.id.action_menu_reports:
fragment = ReportFragment.newInstance();
selected = true;
break;
case R.id.action_setting:
fragment = SettingFragment.newInstance();
selected = true;
}
if(fragment !=null){
fragmentManager = getFragmentManager();
switch (item.getItemId()) {
case R.id.action_announcement:
// Pop every fragment from backstack including home fragment.
fragmentManager.popBackStack(BACK_STACK_ROOT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction()
.replace(R.id.content, fragment)
.addToBackStack(BACK_STACK_ROOT_TAG)
.commit();
break;
default:
fragmentManager.beginTransaction()
.replace(R.id.content, fragment)
.addToBackStack(null)
.commit();
break;
}
}
return selected;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
//Always load first fragment as default
bottomNavigationView.setSelectedItemId(R.id.action_announcement);
if (savedInstanceState != null) {
mMenuItemSelected = savedInstanceState.getInt(SELECTED_ITEM, 0);
menuItemSelected = bottomNavigationView.getMenu().findItem(mMenuItemSelected);
} else {
menuItemSelected = bottomNavigationView.getMenu().getItem(0);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(SELECTED_ITEM, mMenuItemSelected);
super.onSaveInstanceState(outState);
}
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if(count >1){
// We have lots of fragment on backstack to be popped.
// Pop till the root fragment.
getFragmentManager().popBackStack(BACK_STACK_ROOT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
bottomNavigationView.setSelectedItemId(R.id.action_announcement);
}
else{
// Close the application when we are on home fragment.
supportFinishAfterTransition();
}
}
}
Most time when you, press back button, old fragment in the back stack,
are recalled. therefore the system call this onCreateView() method
there add this code
val bottomNav = activity?.findViewById<BottomNavigationView>(R.id.activity_main_bottom_navigation)
bottomNav?.selectedItemId = R.id.the_id_of_the_icon__that_represent_the_fragment
I did this after trying all and everything and at last it worked -_- .I have pasted this 2 override method in my each and every activity that i am surfing through my bottom navigation.
#Override
protected void onResume() {
super.onResume();
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_Menu_name);
bottomNavigationView.getMenu().getItem(Menu_item_position).setChecked(true);
}
#Override
protected void onRestart() {
super.onRestart();
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_Menu_name);
bottomNavigationView.getMenu().getItem(Menu_item_position).setChecked(true);
}
Late answer but here it goes.
Let's say you have a BottomNavigation inside MainActivity with 4 Fragments.
FragmentA
FragmentB
FragmentC
FragmentD
If your are adding each fragment to backstack like so:
With kotlin:
main_bottom_navigation.setOnNavigationItemSelectedListener { item ->
var fragment: Fragment? = null
when (item.itemId) {
R.id.nav_a -> fragment = FragmentA()
R.id.nav_b -> fragment = FragmentB()
R.id.nav_c -> fragment = FragmentC()
R.id.nav_d -> fragment = FragmentD()
}
supportFragmentManager
.beginTransaction()
.setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out)
.replace(R.id.home_content, fragment!!)
.addToBackStack(fragment.tag)
.commit()
true
}
You dont really need to override onBackPressed() inside the MainActivity but explicitly cast on each fragment and assigning the BottomNavigation like this:
FragmentA.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).main_bottom_navigation.menu.getItem(0).isChecked = true
}
FragmentB.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).main_bottom_navigation.menu.getItem(1).isChecked = true
}
FragmentC.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).main_bottom_navigation.menu.getItem(2).isChecked = true
}
FragmentD.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).main_bottom_navigation.menu.getItem(3).isChecked = true
}
Like this the fragment backstack will properly pop and even exit application when it reaches 0.
This is what I did to handle back press in the activity:
#Override
public void onBackPressed() {
super.onBackPressed();
if(homeFragment.isVisible()){
navView.setSelectedItemId(R.id.nav_home);
}
if(searchFragment.isVisible()){
navView.setSelectedItemId(R.id.nav_search);
}
if(myProfileFragment.isVisible()){
navView.setSelectedItemId(R.id.nav_profile);
}
}
this code is work for me:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OneSignal.startInit(this)
.inFocusDisplaying(OneSignal.OSInFocusDisplayOption.Notification)
.unsubscribeWhenNotificationsAreDisabled(true)
.init();
bottomNavigationView = findViewById(R.id.bottomNav);
frameLayout = findViewById(R.id.main_frame);
homeFragment = new HomeFragment();
aboutUsFragment = new AboutUsFragment();
recipesFragment = new RecipesFragment();
knowledgeFragment = new KnowledgeFragment();
contactFragment = new ContactFragment();
loadFragment(homeFragment);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.home:
//mManiNav.setItemBackgroundResource(R.color.blue);
loadFragment(homeFragment);
return true;
case R.id.deposit:
// mManiNav.setItemBackgroundResource(R.color.colorAccent);
loadFragment(recipesFragment);
return true;
case R.id.exchange:
//mManiNav.setItemBackgroundResource(R.color.colorPrimary);
loadFragment(knowledgeFragment);
return true;
case R.id.profile:
// mManiNav.setItemBackgroundResource(R.color.light_blue);
loadFragment(aboutUsFragment);
return true;
case R.id.payout:
// mManiNav.setItemBackgroundResource(R.color.light_blue);
loadFragment(contactFragment);
return true;
default:
return false;
}
}
});
}
Here the load fragment class:
private void loadFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.main_frame, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Here is the popBackStackTillEntry method:
enter code here public void popBackStackTillEntry(int entryIndex) {
if (getSupportFragmentManager() == null) {
return;
}
if (getSupportFragmentManager().getBackStackEntryCount() <= entryIndex) {
return;
}
FragmentManager.BackStackEntry entry = getSupportFragmentManager().getBackStackEntryAt(
entryIndex);
if (entry != null) {
getSupportFragmentManager().popBackStackImmediate(entry.getId(),
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
Here is the backpress method:
boolean doubleBackToExitPressedOnce = false;
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
popBackStackTillEntry(0);
moveTaskToBack(true);
System.exit(0);
return;
}
this.doubleBackToExitPressedOnce = true;
loadFragment(new HomeFragment());
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce=false;
}
}, 2000);
}
This is a simple and complete working code in Kotlin.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bottomNavigationView = findViewById(R.id.bottom_navigation)
bottomNavigationView.setOnItemSelectedListener {menuItem ->
when(menuItem.itemId){
R.id.navBottom_menu_1 -> nextFragment(Fragment_1())
R.id.navBottom_menu_2 -> nextFragment(Fragment_2())
R.id.navBottom_menu_3 -> nextFragment(Fragment_3())
R.id.navBottom_menu_4 -> nextFragment(Fragment_4())
else ->false
}
}
}
fun nextFragment(fm:Fragment): Boolean {
supportFragmentManager.beginTransaction().replace(R.id.linearLayout_rootFragment, fm).commit()
return true
}
fun isMenuChecked(itemIndex:Int):Boolean{
return bottomNavigationView.menu.getItem(itemIndex).isChecked
}
fun setMenuItemChecked(itemIndex:Int){
bottomNavigationView.menu.getItem(itemIndex).isChecked = true
}
override fun onBackPressed() {
when(true){
isMenuChecked(3) -> {nextFragment(Fragment_3()) ; setMenuItemChecked(2) }
isMenuChecked(2) -> {nextFragment(Fragment_2()) ; setMenuItemChecked(1) }
isMenuChecked(1) -> {nextFragment(Fragment_1()) ; setMenuItemChecked(0) }
else -> super.onBackPressed()
}
}
}
This is how I solved my,
Wrap your main widget in WillPopScope() and set a function in the onWillpop: as this
Future<bool> _onBackpress() {
if (_currentpage != 0) {
setState(() {
_currentpage--;//decreases number of pages till the fisrt page
});
} else {
// a function to close the app
}
}
I have a main activity which contains the action bar with 3 menu buttons in it.
I then have a fragment within this main activity which has a list.
I would like to be able to refresh the list in the fragment from the main activity, when one of the menu buttons is clicked, or preferably just removed all the rows from the list.
Any help is appreciated.
Thanks.
public class Favourite extends SherlockFragmentActivity {
ActionBar actionBar;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favourite);
actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
BitmapDrawable bg = (BitmapDrawable)getResources().getDrawable(R.drawable.actionbar_bg);
bg.setTileModeX(TileMode.REPEAT);
getSupportActionBar().setBackgroundDrawable(bg);
getSupportActionBar().setIcon(R.drawable.favourite_title);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tabAll = actionBar.newTab();
ActionBar.Tab tabfavs = actionBar.newTab();
ActionBar.Tab tabhist = actionBar.newTab();
tabAll.setText("all");
tabfavs.setText("favs");
tabhist.setText("hist");
tabAll.setTabListener(new MyTabListener());
tabfavs.setTabListener(new MyTabListener());
tabhist.setTabListener(new MyTabListener());
actionBar.addTab(tabAll);
actionBar.addTab(tabfavs);
actionBar.addTab(tabhist);
try{
}
catch(Exception e)
{
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.actionbar_itemlist_favourite, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.history:
break;
case R.id.favourite:
Intent favAct = new Intent(this, Favourite.class);
startActivity(favAct);
break;
case R.id.delete:
///I WANT TO BE ABLE TO REFRESH FRAGMENTLIST FROM HERE
}
return true;
}
}
class MyTabListener implements ActionBar.TabListener {
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if(tab.getPosition()==0)
{
FavouriteAllWords frag = new FavouriteAllWords();
ft.replace(android.R.id.content, frag);
}
else if(tab.getPosition()==1)
{
FavouriteFavWords frag = new FavouriteFavWords();
ft.replace(android.R.id.content, frag);
}
else if(tab.getPosition()==2)
{
FavouriteHistWords frag = new FavouriteHistWords();
ft.replace(android.R.id.content, frag);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
////////////////////MY LIST FRAGMENT CLASS
public class FavouriteAllWords extends ListFragment {
ArrayAdapter<String> adapter;
List<String> stringOfFavWords;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved)
{
adapter = new ArrayAdapter<String>(
inflater.getContext(), R.layout.row, stringOfFavWords);
setListAdapter(adapter);
return super.onCreateView(inflater, group, saved);
}
#Override
public void onActivityCreated (Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
}
}
You can easily achieve this using INTERFACE
MainActivity.java
public class MainActivity extends Activity {
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
private FragmentRefreshListener fragmentRefreshListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button)findViewById(R.id.btnRefreshFragment);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(getFragmentRefreshListener()!=null){
getFragmentRefreshListener().onRefresh();
}
}
});
}
public interface FragmentRefreshListener{
void onRefresh();
}
}
MyFragment.java
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = null; // some view
/// Your Code
((MainActivity)getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {
#Override
public void onRefresh() {
// Refresh Your Fragment
}
});
return v;
}
}
Just make your update/refresh method public and call it from your Activity.
OR
Use LocalBroadcastManager or EventBus to send event from your Activity, and by subscribing to this event in a Fragment - react to it and call refresh/update method.
Your activity can call methods in the fragment by acquiring a reference to the Fragment.
(1) Provide a tag when you add your fragment.
transaction.add(R.id.fragment_container, myFragment, "myfragmentTag");
(2) In your hosting activity you can find the fragment and have access to it's methods.
FragmentManager fm = getSupportFragmentManager();
myFragment f = (myFragment) fm.findFragmentByTag("myfragmentTag");
f.refreshAdapter()
(3) refreshAdapter() could now call adapter.notifyDataSetChanged().
This is one of the recommended ways to communicate up to a fragment.
The interface implementation is mainly for communicating back to the activity.
Biraj Zalavadia's answer is 100% right, you will call nay fragment methods from using interface....
this interface methods is running without error...
use this in MainActivity above oncreate
private FragmentRefreshListener fragmentRefreshListener;
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(
FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
inside of Activity
private void refreshcall(String result2) {
// TODO Auto-generated method stub
if (getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh(result2);
}
}
and put this in needed Fragment
private FragmentRefreshListener fragmentRefreshListener;
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(
FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
Communicating with Other Fragments
http://developer.android.com/training/basics/fragments/communicating.html
This can also be used to communicate between an Activity and a Fragment.
When you click on ActionBar any Button then call interface to refresh the ListFragment. Because in java interface is used for inter-communication.
In Kotlin
Get the list of Support Fragment from the activity and check Instance and then call fragment function
val fragments = supportFragmentManager.fragments
for (fragment in fragments) {
if (fragment is HomeCategoriesFragment) {
fragment.updateAdapter() // Define function in Fragment
}
}