In my main activity ActionBarDrawerToggle object is present. I have to disable navigation drawer for a specific fragment (eg. fragmentB) which is called by another fragment (eg.fragmentA),where fragmentA has been inflated by the MainActivity. How to do that?
Add this method to your main activity and call it when you switch the fragments to enable/disable the navigation drawer
public void enableNavigationDrawer(boolean isEnabled) {
getActionBar().setDisplayHomeAsUpEnabled(isEnabled);
getActionBar().setHomeButtonEnabled(isEnabled);
if(isEnabled){
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
} else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}
}
step 1:
interface DrawerLocker{
public void setDrawerLocked(boolean shouldLock);
}
use this in ur main activity ,paste this code in above ur class.
step 2 :
go to ur fragment where u want to hide the navigation drawer, into onCreateView() methode paste this code
((DrawerLocker)getActivity()).setDrawerLocked(true);
step 3: create onDestroyView() method as below :
#Override
public void onDestroyView() {
super.onDestroyView();
((DrawerLocker)getActivity()).setDrawerLocked(false);
}
now run ur code and see:-) ,credit goes to another member ...i didt remember his name ...his answer helps me to solve this problem
Related
Problem in short:
I have an MainActivity that holds BottomNavigationView and FrameLayout on top of it. BottomNavigationView has 5 tabs and when tab is clicked, I add some fragment on that FrameLayout. But, from some fragment, I need to open another fragment. From that another fragment, I need to open the other one. Every time when I need to show fragment, I notify MainActivity from fragment, that it needs to add the another one. Every fragment checks does its activity implement interface. And it is annoying. So, if I have 100 fragments, MainActivity implements too many interfaces. It leads to boilerplate code. So, how to properly navigate between fragments if you have a lot?
Problem in detail:
Please, read problem in short section first.
As I've said I have BottomNavigationView that has 5 tabs. Let's call the fragments that responsible for each tab as FragmentA, FragmentB, FragmentC, FragmentD, FragmentE. I really know, how to show these fragments when tab is clicked. I just replace/add these fragments in activity. But, wait, what if you wanna go from FragmentA to FragmentF? After that from FragmentF to FragmentG? This is how I handle this problem: from FragmentF or FragmentG I notify MainActivity that I wanna change the fragment. But how they communicate with MainActivity? For this, I have interfaces inside of each fragment. MainActivity implements those interfaces. And here is problem. MainActivity implements too many interfaces that leads to boilerplate code. So, what is the best way to navigate through Fragments? I don't even touch that I also need to handle back button presses :)
Here is how my code looks like:
MainActivity implementing interfaces to change fragments if necessary:
class MainActivity : AppCompatActivity(), DashboardFragment.OnFragmentInteractionListener,
PaymentFragment.BigCategoryChosenListener, PaymentSubcategoryFragment.ItemClickedListener, PayServiceFragment.OnPayServiceListener, ContactListFragment.ContactTapListener, P2PFragment.P2PNotifier
Here is my PaymentFragment's onAttach method for example:
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof BigCategoryChosenListener) {
listener = (BigCategoryChosenListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement BigCategoryChosenListener");
}
}
And using this listener I notify activity to change fragment. And in EACH fragment I should do so. I don't think that it is best practice. So, is it ok or there is a better way?
Ok What you need is something like this in activity where you would initialized on your BottomNavigationView.
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_1://Handle menu click -
//Call Navigator helper to replace Fragment to Fragment A
break;
case R.id.menu_2:
//Call Navigator helper to replace Fragment to Fragment B
break;
case R.id.menu_3:
//Call Navigator helper to replace Fragment to Fragment C
break;
}
return true;
}
});
I implemented the new NavigationView (from the support library) and a couple of Fragments, I then overrided the onBackPressed function and added this:
getFragmentManager().popBackStack();
which returns me to the previous fragment.
So what I need is this: how I can change the navigationview's current selected item to the Fragment it is popping back to?
Finally i got it,
Firstly, i made the instance of the navigation global and public.
public NavigationView navigationview;
I then added in the onCreate and onResume of my fragment:
NavigationView navigationView = ((MainActivity) getActivity()).navigationview;
navigationView.getMenu().getItem(index).setChecked(true);
and the onResume:
navigationView.getMenu().getItem(index).setChecked(true);
This solved my problem, Hope this helps someone.
I know this is a little late but I found a solution that is maybe a little faster to code for Activities that have a large amount of fragments.
(In your activity)
Implement FragmentManager.OnBackStackChangedListener
In onCreate() add fragmentManager.addOnBackStackChangedListener(this);
Add Method from interface...
#Override
public void onBackStackChanged() {
MainActivityFragment f = (MainActivityFragment) fragmentManager.findFragmentById(R.id.fragment_container);
//Log.v(TAG, "OnBackStackChanged to fragment with index: " + f.getMenuIndex());
navigationView.getMenu().getItem(f.getMenuIndex()).setChecked(true);
}
(Create an interface in a separate file, name it MainActivityFragment) or whatever your activity is named.
public interface MainActivityFragment {
int getMenuIndex();
}
(All fragments that are used in that Activity)
Implement MainActivityFragment
Add Method from interface...
#Override
public int getMenuIndex() {
return 2;
}
It may seem like some extra work but in the long run it makes it pretty easy as all you have to do for new Fragments is implement the Activity's Interface and return the index of it's menu item.
I am working or an app where I have 4 fragments in viewpager and floating action button (fab). When I click on fab there appear 3 subfabs. Each of them start different activities where user can search data from different fragments. Is it possible to set fab so that if I click on it while I'm in first fragment it'll open an activity for searching inside this fragment, onClick inside second - search for second and etc. The issue is that now clicking on sub fab while I'm in some fragment I can search data from another fragment too and it's a bit weird. I understand question is kinda strange, if something is unclear I'll explain further
You can make FAB button public and implement onClick listener in each fragment.
You should override setUserVisibleHint and put your code onResume so getActivity() will not return null. Fab button will have different actions in different fragments.
Here's an example, inside each fragment when you want Fab click listener:
#Override
public void setUserVisibleHint(boolean visible)
{
super.setUserVisibleHint(visible);
if (visible && isResumed())
{
onResume();
}
}
#Override
public void onResume()
{
super.onResume();
if (!getUserVisibleHint())
{
return;
}
MainActivity mainActivity = (MainActivity)getActivity();
mainActivity.fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Do what you want
}
});
}
You can check in onclick method of floating action button which fragment is currently opened and calling it.
Call findFragmentById() on FragmentManager and determine which fragment is in your R.id.frameTitle container.
I have 2 viewpagers: swipeViewPager and nonSwipeViewPager in MainActivity
In swipeableViewPager, I have fragments: homeFragmentFirst and homeFragmentSecond
In nonSwipeableViewPager, I have fragments: AppleFragment , MangoFragment, GrapesFragment and CherryFragment
First I want swipeableViewPager to be viewed in MainActivity. So I have set setVisibility of nonSwipeableViewPager as GONE.
After selecting an item from the drawer, I setVisibility of swipeableViewPager as GONE and of nonSwipeableViewPager as Visible.
By this, I open AppleFragment
Situation:
Suppose, I selected Grapes from drawer, GrapesFragment opens.
I do my some stuff there. And then when I press back button, the app closes i.e. the MainActivity closes.
What I want is when back button is pressed, I want to again bring back homeFragmentFirst from swipeableViewPager.
I have tried below code in GrapesFragment
#Override
public void onBackPressed() {
super.onBackPressed();
// Do some operations here
MainActivity mainActivity = new MainActivity();
mainActivity.swipeHomeViewPager.setVisibility(View.VISIBLE);
mainActivity.nonSwipeHomeViewPager.setVisibility(View.GONE);
}
I solved it myself. I added following in MainActivity:
#Override
public void onBackPressed() {
if (nonSwipeHomeViewPager.getVisibility() == View.VISIBLE) {
nonSwipeHomeViewPager.setVisibility(View.GONE);
swipeHomeViewPager.setVisibility(View.VISIBLE);
swipeHomeViewPager.setCurrentItem(0,true);
} else if (swipeHomeViewPager.getVisibility() == View.VISIBLE){
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
}
You can implement backstack for the fragments (while adding / replacing fragment) add it to backstack. the back press will automatically take you to previous fragment.
otherwise you need to override OnBackPressed method to handle with your own logic.
I know that question about refreshing actionbar title has already been answered.
But my problem is quiet different.
I use fragments with add method and not with replace method for some reasons. So previous fragment are not destroy and when back, previous fragment aren't not recreating.
This is my configuration :
Fragment A with title "FragA" > Fragment B with title "FragB"
When I go back to Fragment A from Fragment B the actionbar title should be "FragA" but it stay "FragB".
The problem is with add method Fragment A is not recreating and I didn't find event to refresh it.
The only simple solution I found for now is :
1- fragB.OnResume : save previous action bar title
2- fragB.OnDestroyView : restore previous actionbar title
With this solution, the result is ok, but I found this solution is not very clean. Is there a better way to refresh actionbartitle using add method with fragments ?
You can override your onBackPressed of your activity and each time you pressed it you then get the name of the fragment from the backstack to know which fragment you current at.
sample:
#Override
public void onBackPressed() {
super.onBackPressed();
int framentCount = this.getFragmentManager().getBackStackEntryCount();
if(framentCount != 0)
{
FragmentManager.BackStackEntry backEntry=getFragmentManager().getBackStackEntryAt(framentCount-1);
String str=backEntry.getName(); //the tag of the fragment
if(str.equals("fragA"))
//set the actionbar title to FragA
else if(str.equals("fragB"))
//set the actionbar title to FragB
}
FragA myFragA = (FragA)getFragmentManager().findFragmentByTag("MY_FRAGMENTA_A_TAG");
if (myFragA.isVisible()) {
//action bar.title="title first fragment"
}
}
Now to know which fragment is which you need to put a tag to your fragment when you add / replace it to the backstack. Also make sure that you call addToBackStack to put the fragments to the backstack.
FragmentTransaction.add(int containerViewId, Fragment fragment, String tag)
FragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)
Call the below line of code in all your fragments onResume() callback. you wouldnt need to save the title.
((YourFragmentActivity) getActivity()).setActionBarTitle(YOUR_TITLE);
it should help.
Put a public static string called tag on your fragments, then use this where the tag is. More maintainability.
Why - This means if you want to change the tag, you only have to change it in one place, less refactoring. (Its used also on add, replace functions - see Rod's answer if confused)
My implementation of the solution is similar to how Rod solved the issue in his edited answer except a lot less code.
#Override
public void onBackPressed() {
super.onBackPressed();
try {
if (getFragmentManager().findFragmentByTag(FragA.tag) != null) {
if (getFragmentManager().findFragmentByTag(FragA.tag).isVisible()) {
getActionBar().setTitle(R.string.FragA_title);
}
}
if (getFragmentManager().findFragmentByTag(FragB.tag) != null) {
if (getFragmentManager().findFragmentByTag(FragB.tag).isVisible()) {
getActionBar().setTitle(R.string.FragB_title);
}
}
}
catch (NullPointerException e) {
}
}
eg of static tag use
FragmentTransaction.add(int containerViewId, Fragment fragment, FragA.tag)
#Override
public void onStop() {
super.onStop();
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Title");
}
Override the onStop() method in your current fragment, and gives the title name of your previous fragment.