如何实现OnFragmentInteractionListener
我有一个向导生成的应用程序与导航抽屉在Android Studio 0.8.2
我创建了一个片段,并添加newInstance(),我得到这个错误:
com.domain.myapp E / AndroidRuntime:致命例外:主 java.lang.ClassCastException: com.domain.myapp.MainActivity@422fb8f0 必须实现OnFragmentInteractionListener
我无法找到任何地方如何实现这个OnFragmentInteractionListener? 即使在android sdk文档中也找不到它!
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)); } }
}
这里发布的答案没有帮助,但下面的链接做了:
http://developer.android.com/training/basics/fragments/communicating.html
定义一个接口
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"); } } ... }
例如,在用户点击一个列表项时调用片段中的以下方法。 该片段使用回调接口将事件传递给父活动。
@Override public void onListItemClick(ListView l, View v, int position, long id) { // Send the event to the host activity mCallback.onArticleSelected(position); }
实现接口
例如,以下活动将实现上述示例中的界面。
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 } }
更新API 23:8/31/2015
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"); } }
对于那些读完@meda回答后仍然不明白的人,下面是我对这个问题的简明扼要的解释:
假设您有2个Fragment, 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); } }
为了克服这个问题,你必须在你的活动中添加onFragmentInteraction
方法,在我的情况下,这个方法被命名为MainActivity2
。 之后,您需要像这样在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 } }
PS:总之,这个方法可以用来在片段之间进行通信。 对于那些想了解这种方法的人,请参考这个链接 。
查看由Android Studio创建的自动生成的Fragment
。 当你创建新的Fragment
,Studio会为你留下一堆代码。 在自动生成的模板的底部有一个名为OnFragmentInteractionListener
的内部接口定义。 你的Activity
需要实现这个接口。 这是你的Fragment
通知你的Activity
事件的建议模式,以便它可以采取适当的行动,比如加载另一个Fragment
。 有关详细信息,请参阅此页面,查找“为活动创建事件回调”部分: http : //developer.android.com/guide/components/fragments.html
对于那些访问这个页面的人来说,这个错误需要进一步澄清,在我的情况下,在这种情况下,调用碎片需要有2个工具,如下所示:
public class MyActivity extends Activity implements MyFragment.OnFragmentInteractionListener, NavigationDrawerFragment.NaviationDrawerCallbacks { ...// rest of the code }
您应该尝试从您的片段中删除以下代码
try { mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); }
接口/侦听器是一个默认的创建,以便您的活动和片段可以更容易沟通
除了@ user26409021的回答,如果你已经添加了一个ItemFragment,ItemFragment中的消息是;
Activities containing this fragment MUST implement the {@link OnListFragmentInteractionListener} interface.
而你应该加入你的活动;
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 }
这里的虚拟物品是你的ItemFragment的底部
而不是活动使用上下文。它适用于我。
@Override public void onAttach(Context context) { super.onAttach(context); try { mListener = (OnFragmentInteractionListener) context; } catch (ClassCastException e) { throw new ClassCastException(context.toString() + " must implement OnFragmentInteractionListener"); } }
只是一个附录:
OnFragmentInteractionListener使用接口 (OnFragmentInteractionListener) 处理Activity和Fragment之间的通信,并且是由Android Studio默认创建的,但是如果您不需要与您的活动进行通信,则可以使用它。
目标是你可以将你的片段附加到多个活动,并仍然重复使用相同的通信方法 (每个活动可以有自己的OnFragmentInteractionListener为每个片段)。
但是,如果我确定我的片段将只附加到一种类型的活动,我想与该活动沟通?
然后,如果由于冗长而不想使用OnFragmentInteractionListener,则可以使用以下命令访问您的活动方法:
((MyActivityClass) getActivity()).someMethod()
我想添加碎片从活动分离或销毁时的监听器的销毁。
@Override public void onDetach() { super.onDetach(); mListener = null; }
并在Context中使用新的onStart()方法时
@Override public void onDestroy() { super.onDestroy(); mListener = null; }