0

我使用了从 Eclipse“Master/Detail”布局创建的基本布局。我已经对其进行了修改并添加了外部页面。但是,当我现在尝试仅加载 ContactListActivity.java 时,它无法加载给我下面的 logcat 错误。关于我做错了什么的任何想法?

ContactListActivity.java

package com.cyphrd.chirpd;

import com.cyphrd.chirpd.R;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuItem;

/**
 * An activity representing a list of Contacts. This activity
 * has different presentations for handset and tablet-size devices. On
 * handsets, the activity presents a list of items, which when touched,
 * lead to a {@link ContactChatActivity} representing
 * item details. On tablets, the activity presents the list of items and
 * item details side-by-side using two vertical panes.
 * <p>
 * The activity makes heavy use of fragments. The list of items is a
 * {@link ContactListFragment} and the item details
 * (if present) is a {@link ContactChatFragment}.
 * <p>
 * This activity also implements the required
 * {@link ContactListFragment.Callbacks} interface
 * to listen for item selections.
 */
public class ContactListActivity extends FragmentActivity
        implements ContactListFragment.Callbacks {

    /**
     * Whether or not the activity is in two-pane mode, i.e. running on a tablet
     * device.
     */
    private boolean mTwoPane;

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

        if (findViewById(R.id.contact_detail_container) != null) {
            // The detail container view will be present only in the
            // large-screen layouts (res/values-large and
            // res/values-sw600dp). If this view is present, then the
            // activity should be in two-pane mode.
            mTwoPane = true;

            // In two-pane mode, list items should be given the
            // 'activated' state when touched.
            ((ContactListFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.contact_list))
                    .setActivateOnItemClick(true);
        }

        // TODO: If exposing deep links into your app, handle intents here.
    }

    /**
     * Callback method from {@link ContactListFragment.Callbacks}
     * indicating that the item with the given ID was selected.
     */
    @Override
    public void onItemSelected(String id) {
        if (mTwoPane) {
            // In two-pane mode, show the detail view in this activity by
            // adding or replacing the detail fragment using a
            // fragment transaction.
            Bundle arguments = new Bundle();
            arguments.putString(ContactChatFragment.ARG_ITEM_ID, id);
            ContactChatFragment fragment = new ContactChatFragment();
            fragment.setArguments(arguments);
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.contact_detail_container, fragment)
                    .commit();

        } else {
            // In single-pane mode, simply start the detail activity
            // for the selected item ID.
            Intent detailIntent = new Intent(this, ContactChatActivity.class);
            detailIntent.putExtra(ContactChatFragment.ARG_ITEM_ID, id);
            startActivity(detailIntent);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add("Search")
            .setIcon(R.drawable.ic_search)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        menu.add("Add Contact")
            .setIcon(R.drawable.ic_add_person)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        menu.add("Settings").setIcon(R.drawable.ic_settings);
        //Whatever else is under the "More" menu
        return true;
    }
}

ContactListFragment.java

package com.cyphrd.chirpd;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.cyphrd.chirpd.dummy.DummyContent;

/**
 * A list fragment representing a list of Contacts. This fragment
 * also supports tablet devices by allowing list items to be given an
 * 'activated' state upon selection. This helps indicate which item is
 * currently being viewed in a {@link ContactChatFragment}.
 * <p>
 * Activities containing this fragment MUST implement the {@link Callbacks}
 * interface.
 */
public class ContactListFragment extends ListFragment {

    /**
     * The serialization (saved instance state) Bundle key representing the
     * activated item position. Only used on tablets.
     */
    private static final String STATE_ACTIVATED_POSITION = "activated_position";

    /**
     * The fragment's current callback object, which is notified of list item
     * clicks.
     */
    private Callbacks mCallbacks = sDummyCallbacks;

    /**
     * The current activated item position. Only used on tablets.
     */
    private int mActivatedPosition = ListView.INVALID_POSITION;

    /**
     * A callback interface that all activities containing this fragment must
     * implement. This mechanism allows activities to be notified of item
     * selections.
     */
    public interface Callbacks {
        /**
         * Callback for when an item has been selected.
         */
        public void onItemSelected(String id);
    }

    /**
     * A dummy implementation of the {@link Callbacks} interface that does
     * nothing. Used only when this fragment is not attached to an activity.
     */
    private static Callbacks sDummyCallbacks = new Callbacks() {
        @Override
        public void onItemSelected(String id) {
        }
    };

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

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

        // TODO: replace with a real list adapter.
        setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(
                getActivity(),
                android.R.layout.simple_list_item_activated_1,
                android.R.id.text1,
                DummyContent.ITEMS));
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Restore the previously serialized activated item position.
        if (savedInstanceState != null
                && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
            setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
        }
    }

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

        // Activities containing this fragment must implement its callbacks.
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }

        mCallbacks = (Callbacks) activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        // Reset the active callbacks interface to the dummy implementation.
        mCallbacks = sDummyCallbacks;
    }

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        super.onListItemClick(listView, view, position, id);

        // Notify the active callbacks interface (the activity, if the
        // fragment is attached to one) that an item has been selected.
        mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mActivatedPosition != ListView.INVALID_POSITION) {
            // Serialize and persist the activated item position.
            outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
        }
    }

    /**
     * Turns on activate-on-click mode. When this mode is on, list items will be
     * given the 'activated' state when touched.
     */
    public void setActivateOnItemClick(boolean activateOnItemClick) {
        // When setting CHOICE_MODE_SINGLE, ListView will automatically
        // give items the 'activated' state when touched.
        getListView().setChoiceMode(activateOnItemClick
                ? ListView.CHOICE_MODE_SINGLE
                : ListView.CHOICE_MODE_NONE);
    }

    private void setActivatedPosition(int position) {
        if (position == ListView.INVALID_POSITION) {
            getListView().setItemChecked(mActivatedPosition, false);
        } else {
            getListView().setItemChecked(position, true);
        }

        mActivatedPosition = position;
    }
}

布局的 XML:

活动联系人列表:

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/contact_list"
        android:name="com.cyphrd.chirp.ContactListFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        tools:context=".ContactListActivity"
        tools:layout="@android:layout/list_content" />

activity_contact_twopane.xml

    <!--
    This layout is a two-pane layout for the Contacts
    master/detail flow. See res/values-large/refs.xml and
    res/values-sw600dp/refs.xml for an example of layout aliases
    that replace the single-pane version of the layout with
    this two-pane version.

    For more on layout aliases, see:
    http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
    -->

    <fragment
        android:id="@+id/contact_list"
        android:name="com.cyphrd.chirp.ContactListFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        tools:layout="@android:layout/list_content" />

    <FrameLayout
        android:id="@+id/contact_detail_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3" />

</LinearLayout>

日志猫:

12-08 15:11:31.978: E/AndroidRuntime(7071): FATAL EXCEPTION: main
12-08 15:11:31.978: E/AndroidRuntime(7071): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cyphrd.chirpd/com.cyphrd.chirpd.ContactListActivity}: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2049)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2083)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.ActivityThread.access$600(ActivityThread.java:134)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1233)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.os.Looper.loop(Looper.java:137)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.ActivityThread.main(ActivityThread.java:4697)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at java.lang.reflect.Method.invokeNative(Native Method)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at java.lang.reflect.Method.invoke(Method.java:511)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at dalvik.system.NativeStart.main(Native Method)
12-08 15:11:31.978: E/AndroidRuntime(7071): Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:255)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.Activity.setContentView(Activity.java:1879)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at com.cyphrd.chirpd.ContactListActivity.onCreate(ContactListActivity.java:39)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.Activity.performCreate(Activity.java:4539)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2013)
12-08 15:11:31.978: E/AndroidRuntime(7071):     ... 11 more
12-08 15:11:31.978: E/AndroidRuntime(7071): Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.cyphrd.chirp.ContactListFragment: make sure class name exists, is public, and has an empty constructor that is public
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.support.v4.app.Fragment.instantiate(Fragment.java:401)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.support.v4.app.Fragment.instantiate(Fragment.java:369)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:272)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:669)
12-08 15:11:31.978: E/AndroidRuntime(7071):     ... 20 more
12-08 15:11:31.978: E/AndroidRuntime(7071): Caused by: java.lang.ClassNotFoundException: com.cyphrd.chirp.ContactListFragment
12-08 15:11:31.978: E/AndroidRuntime(7071):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
12-08 15:11:31.978: E/AndroidRuntime(7071):     at android.support.v4.app.Fragment.instantiate(Fragment.java:391)
12-08 15:11:31.978: E/AndroidRuntime(7071):     ... 23 more

清单.xml:

<activity
            android:name="com.cyphrd.chirpd.ContactListActivity"
            android:label="@string/title_contact_list" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.cyphrd.chirpd.ContactChatActivity"
            android:label="@string/title_contact_detail"
            android:parentActivityName="com.cyphrd.chirpd.ContactListActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".ContactListActivity" />
        </activity>
4

2 回答 2

3

您已经在您的 XML 文件中为该类声明了 Fragment:

 com.cyphrd.chirp.ContactListFragment

但它看起来像是在包装中:

 package com.cyphrd.chirpd
于 2012-12-08T22:29:55.323 回答
0

您是否考虑过通过执行以下操作来放入框架布局并在 oncreate 中动态添加片段:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.placeholder_framelayout, new ContactChatFragment());
ft.commit();

这段代码应该可以正常工作,但我只是从内存中输入的,因此替换函数可能会将字段向后。

于 2012-12-08T22:27:51.083 回答