【问题标题】:Doesn't work changing fragment using navigation drawer使用导航抽屉更改片段不起作用
【发布时间】:2015-01-28 20:38:05
【问题描述】:

我想用出色的代码编写非常酷的程序,所以我决定了解 Android studio 创建的代码(认为它一定很棒,因为是专业人士编写的)。

  1. 如何使用抽屉式导航更改片段?我向onNavigationDrawerItemSelected 添加了一些代码,但它不起作用(应用程序崩溃)
  2. 什么是PlaceholderFragment?无法理解它的作用和工作原理。

这是 MainActivity.java 的代码。请帮帮我。谢谢。

public class MainActivity extends ActionBarActivity
        implements NavigationDrawerFragment.NavigationDrawerCallbacks {

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

    /**
     * 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)
                getSupportFragmentManager().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) {
        Fragment fragment;
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragment = new AlarmClockFragment();
        fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
        /*FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
                .commit();*/
    }

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

    public void restoreActionBar() {
        ActionBar actionBar = getSupportActionBar();
        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();

        //noinspection SimplifiableIfStatement
        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 {

        private static final String ARG_SECTION_NUMBER = "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));
        }
    }

}

AlarmClockFragment:

public class AlarmClockFragment extends Fragment implements AbsListView.OnItemClickListener  {

// 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";

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

private OnFragmentInteractionListener mListener;

/**
 * The fragment's ListView/GridView.
 */
private AbsListView mListView;

/**
 * The Adapter which will be used to populate the ListView/GridView with
 * Views.
 */
private ListAdapter mAdapter;

// TODO: Rename and change types of parameters
public static AlarmClockFragment newInstance(String param1, String param2) {
    AlarmClockFragment fragment = new AlarmClockFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

/**
 * Mandatory empty constructor for the fragment manager to instantiate the
 * fragment (e.g. upon screen orientation changes).
 */
public AlarmClockFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }

    // TODO: Change Adapter to display your content
    mAdapter = new ArrayAdapter<DummyContent.DummyItem>(getActivity(),
            android.R.layout.simple_list_item_1, android.R.id.text1, DummyContent.ITEMS);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_alarmclock, container, false);

    // Set the adapter
    mListView = (AbsListView) view.findViewById(android.R.id.list);
    ((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter);

    // Set OnItemClickListener so we can be notified on item clicks
    mListView.setOnItemClickListener(this);

    return view;
}

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

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


@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    if (null != mListener) {
        // Notify the active callbacks interface (the activity, if the
        // fragment is attached to one) that an item has been selected.
        mListener.onFragmentInteraction(DummyContent.ITEMS.get(position).id);
    }
}

/**
 * The default content for this Fragment has a TextView that is shown when
 * the list is empty. If you would like to change the text, call this method
 * to supply the text it should use.
 */
public void setEmptyText(CharSequence emptyText) {
    View emptyView = mListView.getEmptyView();

    if (emptyView instanceof TextView) {
        ((TextView) emptyView).setText(emptyText);
    }
}

/**
 * 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
    public void onFragmentInteraction(String id);
}

}

【问题讨论】:

  • 您的第一步可能是使用系统日志找出应用程序崩溃的确切原因 - 一旦您在此处查看了该错误的发布详细信息。您可以了解如何查看此日志here
  • 我发现这个:Caused by: java.lang.ClassCastException: test.MainActivity@41e49320 must implement OnFragmentInteractionListener
  • 由Android Studio模板生成的更好的使用方式还是我应该自己编写?我觉得看懂专业的代码就好了,但是看不清楚:(
  • 错误告诉你AlarmClockFragment 类应该实现OnFragmentationInteractionListener 接口,以便它可以用作片段。您目前只实现OnItemClickListener,因此将implements OnFragmentationInteractionListener 添加到类定义中。然后,IDE 和/或文档应该可以帮助您了解接口提供的方法和属性。
  • 非常感谢!我明白了!

标签: android fragment navigation-drawer


【解决方案1】:
  1. AlarmClockFragment() 的代码是什么?
  2. PlaceholderFragment 只是 Fragment 外观的一个简单示例。

【讨论】:

  • AlarmClockFragment 是 Android Studio Fragment 基于 ListView 创建的。添加代码。
  • 正如 Octopoid 所说,您的 AlarmClockFragment 中有接口 OnFragmentInteractionListener,因此您的 MainActivity 应该实现它。
【解决方案2】:

您的代码看起来很合理,您在 onNavigationDrawerItemSelected 中做对了。 PlaceholderFragment 只是一个示例片段 - 将其替换为您要使用的实际片段是正确的。如果没有堆栈跟踪,很难说您的应用程序为什么会崩溃,这可能是您的 AlarmClockFragment 有问题。

【讨论】:

  • 我加了一段AlarmClockFragment的代码。它只是一个基于 Android Studio 创建的 ListVIew 的片段。堆栈跟踪?像 PlaceholderFragment 那样将所有片段放入 MainActivity.java 是否是一种好方法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多