Android Studio onBackPressed() needs to change base class variables - android

I have a global navigation bar currently and it works beautifully unless the user hits the back button. I have overridden the back button like so
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(mDrawerList)) {
mDrawerLayout.closeDrawer(mDrawerList);
} else {
navBar.curr_position = navBar.position.pop();
Log.d("Backing To pos", Integer.toString(navBar.curr_position));
mDrawerList.setItemChecked(navBar.curr_position, true);
super.onBackPressed();
}
}
Where navBar.curr_position is the protected static int containing current position of the activity, and navBar.position is a protected static ArrayDeque (or stack) from my understanding.
All activities extend my base navBar class.
Now what I want the app to do, is when back is called to change the navBar's selection to whatever it was before. However it seems that with Android, when back is called it does not rerun any of the activity or base code so it simply never changes the selection.
Is there a function somewhere that can check to see if the program was just returned to from back and then change the navbar?
Thanks!

It turns out that I can put the setItemChecked code in onStart();

Related

Refresh the backstack Activities after Night Mode has changed

I have seen a lot of questions and answers about recreating the current activity after changing the application's Night Mode, but I have seen nothing on how to refresh the back stack Activities.
Say I have the backstack A > B > C. Activity C allows to change the night mode by calling AppCompatDelegate.setDefaultNightMode(). After this call, the current Activity (C), can refresh its theme with delegate.applyDayNight() or recreate().
However, when the user navigates back to B or A, the activities are still using the "old" mode, either day or night.
I tried to add something like that to the Activities:
override fun onResume() {
super.onResume()
delegate.applyDayNight()
}
But it does not seem to work.
I did multiple attempts to fix this:
One idea would be to recreate the backstack completely like suggested here or here, but since the backstack is not static, it's not doable for me.
Another idea would be to have a class that handles the night mode change and provides a LiveData. Each Activity would listen to the LiveData for a mode change and call recreate(). However, we are stuck in an infinite loop because the Activity would recreate directly after starting to listen to the LiveData.
I find it hard to believe that I am the first one trying to refresh the Activities from the backstack after changing the night mode. What did I miss?
Thanks!
If you can detect when the day/night mode has changed, you can simply recreate an activity that is resumed when the back stack is popped.
In the following demo, there are three activities: A, B and C. A creates B and B creates C. Activity C can change the day/night mode. When C is popped, activity B sees the change in the day/night mode and calls reCreate() to recreate the activity. The same happens in activity A when activity B is popped.
The video below shows the effect. The light-colored background is the "day" mode and the dark is "night" mode.
I have created a GitHub project for this demo app. If this works as a solution, I can incorporate more text into the answer from the project.
Refreshing your back stack completely is probably overkill and may add some overhead/lag to the UX; and as you mentioned, most applications will not have access to a full, static back stack.
You are essentially describing a more general issue: global changes to the theme or WindowManager itself affect the subsequent drawing of views. But previous layouts for Activities in the stack may not be redrawn. It might seem odd for you in this situation, but there could also be many good reasons why one would not want to redraw an Activity in the stack if once the user goes back to it. And so this is not an automatic feature.
I can think of a couple of options:
1) Write a custom class inheriting from Activity that invalidates all it's views when it moves to the front of the stack again. E.g. in onResume() or onRestart(), call (if in Fragment)
View view = getActivity().findViewById(R.id.viewid);
view.invalidate();
Use this custom Activity for all your activities that you want to keep consistent with the current day/night mode.
2) Use ActivityLifecycleCallbacks. This helps keep all your logic in one place, and avoids the need for custom inheritance as above. You could invalidate your views here as needed as activities are paused/resumed. You could include a Listener, if it is your app that is changing the theme, and record as SharedPreference, for example.
To use, add the callbacks to your Application class:
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void
onActivityCreated(Activity activity, Bundle savedInstanceState) {
//can check type of Activity for custom behaviour, if using inheritance
if(activity instanceof MainActivity) {
mMainActivities.put(activity, new MainActivityEntry((MainActivity)activity));
//...
}
}
#Override
public void
onActivityDestroyed(Activity activity) {
}
#Override
public void
onActivityPaused(Activity activity) {
}
#Override
public void
onActivityResumed(Activity activity) {
if(activity instanceof MainActivity) {
//...
}
//can update Entry properties too
final MainActivityEntry activityEntry = mMainActivities.get(activity);
if(activityEntry != null) {
//record state /perform action
}
}
#Override
public void
onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void
onActivityStarted(Activity activity) {
}
#Override
public void
onActivityStopped(Activity activity) {
}
});
Quick answer:
#Override
protected void onRestart() {
super.onRestart();
recreate();
}
You add the above codes to your MainActivity and it will work.
create a static boolean variable in the project and in each activity check if the boolean is true or false, then apply daylight and night based on value.

Android navigation drawer exits on back pressed

I am using navigation drawer in my MainActivity.java to switch fragments and I am also extending my MainActivity to the other activities in my app. Now the problem is that, when I press back button during I am on fragment, the app suddenly exits without any notification. And if I use OnBackPressed in my MainActivity it is bydefault implemented to the other activities extending main activity too and when I press back button to any of that acivity it asks me first for confirmation and then comes back to previous activity or frag. Need a solution to avoid this. I want to set onbackpessed or anything that shows dialogue or asks for confirmation to exit app on fragments only but dont know howto do.
Or any help regarding fragment back stacking to open a fixed fragment on back button pressed is welcomed if it tells how to change the title of hence opened fragment too.
call onBackPressed() in that activity in which you have put all fragment or main activity
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
//Display your dialog here
} else {
getFragmentManager().popBackStack();
}
}
Other solution
#Override
public void onBackPressed() {
if (slidingMenu.isMenuShowing()) {
slidingMenu.toggle(true);
} else {
super.onBackPressed();
//Display your dialog
}
}
This is works for me.

Detecting the visible fragment in android

I want to implement the onbackpressed() in android and my code is as follows
public void backpressed(){
NDListeningFragment fragment1=(NDListeningFragment)getSupportFragmentManager().findFragmentByTag(ConnectedDevicesFragment.TAG);
if(fragment1!=null && fragment1.isVisible())
{
super.onBackPressed();
}
else
{
fragment1=(NDListeningFragment)SimpleFragmentFactory.createFragment(ConnectedDevicesFragment.TAG);
getSupportFragmentManager().beginTransaction().replace(R.id.content,fragment1).commit();
fragment1.setUserVisibleHint(true);
}
}
The above code checks if the visible fragment is ConnectedDevicesFragment. If yes then super() is called and if not then I create ConnectedDevicesFragment and replace it in the framelayout.
But I am not able to implement in this way. When I press back button it reloads the Connected DevicesFragment again and again.
can you help with some workaround.
Cheers!
You creates fragment1 object every time in the onBackPressed function it means it will not null and it is on invisible state. You need to add NDListeningFragment in backstack when you open NDListeningFragment first and check Is the fragment available in back stack. If yes then call super.onBackpressed.

ActionBarActivity back button not popping from backstack

I'm using this template https://github.com/kanytu/android-material-drawer-template just to try out material design so I've implemented a few fragments some have webviews some have not.
My problem is when switching between the fragments I can see them being successfully added to the backstack
getFragmentManager().beginTransaction().replace(R.id.container, new FAQ()).addToBackStack("FAQ").commit();
But when I press the back button it just closes the app.
When I change it to use Activity instead of ActionBarActivity the navigation works fine but I lose some other functionality.
There is an override on the back button
#Override
public void onBackPressed() {
if (mNavigationDrawerFragment.isDrawerOpen())
mNavigationDrawerFragment.closeDrawer();
else
super.onBackPressed();
}
but even if that's removed it still happens. I think the problem lies somewhere in the super.onBackPressed
Is there any reason ActionBarActivity would break the back button?
I recently read a post about this, sorry I can't find it anymore... But basically, it explained that the primary function of the back button is to finish the current Activity.
In fact, according to the onBackPressed() official documentation:
Called when the activity has detected the user's press of the back key. The default implementation simply finishes the current activity, but you can override this to do whatever you want.
And it would appear that even though the back button used to pop the backstack before 5.0, Google would have changed this behaviour with the new ActionBarActivity.
For my part, I used some workarround that works for me but that might not work for everybody, depending on your navigation implementation.
But in case it could be helpful to somebody, here it is :
#Override
public void onBackPressed()
{
if (mDrawerLayout.isDrawerOpen()) {
mDrawerLayout.closeDrawer();
} else if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
This way, ActionBarActivity.onBackPressed() is only called when the backstack is empty, in which case it destroys the ActionBarActivity.
You should check "getFragmentManager" & "getSupportFragmentManager" is matched your activity & actionbaractivity or not.
Because, in Activity:
public void onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
finish();
}
}
in FragmentActivity:
public void onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
finish();
}
}
We can see the same code which already handled pop fragments backstatck.
In my situation, I used actionbaractivity(extends FragmentAcvitiy), but I also used "getFragmentManager" , so I got the same error as you. After I have replaced "getFragmentManager" to "getSupportFragmentManager", that's ok! You also can replace "actionbaractiviy" to "Activity" to fix this problem.
Must ensure "getFragmentManager" match "Activity", "getSupportFragmentManager" match "FragmentActivity(ActionbarActivity)".
If you want add actionbar On API level 11 or higher, You can see below:
https://developer.android.com/guide/topics/ui/actionbar.html#Adding
On API level 11 or higher
The action bar is included in all activities that use the Theme.Holo theme (or one of its descendants), which is the default theme when either the targetSdkVersion or minSdkVersion attribute is set to "11" or higher. If you don't want the action bar for an activity, set the activity theme to Theme.Holo.NoActionBar.

Webview back button is killing all activity

i know that may duplicate some threads but i can#t figure out what i wrong. I have slider dreawer where are fragments and in fragments there are webview. Everything is working fine at least one thing, namely when i press back button it closes the app. I have tried some other possible solutions but anything is not working. I even don't get any errors. I even tried this easy solution but without any progress
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
My Main activity:
And this is one of my fragments:
By default back button shall close the app, if you are at the main/landing activity(there are other ways as well). If you want to override backbutton behavior, you should be overriding onBackPressed(), which you are doing right, but you should avoid calling super.onBackPressed() (since this gives you the default behavious, i.e. closing the activity OR finish(), with this you're closing the activity yourself. which is what you want to avoid.
Hope it helps.
#Override
public void onBackPressed() {
if (mSlidingDrawer.isOpened()) {
mSlidingDrawer.close()
} else {
Toast.makeText(MyTestApplication.getAppContext(), "Closing application", Toast.LENGTH_SHORT).show();
super.onBackPressed();
}
}

Categories

Resources