1

I am trying to use onBackPressed() in my Fragment so that I can allow the user to roll back in a pile of fragments he navigated in my app.

The problem is that, when I add the method below to my Fragment, it gives me the error: Method does not override method from its superclass.

@Override
public void onBackPressed() {

    android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.popBackStack();

}

Would you know why?

Thanks!

Here goes the entire Fragment:

package it.bitrack.fabio.bitrack;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
//import android.app.Fragment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.ArrayAdapter;

import java.util.ArrayList;
import java.util.Arrays;
import android.view.KeyEvent;


/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link AssetMngtView.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link AssetMngtView#newInstance} factory method to
 * create an instance of this fragment.
 */
public class AssetMngtView extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    View view;

    ListView assetMngtListView;
    ArrayAdapter<String> listAdapter;

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    public AssetMngtView() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment AssetMngtView.
     */
    // TODO: Rename and change types and number of parameters
    public static AssetMngtView newInstance(String param1, String param2) {
        AssetMngtView fragment = new AssetMngtView();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onBackPressed() {

        android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.popBackStack();

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        view = inflater.inflate(R.layout.fragment_asset_mngt_view, container, false);

        assetMngtListView = (ListView) view.findViewById(R.id.assetMngtListView);
        setListView();


        return view;
    }

    public void setListView() {

        String[] options = new String[]{"Bind tag & thing", "Create new thing", "Edit existent thing", "Maintain existent thing", "View things notifications"};

        ArrayList<String> optionsList = new ArrayList<String>();
        optionsList.addAll(Arrays.asList(options));

        listAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, optionsList);

        assetMngtListView.setAdapter(listAdapter);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}
Fabio Lanza
  • 167
  • 2
  • 5
  • 14
  • Please provide an [mcve]. In particular, what class contains the method you are overriding? Also, how do you create and show your fragments? – Code-Apprentice Jul 07 '17 at 08:01
  • 1
    Note that pressing the back button pops the back stack automatically. There is no reason to override `onBackPressed()` to do this yourself. – Code-Apprentice Jul 07 '17 at 08:02
  • This method should be a native Android method, that handles the back button available in any Android phone. My code is fully available in my question. – Fabio Lanza Jul 07 '17 at 08:03
  • @Code-Apprentice let me try that, nice tip... – Fabio Lanza Jul 07 '17 at 08:03
  • will you please tell what you want to do in your code so that i can help you further – Ashish Pandey Jul 07 '17 at 08:04
  • @Code-Apprentice, even if it works, do you know why I am not being able to override that superclass? I would like to know conceptually why I can't. Thanks! – Fabio Lanza Jul 07 '17 at 08:05
  • 1
    As the message says, there is no `onBackPressed()` method in `Fragment` nor any of its superclasses. When you get errors like these, you should always consult the documentation. If you cannot find a method in the class where you think it is, then just google the method name. – Code-Apprentice Jul 07 '17 at 08:06
  • Possible duplicate of [How to implement onBackPressed() in Fragments?](https://stackoverflow.com/questions/5448653/how-to-implement-onbackpressed-in-fragments) – Andy Developer Jul 07 '17 at 09:08

6 Answers6

10

If you want to implement onBackPressed behavior in fragment, you should do this in onViewCreated of your fragment:

requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
    @Override
    public void handleOnBackPressed() {
        if (isHandlingBackPressInFragment()) {
            // Handle back press
        } else {
            // If you want to get default implementation of onBackPressed, use this
            this.remove();
            requireActivity().onBackPressed();
        }
    }
});
  • Thanks for your anwser!!! This method is exactly, so simple & ligtweight. Your anw need to be upvote to on top. I have applied this for my app to clear data holded by ViewModel when press on Back button. – Nghien Nghien Feb 13 '22 at 18:40
  • Many thanks, I was missing this.remove(); which solved my issue. – Wessam El Mahdy Dec 18 '22 at 08:18
6

To achieve what you want, you should override the onBackPressed() of the Activity associated like that:

@Override
public void onBackPressed() {
    if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
        getSupportFragmentManager().popBackStack();
    } else {
      finish();
    }
}

Hope this helps. Sorry for my english.

Cochi
  • 2,199
  • 2
  • 12
  • 15
4

the problem is that Fragment does not have public void onBackPressed() method.

you are getting the error because your method is annotated with @Override but it is not actually overriding any method in the superclass. the purpose of @Override is exactly this one, letting you know that you think you're overriding something but, actually, you aren't

on a side note, what you are trying to do is unnecessary. if you press the back button and you have fragments in the back stack they will be popped automatically. try this

public class FragmentsActivity extends AppCompatActivity {

    public static class FragmentA extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = new TextView(getActivity());
            view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            view.setBackgroundColor(0xffff0000);    
            return view;
        }
    }

    public static class FragmentB extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = new TextView(getActivity());
            view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            view.setBackgroundColor(0xff00ff00);    
            return view;
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments);

        FragmentManager fm = getSupportFragmentManager();
        fm.beginTransaction()
                .add(R.id.fragment_container, new FragmentA(), FragmentA.class.getSimpleName())
                .commit();

        // notice addToBackStack here
        fm.beginTransaction()
                .add(R.id.fragment_container, new FragmentB(), FragmentB.class.getSimpleName())
                .addToBackStack(FragmentB.class.getSimpleName())
                .commit();
    }
}
lelloman
  • 13,883
  • 5
  • 63
  • 85
0

Use method onBackPressed() and call popBackStack() in your Activity class, not in fragment

nick_kryloff
  • 126
  • 6
0

If you want to go back to the previous Fragment, you can use this. The content_frame is the id of your FrameLayout. You can't use onBackPressed since the fragment can't stand alone without Activity.

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                        ft.replace(R.id.content_frame, new MainActivity());
                        ft.addToBackStack(null);
                        ft.commit();
IMNK
  • 21
  • 1
-1

I am sorry if I missunderstood or if I am missing something, but you get the error because onBackPressed() is not a method of the super class (Fragment class in your case)

Ionut J. Bejan
  • 734
  • 11
  • 28