Comment implémenter OnFragmentInteractionListener

J'ai une application générée par l'assistant avec tiroir de navigation dans android studio 0.8.2

, j'ai créé un fragment et de l'ajouter avec newInstance() et j'obtiens cette erreur:

Com.domaine.myapp E/ AndroidRuntime FATAL exception fatale: principale Java.lang.ClassCastException: com.domaine.myapp.MainActivity @ 422fb8f0 doit implémenter OnFragmentInteractionListener

Je ne trouve nulle part comment implémenter ce OnFragmentInteractionListener ?? Il ne peut pas être trouvé même dans documentation sdk android!

MainActivity.java

import android.app.Activity;

import android.app.ActionBar;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.widget.DrawerLayout;


public class MainActivity extends Activity
    implements NavigationDrawerFragment.NavigationDrawerCallbacks {

/**
 * Fragment managing the behaviors, interactions and presentation of the navigation drawer.
 */
private NavigationDrawerFragment mNavigationDrawerFragment;

/**
 * Used to store the last screen title. For use in {@link #restoreActionBar()}.
 */
private CharSequence mTitle;

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

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));
}

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();

    switch (position) {
        case 0: fragmentManager.beginTransaction()
                .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
                .commit(); break; 
        case 1: fragmentManager.beginTransaction() 
                .replace(R.id.container, AboutFragment.newInstance("test1", "test2"))
                .commit(); break; // this crashes the app
        case 2: fragmentManager.beginTransaction()
                .replace(R.id.container, BrowseQuotesFragment.newInstance("test1", "test2"))
                .commit(); break; // this crashes the app
    }
}


public void onSectionAttached(int number) {
    switch (number) {
        case 1:
            mTitle = getString(R.string.title_section1);
            break;
        case 2:
            mTitle = getString(R.string.title_section2);
            break;
        case 3:
            mTitle = getString(R.string.title_section3);
            break;
    }
}

public void restoreActionBar() {
    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setDisplayShowTitleEnabled(true);
    actionBar.setTitle(mTitle);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (!mNavigationDrawerFragment.isDrawerOpen()) {
        // Only show items in the action bar relevant to this screen
        // if the drawer is not showing. Otherwise, let the drawer
        // decide what to show in the action bar.
        getMenuInflater().inflate(R.menu.main, menu);
        restoreActionBar();
        return true;
    }
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((MainActivity) activity).onSectionAttached(
                getArguments().getInt(ARG_SECTION_NUMBER));
    }
}

}

113
demandé sur cricket_007 2014-07-16 14:05:55

11 réponses

Les réponses postées ici n'ont pas aidé, mais le lien suivant l'a fait:

Http://developer.android.com/training/basics/fragments/communicating.html

Définir une Interface

public class HeadlinesFragment extends ListFragment {
    OnHeadlineSelectedListener mCallback;

    // Container Activity must implement this interface
    public interface OnHeadlineSelectedListener {
        public void onArticleSelected(int position);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }

    ...
}

Par exemple, la méthode suivante dans le fragment est appelé lorsque l'utilisateur clique sur un élément de liste. Le fragment utilise l'interface de rappel pour délivrer l'événement à l'activité parent.

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    // Send the event to the host activity
    mCallback.onArticleSelected(position);
}

Implémenter l'Interface

Par exemple, l'activité suivante implémente l'interface de l'exemple ci-dessus.

public static class MainActivity extends Activity
        implements HeadlinesFragment.OnHeadlineSelectedListener{
    ...

    public void onArticleSelected(int position) {
        // The user selected the headline of an article from the HeadlinesFragment
        // Do something here to display that article
    }
}

Mise à jour pour L'API 23: 8/31/2015

Surdéfini méthode onAttach(Activity activity) est maintenant obsolète dans android.app.Fragment, le code doit être mis à niveau vers onAttach(Context context)

@Override
public void onAttach(Context context) {
    super.onAttach(context);
}


@Override
public void onStart() {
    super.onStart();
    try {
        mListener = (OnFragmentInteractionListener) getActivity();
    } catch (ClassCastException e) {
        throw new ClassCastException(getActivity().toString()
                + " must implement OnFragmentInteractionListener");
    }
}
99
répondu meda 2015-09-01 14:19:54

Pour ceux d'entre vous qui ne comprennent toujours pas après avoir lu la réponse de @ meda, voici mon explication concise et complète de ce problème:

Disons que vous avez 2 Fragments, Fragment_A et Fragment_B, qui sont générés automatiquement à partir de l'application. Sur la partie inférieure de vos fragments générés, vous allez trouver ce code:

public class Fragment_A extends Fragment {

    //rest of the code is omitted

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }
}

public class Fragment_B extends Fragment {

    //rest of the code is omitted

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }
}

Pour résoudre le problème, vous devez ajouter onFragmentInteraction méthode dans votre activité, ce qui dans mon cas est nommé MainActivity2. Après cela, vous devez implémenter tous les fragments dans le MainActivity comme ceci:

public class MainActivity2 extends ActionBarActivity
        implements Fragment_A.OnFragmentInteractionListener, 
                   Fragment_B.OnFragmentInteractionListener, 
                   NavigationDrawerFragment.NavigationDrawerCallbacks {
    //rest code is omitted

    @Override
    public void onFragmentInteraction(Uri uri){
        //you can leave it empty
    }
}

P.S.: en bref, cette méthode pourrait être utilisée pour communiquer entre fragments. Pour ceux d'entre vous qui veulent en savoir plus sur cette méthode, veuillez vous référer à ce lien .

167
répondu Bla... 2018-09-25 01:56:44

Voir votre Fragment généré automatiquement créé par Android Studio. Lorsque vous avez créé le nouveau Fragment, Studio a bourré un tas de code pour vous. Au bas du modèle généré automatiquement, il y a une définition d'interface interne appelée OnFragmentInteractionListener. Votre Activity doit implémenter cette interface. C'est le modèle recommandé pour votre Fragment pour notifier votre Activity des événements afin qu'il puisse ensuite prendre les mesures appropriées, telles que charger un autre Fragment. Voir cette page pour plus de détails, recherchez le " Création de rappels d'événements pour la section "Activité": http://developer.android.com/guide/components/fragments.html

40
répondu Larry Schiefer 2014-07-16 10:51:51

Pour ceux d'entre vous qui visitent cette page à la recherche de précisions sur cette erreur, dans mon cas, l'activité faisant l'appel au fragment devait avoir 2 implémentations dans ce cas, comme ceci:

public class MyActivity extends Activity implements 
    MyFragment.OnFragmentInteractionListener, 
    NavigationDrawerFragment.NaviationDrawerCallbacks {
    ...// rest of the code
}
25
répondu Bwvolleyball 2017-08-09 00:22:37

Vous devriez essayer de supprimer le code suivant de vos fragments

    try {
        mListener = (OnFragmentInteractionListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }

L'interface / écouteur est créé par défaut pour que votre activité et vos fragments puissent communiquer plus facilement

5
répondu Joe Plante 2015-10-12 09:31:36

En plus de la réponse de @user26409021, si vous avez ajouté un ItemFragment, le message dans ItemFragment est;

Activities containing this fragment MUST implement the {@link OnListFragmentInteractionListener} interface.

Et vous devriez ajouter dans votre activité;

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener, ItemFragment.OnListFragmentInteractionListener {

//the code is omitted

 public void onListFragmentInteraction(DummyContent.DummyItem uri){
    //you can leave it empty
}

Ici, l'élément factice est ce que vous avez sur le bas de votre ItemFragment

4
répondu oneNiceFriend 2016-02-27 08:10:30

Au lieu de L'utilisation de L'activité context.It ça marche pour moi.

@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mListener = (OnFragmentInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
}
3
répondu KCN 2016-03-25 08:46:01

Juste un additif:

OnFragmentInteractionListener gère la communication entre Activity et Fragment à l'aide d'une interface (OnFragmentInteractionListener) et est créée par défaut par Android Studio, mais si vous n'avez pas besoin de communiquer avec votre activité, vous pouvez simplement en profiter.

Le but est que vous puissiez attacher votre fragment à plusieurs activités tout en réutilisant la même approche de communication (chaque activité pourrait avoir sa propre OnFragmentInteractionListener pour chaque fragment).

Mais et si je suis sûr que mon fragment sera attaché à un seul type d'activité et que je veux communiquer avec cette activité?

Ensuite, si vous ne voulez pas utiliser OnFragmentInteractionListener en raison de sa verbosité, vous pouvez accéder à vos méthodes d'activité en utilisant:

((MyActivityClass) getActivity()).someMethod()
3
répondu sagits 2016-04-02 17:16:25

Allez simplement à votre activité de fragment et supprimez toute la méthode.....au lieu de cela sur la méthode createview.

Votre fragment a seulement sur la méthode oncreateview c'est tout.

/ / seule cette méthode implémente une autre méthode delete

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    return rootView;
}

Et assurez-vous que votre mise en page est démo pour u.

3
répondu Kalpesh A. Nikam 2018-07-12 19:10:18

OnFragmentInteractionListener est l'implémentation par défaut pour gérer la communication fragment à activité. Cela peut être mis en œuvre en fonction de vos besoins. Supposons que si vous avez besoin d'une fonction dans votre activité à exécuter pendant un moment particulier dans votre fragment, vous pouvez utiliser cette méthode de rappel. Si vous n'avez pas besoin d'avoir cette interaction entre votre hébergement activity et fragment, Vous pouvez supprimer cette implémentation.

En bref, vous devriez implement l'écouteur dans votre activité d'hébergement de fragments si vous avez besoin de l'interaction fragment-activité comme ceci

public class MainActivity extends Activity implements 
YourFragment.OnFragmentInteractionListener {..}

Et votre fragment devrait l'avoir défini comme ceci

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

Aussi fournir la définition de void onFragmentInteraction(Uri uri); dans votre activité

Ou bien supprimez simplement l'initialisation listener de votre fragment onAttach Si vous n'avez aucune interaction fragment-activité

3
répondu Navneet Krishna 2018-07-25 10:23:56

Je voudrais ajouter la destruction de l'auditeur lorsque le fragment est détaché de l'activité ou détruits.

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

Et lors de l'utilisation de la nouvelle méthode onStart () avec Context

@Override
public void onDestroy() {
    super.onDestroy();
    mListener = null;
}
1
répondu rexxar 2015-12-07 10:47:19