0

In my application i have some fragment and i can exit from application by click on back on phone without problem, but when i implementing onBackPress on that i can't exit from application

My code:

@Override
public void onResume() {
    super.onResume();
    if (getView() == null) {
        return;
    }
    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
                if (slider_call_phones.isOpened()) {
                    slider_call_phones.closeLayer(true);
                }
                return true;
            }
            return false;
        }
    });
}

I want to handle onBackPressed on fragment not Activities

tux-world
  • 2,680
  • 6
  • 24
  • 55
  • This code is not implementing `onBackPressed()`. If you get rid of this code and instead implement `onBackPressed()`, you may have better luck. – CommonsWare Nov 13 '16 at 14:32
  • Possible duplicate of [How to implement onBackPressed() in Fragments?](http://stackoverflow.com/questions/5448653/how-to-implement-onbackpressed-in-fragments) – Viktor Yakunin Nov 13 '16 at 14:34
  • @CommonsWare you mean is `onBackPressed` work fine on Fragments ? – tux-world Nov 13 '16 at 14:34
  • 1
    There is no `onBackPressed()` on `Fragment`. IMHO, the decision of what to do when BACK is pressed is the responsibility of the activity, not any particular fragment. And, there is an `onBackPressed()` method on `Activity`. – CommonsWare Nov 13 '16 at 14:35
  • @ViktorYakunin I want to handle `onBackPressed` on fragment not Activities – tux-world Nov 13 '16 at 14:36
  • @CommonsWare yes i know that, on fragment i have some slider and with your solution i have to define more and more listener to handle them – tux-world Nov 13 '16 at 14:37
  • The BACK button is for large-scale navigation (e.g., exiting an activity, reversing a `FragmentTransaction`) or system UI (e.g., exiting a dialog, collapsing the soft keyboard). I do not know what your "slider" is, but I suspect that I would not recommend that it take control over the BACK button. – CommonsWare Nov 13 '16 at 14:39
  • @CommonsWare yes you're right, ok, then i handle that inside parent Activity, Thanks sir – tux-world Nov 13 '16 at 14:41

2 Answers2

1

Here's how I do it,

  • create an interface that would receive onBackPressed() in any class that implements it and would return true if it's handling the method or false otherwise. This would make sure that your app would exit when your return false.
  • create a stack of these interfaces in your Activity, then add any of such interfaces to it.
  • override onBackPressed() in your activity, then anytime it's called, get a listener from the stack and call its own onBackPressed() if it returns true. If it returns false, then it's not handling onBackPressed() so Activity can take over and remove fragment or exit the application.

Here's a sample implementation.

In your Activity

public class MyActivity extends Activity {

//a stack of OnBackPressedListeners, stack one when you want it to receive onBackPressed() from
//this activity.
//PS used stack so that by LIFO, the last listener would be the first to be called.
private Stack<OnBackPressedListener> onBackPressedListeners = new Stack<>();

@Override
public void onBackPressed() {
    if (!onBackPressedListeners.isEmpty()) {
        if (onBackPressedListeners.peek().onBackPressed()) //if interface is handling onBackPressed(), return. Otherwise super would be called below.
            return;
    }

    //if no listeners, then do super. This would ensure natural behaviour such as closing the app or popping a fragment when no listeners are using onBackPressed()
    super.onBackPressed();
}

//listener interface
public static interface OnBackPressedListener {

    /**
     * @return true if you're handling onBackPressed, false otherwise to let super.onBackPressed() take over
     */
    public boolean onBackPressed();
}

public void addOnBackPressedListener(OnBackPressedListener listener) {
    onBackPressedListeners.add(listener);
}

public void removeOnBackPressedListener(OnBackPressedListener listener) {
    onBackPressedListeners.remove(listener);
}

}

In your Fragment

//implement OnBackPressedListener in your fragment.
public class MyFragment extends Fragment implements OnBackPressedListener {


    //find somewhere to add the listener to your Activity, most likely in onCreateView(...)
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        ...

        ((MyActivity)getActivity()).addOnBackPressedListener(this);

        ...

        return view;
    }

    //overide onBackPressed(), then return true if you're handling the onBackPressed(), false otherwise.
    @Override
    public boolean onBackPressed() {
        if (slider_call_phones.isOpened()) {
            slider_call_phones.closeLayer(true);
            return true;
        }
        return false;
    }

    //lastly remember to remove the listener when your fragment is destroyed, so that it stops receiving callbacks,
    //if you don't do this, you might get a NullPointerException.
    @Override
    public void onDestroy() {
        super.onDestroy();
        ((MyActivity)getActivity()).removeOnBackPressedListener(this);
    }
}

I mostly use a single Activity and a whole lot of Fragment's in my Android apps, this is exactly how I solve such problems you are having, for example closing a drawer in a Fragment if its open when the back button is pressed, or exiting the application if it's closed.

Joey Dalu
  • 1,113
  • 9
  • 13
-1

You should call onBackPressed() in the following manner in order to exit from the app:

public void onBackPressed(){
   finishAffinity();
}
Kiran Nemani
  • 67
  • 1
  • 6