Android 如何实现 OnFragmentInteractionListener

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24777985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:44:51  来源:igfitidea点击:

How to implement OnFragmentInteractionListener

androidandroid-fragments

提问by Mario M

I have a wizard generated app with navigation drawer in android studio 0.8.2

我在 android studio 0.8.2 中有一个带有导航抽屉的向导生成的应用程序

I have created a fragment and added it with newInstance() and I get this error:

我创建了一个片段并使用 newInstance() 添加它,但出现此错误:

com.domain.myapp E/AndroidRuntime﹕ FATAL EXCEPTION: main java.lang.ClassCastException: com.domain.myapp.MainActivity@422fb8f0 must implement OnFragmentInteractionListener

com.domain.myapp E/AndroidRuntime:致命异常:主要 java.lang.ClassCastException:com.domain.myapp.MainActivity@422fb8f0 必须实现 OnFragmentInteractionListener

I can't find anywhere how to implement this OnFragmentInteractionListener ?? It cannot be found even in android sdk documentation!

我在任何地方都找不到如何实现这个 OnFragmentInteractionListener ?? 即使在android sdk文档中也找不到它!

MainActivity.java

主活动.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));
    }
}

}

}

采纳答案by meda

Answers posted here did not help, but the following link did:

此处发布的答案没有帮助,但以下链接有帮助:

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

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

Define an 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");
        }
    }

    ...
}

For example, the following method in the fragment is called when the user clicks on a list item. The fragment uses the callback interface to deliver the event to the parent activity.

例如,片段中的以下方法在用户单击列表项时调用。该片段使用回调接口将事件传递给父活动。

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

Implement the Interface

实现接口

For example, the following activity implements the interface from the above example.

例如,以下活动实现了上述示例中的接口。

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
    }
}


Update for API 23: 8/31/2015

API 23 更新:8/31/2015

Overrided method onAttach(Activity activity)is now deprecated in android.app.Fragment, code should be upgraded to onAttach(Context context)

重写的方法onAttach(Activity activity)现在已弃用android.app.Fragment,代码应升级为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");
    }
}

回答by Bla...

For those of you who still don't understand after reading @meda answer, here is my concise and complete explanation for this issue:

对于那些在阅读@meda 回答后仍然不明白的人,这里是我对这个问题的简洁完整的解释:

Let's say you have 2 Fragments, Fragment_Aand Fragment_Bwhich are auto-generated from the app. On the bottom part of your generated fragments, you're going to find this code:

比方说,你有2个片段,Fragment_A以及Fragment_B它们是自动生成的,从应用程序。在生成的片段的底部,您将找到以下代码:

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);
    }
}

To overcome the issue, you have to add onFragmentInteractionmethod into your activity, which in my case is named MainActivity2. After that, you need to implementsall fragments in the MainActivitylike this:

为了解决这个问题,你必须在onFragmentInteraction你的活动中添加方法,在我的例子中它被命名为MainActivity2. 之后,你需要像这样的implements所有片段MainActivity

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.: In short, this method could be used for communicating between fragments. For those of you who want to know more about this method, please refer to this link.

PS:简而言之,这种方法可以用于片段之间的通信。如果您想了解更多有关此方法的信息,请参阅此链接

回答by Larry Schiefer

See your auto-generated Fragmentcreated by Android Studio. When you created the new Fragment, Studio stubbed a bunch of code for you. At the bottom of the auto-generated template there is an inner interface definition called OnFragmentInteractionListener. Your Activityneeds to implement this interface. This is the recommended pattern for your Fragmentto notify your Activityof events so it can then take appropriate action, such as load another Fragment. See this page for details, look for the "Creating event callbacks for the Activity" section: http://developer.android.com/guide/components/fragments.html

查看Fragment由 Android Studio 创建的自动生成。当您创建新的 时Fragment,Studio 会为您存根一堆代码。在自动生成的模板底部有一个内部接口定义,称为OnFragmentInteractionListener. 你Activity需要实现这个接口。这是您Fragment通知Activity事件的推荐模式,以便它可以采取适当的操作,例如加载另一个Fragment. 有关详细信息,请参阅此页面,查找“为活动创建事件回调”部分:http: //developer.android.com/guide/components/fragments.html

回答by Bwvolleyball

For those of you who visit this page looking for further clarification on this error, in my case the activity making the call to the fragment needed to have 2 implements in this case, like this:

对于那些访问此页面以寻求有关此错误的进一步说明的人,在我的情况下,在这种情况下调用片段的活动需要有 2 个实现,如下所示:

public class MyActivity extends Activity implements 
    MyFragment.OnFragmentInteractionListener, 
    NavigationDrawerFragment.NaviationDrawerCallbacks {
    ...// rest of the code
}

回答by Joe Plante

You should try removing the following code from your fragments

您应该尝试从片段中删除以下代码

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

The interface/listener is a default created so that your activity and fragments can communicate easier

接口/侦听器是默认创建的,以便您的活动和片段可以更轻松地进行通信

回答by oneNiceFriend

In addition to @user26409021 's answer, If you have added a ItemFragment, The message in the ItemFragment is;

除了@user26409021 的回答,如果您添加了 ItemFragment,则 ItemFragment 中的消息是;

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

And You should add in your activity;

你应该加入你的活动;

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
}

Here the dummy item is what you have on the bottom of your ItemFragment

这里的虚拟项目是你在 ItemFragment 底部的东西

回答by Navneet Krishna

OnFragmentInteractionListeneris the default implementation for handling fragment to activity communication. This can be implemented based on your needs. Suppose if you need a function in your activity to be executed during a particular action within your fragment, you may make use of this callback method. If you don't need to have this interaction between your hosting activityand fragment, you may remove this implementation.

OnFragmentInteractionListener是处理片段到活动通信的默认实现。这可以根据您的需要实施。假设如果您需要在片段内的特定操作期间执行活动中的函数,则可以使用此回调方法。如果您不需要在您的主机activity和之间进行这种交互fragment,您可以删除此实现。

In short you should implementthe listener in your fragment hosting activity if you need the fragment-activity interaction like this

简而言之,implement如果您需要这样的片段活动交互,您应该在片段托管活动中监听监听器

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

and your fragment should have it defined like this

你的片段应该像这样定义它

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

also provide definition for void onFragmentInteraction(Uri uri);in your activity

还为void onFragmentInteraction(Uri uri);您的活动提供定义

or else just remove the listenerinitialisation from your fragment's onAttachif you dont have any fragment-activity interaction

否则,如果您没有任何片段活动交互,则只需listener从片段中删除初始化onAttach

回答by Vinicius Petrachin

With me it worked delete this code:

对我来说,它可以删除此代码:

@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");
        }
    }

Ending like this:

结局是这样的:

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

回答by KCN

Instead of Activity use context.It works for me.

而不是 Activity 使用上下文。它对我有用。

@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mListener = (OnFragmentInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
}

回答by sagits

Just an addendum:

只是一个附录:

OnFragmentInteractionListener handle communication between Activity and Fragment using an interface(OnFragmentInteractionListener) and is created by default by Android Studio, but if you dont need to communicate with your activity, you can just get ride of it.

OnFragmentInteractionListener 使用接口(OnFragmentInteractionListener)处理 Activity 和 Fragment 之间的通信,默认情况下由 Android Studio 创建,但如果您不需要与您的 Activity 通信,则可以使用它。

The goal is that you can attach your fragment to multiple activities and still reuse the same communication approach(Every activity could have its own OnFragmentInteractionListener for each fragment).

目标是您可以将片段附加到多个活动,并且仍然重用相同的通信方法(每个活动可以为每个片段拥有自己的 OnFragmentInteractionListener)。

But and if im sure my fragment will be attached to only one type of activity and i want to communicate with that activity?

但是,如果我确定我的片段将只附加到一种类型的活动并且我想与该活动进行交流?

Then, if you dont want to use OnFragmentInteractionListener because of its verbosity, you can access your activity methods using:

然后,如果您不想使用 OnFragmentInteractionListener 因为它的冗长,您可以使用以下方法访问您的活动方法:

((MyActivityClass) getActivity()).someMethod()