14

我想讓我的ExpandableListActivity與Honeycomb兼容。 我想知道爲什麼沒有兼容包的ExpandableListFragment。ExpandableListFragment與LoaderManager的兼容性包

有沒有辦法讓ExpandableListView與普通的Fragment類一起工作? 如何使用LoaderManager加載遊標?

+4

我已經在http://code.google.com/p/android/issues/detail?id=20973提交了此功能請求..請爲此投票。 – 2011-10-19 21:29:05

回答

23

我有同樣的問題。我沒有找到這個解決方案,所以我決定自己基於android.support.v4.app.ListFragment(Compatibility API)和API level 8的android.app.ExpandableListActivity的組合來實現ExpandableListFragment,所以這應該與API級別兼容< 11.

雖然我沒有答案關於遊標和LoaderManagers的問題。

有一點需要注意一下我的ExpandableListFragment版本,你必須從你的封裝活動的oncontentchanged() - 方法定義中自己調用onContentChanged()方法,否則就不會有任何附加到列表項的監聽器。

爲ExpandableListFragment的源代碼(在android.support.v4.app的本地包副本,將其命名爲你想要的):

package android.support.v4.app; 

import android.app.Fragment; 
import android.os.Bundle; 
import android.os.Handler; 
import android.view.ContextMenu; 
import android.view.ContextMenu.ContextMenuInfo; 
import android.view.Gravity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnCreateContextMenuListener; 
import android.view.ViewGroup; 
import android.view.animation.AnimationUtils; 
import android.widget.AdapterView; 
import android.widget.ExpandableListAdapter; 
import android.widget.ExpandableListView; 
import android.widget.FrameLayout; 
import android.widget.ListAdapter; 
import android.widget.ListView; 
import android.widget.TextView; 

public class ExpandableListFragment extends Fragment 
    implements OnCreateContextMenuListener, 
    ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, 
    ExpandableListView.OnGroupExpandListener 
    { 

    static final int INTERNAL_EMPTY_ID = 0x00ff0001; 

    final private Handler mHandler = new Handler(); 

    final private Runnable mRequestFocus = new Runnable() { 
     public void run() { 
      mList.focusableViewAvailable(mList); 
     } 
    }; 

    final private AdapterView.OnItemClickListener mOnClickListener 
      = new AdapterView.OnItemClickListener() { 
     public void onItemClick(AdapterView<?> parent, View v, int position, long id) { 
      onListItemClick((ListView)parent, v, position, id); 
     } 
    }; 

    ExpandableListAdapter mAdapter; 
    ExpandableListView mList; 
    View mEmptyView; 
    TextView mStandardEmptyView; 
    View mListContainer; 
    boolean mSetEmptyText; 
    boolean mListShown; 
    boolean mFinishedStart = false; 

    public ExpandableListFragment() { 
    } 

    /** 
    * Provide default implementation to return a simple list view. Subclasses 
    * can override to replace with their own layout. If doing so, the 
    * returned view hierarchy <em>must</em> have a ListView whose id 
    * is {@link android.R.id#list android.R.id.list} and can optionally 
    * have a sibling view id {@link android.R.id#empty android.R.id.empty} 
    * that is to be shown when the list is empty. 
    * 
    * <p>If you are overriding this method with your own custom content, 
    * consider including the standard layout {@link android.R.layout#list_content} 
    * in your layout file, so that you continue to retain all of the standard 
    * behavior of ListFragment. In particular, this is currently the only 
    * way to have the built-in indeterminant progress state be shown. 
    */ 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     FrameLayout root = new FrameLayout(getActivity()); 

     TextView tv = new TextView(getActivity()); 
     tv.setId(INTERNAL_EMPTY_ID); 
     tv.setGravity(Gravity.CENTER); 
     root.addView(tv, new FrameLayout.LayoutParams(
       ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); 

     ListView lv = new ListView(getActivity()); 
     lv.setId(android.R.id.list); 
     lv.setDrawSelectorOnTop(false); 
     root.addView(lv, new FrameLayout.LayoutParams(
       ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); 

     ListView.LayoutParams lp = new ListView.LayoutParams(
       ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); 
     root.setLayoutParams(lp); 

     return root; 
    } 

    /** 
    * Attach to list view once Fragment is ready to run. 
    */ 
    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     ensureList(); 
    } 

    /** 
    * Detach from list view. 
    */ 
    @Override 
    public void onDestroyView() { 
     mHandler.removeCallbacks(mRequestFocus); 
     mList = null; 
     super.onDestroyView(); 
    } 

    /** 
    * This method will be called when an item in the list is selected. 
    * Subclasses should override. Subclasses can call 
    * getListView().getItemAtPosition(position) if they need to access the 
    * data associated with the selected item. 
    * 
    * @param l The ListView where the click happened 
    * @param v The view that was clicked within the ListView 
    * @param position The position of the view in the list 
    * @param id The row id of the item that was clicked 
    */ 
    public void onListItemClick(ListView l, View v, int position, long id) { 
    } 

    /** 
    * Provide the cursor for the list view. 
    */ 
    public void setListAdapter(ExpandableListAdapter adapter) { 
     boolean hadAdapter = mAdapter != null; 
     mAdapter = adapter; 
     if (mList != null) { 
      mList.setAdapter(adapter); 
      if (!mListShown && !hadAdapter) { 
       // The list was hidden, and previously didn't have an 
       // adapter. It is now time to show it. 
       setListShown(true, getView().getWindowToken() != null); 
      } 
     } 
    } 

    /** 
    * Set the currently selected list item to the specified 
    * position with the adapter's data 
    * 
    * @param position 
    */ 
    public void setSelection(int position) { 
     ensureList(); 
     mList.setSelection(position); 
    } 

    public long getSelectedPosition() { 
     ensureList(); 
     return mList.getSelectedPosition(); 
    } 

    public long getSelectedId() { 
     ensureList(); 
     return mList.getSelectedId(); 
    } 

    public ExpandableListView getExpandableListView() { 
     ensureList(); 
     return mList; 
    } 

    /** 
    * The default content for a ListFragment has a TextView that can 
    * be shown when the list is empty. If you would like to have it 
    * shown, call this method to supply the text it should use. 
    */ 
    public void setEmptyText(CharSequence text) { 
     ensureList(); 
     if (mStandardEmptyView == null) { 
      throw new IllegalStateException("Can't be used with a custom content view"); 
     } 
     mStandardEmptyView.setText(text); 
     if (!mSetEmptyText) { 
      mList.setEmptyView(mStandardEmptyView); 
      mSetEmptyText = true; 
     } 
    } 

    /** 
    * Control whether the list is being displayed. You can make it not 
    * displayed if you are waiting for the initial data to show in it. During 
    * this time an indeterminant progress indicator will be shown instead. 
    * 
    * <p>Applications do not normally need to use this themselves. The default 
    * behavior of ListFragment is to start with the list not being shown, only 
    * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}. 
    * If the list at that point had not been shown, when it does get shown 
    * it will be do without the user ever seeing the hidden state. 
    * 
    * @param shown If true, the list view is shown; if false, the progress 
    * indicator. The initial value is true. 
    */ 
    public void setListShown(boolean shown) { 
     setListShown(shown, true); 
    } 

    /** 
    * Like {@link #setListShown(boolean)}, but no animation is used when 
    * transitioning from the previous state. 
    */ 
    public void setListShownNoAnimation(boolean shown) { 
     setListShown(shown, false); 
    } 

    /** 
    * Control whether the list is being displayed. You can make it not 
    * displayed if you are waiting for the initial data to show in it. During 
    * this time an indeterminant progress indicator will be shown instead. 
    * 
    * @param shown If true, the list view is shown; if false, the progress 
    * indicator. The initial value is true. 
    * @param animate If true, an animation will be used to transition to the 
    * new state. 
    */ 
    private void setListShown(boolean shown, boolean animate) { 
     ensureList(); 
     if (mListShown == shown) { 
      return; 
     } 
     mListShown = shown; 
     if (shown) { 
      if (animate) { 
       mListContainer.startAnimation(AnimationUtils.loadAnimation(
         getActivity(), android.R.anim.fade_in)); 
      } 
      mListContainer.setVisibility(View.VISIBLE); 
     } else { 
      if (animate) { 
       mListContainer.startAnimation(AnimationUtils.loadAnimation(
         getActivity(), android.R.anim.fade_out)); 
      } 
      mListContainer.setVisibility(View.GONE); 
     } 
    } 

    /** 
    * Get the ListAdapter associated with this activity's ListView. 
    */ 
    public ExpandableListAdapter getExpandableListAdapter() { 
     return mAdapter; 
    } 

    private void ensureList() { 
     if (mList != null) { 
      return; 
     } 
     View root = getView(); 
     if (root == null) { 
      throw new IllegalStateException("Content view not yet created"); 
     } 
     if (root instanceof ExpandableListView) { 
      mList = (ExpandableListView)root; 
     } else { 
      mStandardEmptyView = (TextView)root.findViewById(INTERNAL_EMPTY_ID); 
      if (mStandardEmptyView == null) { 
       mEmptyView = root.findViewById(android.R.id.empty); 
      } 
      mListContainer = null; //root.findViewById(com.android.internal.R.id.listContainer); 
      View rawListView = root.findViewById(android.R.id.list); 
      if (!(rawListView instanceof ExpandableListView)) { 
       if (rawListView == null) { 
        throw new RuntimeException(
          "Your content must have a ExpandableListView whose id attribute is " + 
          "'android.R.id.list'"); 
       } 
       throw new RuntimeException(
         "Content has view with id attribute 'android.R.id.list' " 
         + "that is not a ExpandableListView class"); 
      } 
      mList = (ExpandableListView)rawListView; 
      if (mEmptyView != null) { 
       mList.setEmptyView(mEmptyView); 
      } 
     } 
     mListShown = true; 
     mList.setOnItemClickListener(mOnClickListener); 
     if (mAdapter != null) { 
      setListAdapter(mAdapter); 
     } else { 
      // We are starting without an adapter, so assume we won't 
      // have our data right away and start with the progress indicator. 
      setListShown(false, false); 
     } 
     mHandler.post(mRequestFocus); 
    } 

    @Override 
    public void onGroupExpand(int arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onGroupCollapse(int arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public boolean onChildClick(ExpandableListView arg0, View arg1, int arg2, 
      int arg3, long arg4) { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @Override 
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 
    } 

    public void onContentChanged() { 
     View emptyView = getView().findViewById(android.R.id.empty); 
     mList = (ExpandableListView)getView().findViewById(android.R.id.list); 
     if (mList == null) { 
      throw new RuntimeException(
        "Your content must have a ExpandableListView whose id attribute is " + 
        "'android.R.id.list'"); 
     } 
     if (emptyView != null) { 
      mList.setEmptyView(emptyView); 
     } 
     mList.setOnChildClickListener(this); 
     mList.setOnGroupExpandListener(this); 
     mList.setOnGroupCollapseListener(this); 

     if (mFinishedStart) { 
      setListAdapter(mAdapter); 
     } 
     mFinishedStart = true; 
    } 
} 
+0

感謝您的幫助,我以類似的方式解決,問題是沒有SupportTreeCursor那個 – user579619 2011-06-16 14:01:33

+0

08-11 22:21:25.396:WARN/dalvikvm(18239):無法解析Landroid/support/v4的超類/應用程序/ ExpandableListFragment; (15) – 2011-08-11 20:23:53

+4

這個實現的小問題,你應該在創建一個ExpandableListView時在onCreateView()方法上創建一個ListView,因爲下面的方法調用ensureList()它會驗證你的實例是ExpandableListView.class! – Necronet 2011-09-08 08:23:22

2

我想改變可能最少的;代替使用上面的片段實現,當已經使用ExpandableListActivity時,可以簡單地將ExpandableListActivity的代碼複製到自己的應用程序中,將內部R. *資源引用更改爲使用對應的公共名稱空間,並將該類更改爲從FragmentActivity繼承。

9

不知道是否有人可以從arne.jans的帖子中獲得代碼,但我無法這樣做,因爲mListContainer始終爲空。每次我們去setListShown方法時,ensureList()都會被調用。

因此,我使用了與arne.jans相同的想法,結合了ListFragment和ExpandableListActivity的代碼(從http://grepcode.com/下載)。我終於開始工作,並認爲這可能對其他人有幫助。下面是代碼:

package mypackage.util; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnCreateContextMenuListener; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ProgressBar; import android.widget.TextView; public class ExpandableListFragment extends Fragment implements OnCreateContextMenuListener, ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, ExpandableListView.OnGroupExpandListener { static final int INTERNAL_EMPTY_ID = 0x00ff0001; static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002; static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003; final private Handler mHandler = new Handler(); final private Runnable mRequestFocus = new Runnable() { public void run() { mExpandableList.focusableViewAvailable(mExpandableList); } }; final private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { onListItemClick((ExpandableListView)parent, v, position, id); } }; ExpandableListAdapter mAdapter; ExpandableListView mExpandableList; boolean mFinishedStart = false; View mEmptyView; TextView mStandardEmptyView; View mProgressContainer; View mExpandableListContainer; CharSequence mEmptyText; boolean mExpandableListShown; public ExpandableListFragment() { } /** * Provide default implementation to return a simple list view. Subclasses * can override to replace with their own layout. If doing so, the * returned view hierarchy <em>must</em> have a ListView whose id * is {@link android.R.id#list android.R.id.list} and can optionally * have a sibling view id {@link android.R.id#empty android.R.id.empty} * that is to be shown when the list is empty. * * <p>If you are overriding this method with your own custom content, * consider including the standard layout {@link android.R.layout#list_content} * in your layout file, so that you continue to retain all of the standard * behavior of ListFragment. In particular, this is currently the only * way to have the built-in indeterminant progress state be shown. */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final Context context = getActivity(); FrameLayout root = new FrameLayout(context); // ------------------------------------------------------------------ LinearLayout pframe = new LinearLayout(context); pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID); pframe.setOrientation(LinearLayout.VERTICAL); pframe.setVisibility(View.GONE); pframe.setGravity(Gravity.CENTER); ProgressBar progress = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge); pframe.addView(progress, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); root.addView(pframe, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); // ------------------------------------------------------------------ FrameLayout lframe = new FrameLayout(context); lframe.setId(INTERNAL_LIST_CONTAINER_ID); TextView tv = new TextView(getActivity()); tv.setId(INTERNAL_EMPTY_ID); tv.setGravity(Gravity.CENTER); lframe.addView(tv, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); ExpandableListView lv = new ExpandableListView(getActivity()); lv.setId(android.R.id.list); lv.setDrawSelectorOnTop(false); lframe.addView(lv, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); root.addView(lframe, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); // ------------------------------------------------------------------ root.setLayoutParams(new FrameLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); return root; } /** * Attach to list view once the view hierarchy has been created. */ @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ensureList(); } /** * Detach from list view. */ @Override public void onDestroyView() { mHandler.removeCallbacks(mRequestFocus); mExpandableList = null; mExpandableListShown = false; mEmptyView = mProgressContainer = mExpandableListContainer = null; mStandardEmptyView = null; super.onDestroyView(); } /** * This method will be called when an item in the list is selected. * Subclasses should override. Subclasses can call * getListView().getItemAtPosition(position) if they need to access the * data associated with the selected item. * * @param l The ListView where the click happened * @param v The view that was clicked within the ListView * @param position The position of the view in the list * @param id The row id of the item that was clicked */ public void onListItemClick(ExpandableListView l, View v, int position, long id) { } /** * Provide the cursor for the list view. */ public void setListAdapter(ExpandableListAdapter adapter) { boolean hadAdapter = mAdapter != null; mAdapter = adapter; if (mExpandableList != null) { mExpandableList.setAdapter(adapter); if (!mExpandableListShown && !hadAdapter) { // The list was hidden, and previously didn't have an // adapter. It is now time to show it. setListShown(true, getView().getWindowToken() != null); } } } /** * Set the currently selected list item to the specified * position with the adapter's data * * @param position */ public void setSelection(int position) { ensureList(); mExpandableList.setSelection(position); } /** * Get the position of the currently selected list item. */ public int getSelectedItemPosition() { ensureList(); return mExpandableList.getSelectedItemPosition(); } /** * Get the cursor row ID of the currently selected list item. */ public long getSelectedItemId() { ensureList(); return mExpandableList.getSelectedItemId(); } /** * Get the activity's list view widget. */ public ExpandableListView getListView() { ensureList(); return mExpandableList; } /** * The default content for a ListFragment has a TextView that can * be shown when the list is empty. If you would like to have it * shown, call this method to supply the text it should use. */ public void setEmptyText(CharSequence text) { ensureList(); if (mStandardEmptyView == null) { throw new IllegalStateException("Can't be used with a custom content view"); } mStandardEmptyView.setText(text); if (mEmptyText == null) { mExpandableList.setEmptyView(mStandardEmptyView); } mEmptyText = text; } /** * Control whether the list is being displayed. You can make it not * displayed if you are waiting for the initial data to show in it. During * this time an indeterminant progress indicator will be shown instead. * * <p>Applications do not normally need to use this themselves. The default * behavior of ListFragment is to start with the list not being shown, only * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}. * If the list at that point had not been shown, when it does get shown * it will be do without the user ever seeing the hidden state. * * @param shown If true, the list view is shown; if false, the progress * indicator. The initial value is true. */ public void setListShown(boolean shown) { setListShown(shown, true); } /** * Like {@link #setListShown(boolean)}, but no animation is used when * transitioning from the previous state. */ public void setListShownNoAnimation(boolean shown) { setListShown(shown, false); } /** * Control whether the list is being displayed. You can make it not * displayed if you are waiting for the initial data to show in it. During * this time an indeterminant progress indicator will be shown instead. * * @param shown If true, the list view is shown; if false, the progress * indicator. The initial value is true. * @param animate If true, an animation will be used to transition to the * new state. */ private void setListShown(boolean shown, boolean animate) { ensureList(); if (mProgressContainer == null) { throw new IllegalStateException("Can't be used with a custom content view"); } if (mExpandableListShown == shown) { return; } mExpandableListShown = shown; if (shown) { if (animate) { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_out)); mExpandableListContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_in)); } else { mProgressContainer.clearAnimation(); mExpandableListContainer.clearAnimation(); } mProgressContainer.setVisibility(View.GONE); mExpandableListContainer.setVisibility(View.VISIBLE); } else { if (animate) { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_in)); mExpandableListContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_out)); } else { mProgressContainer.clearAnimation(); mExpandableListContainer.clearAnimation(); } mProgressContainer.setVisibility(View.VISIBLE); mExpandableListContainer.setVisibility(View.GONE); } } /** * Get the ListAdapter associated with this activity's ListView. */ public ExpandableListAdapter getListAdapter() { return mAdapter; } private void ensureList() { if (mExpandableList != null) { return; } View root = getView(); if (root == null) { throw new IllegalStateException("Content view not yet created"); } if (root instanceof ExpandableListView) { mExpandableList = (ExpandableListView)root; } else { mStandardEmptyView = (TextView)root.findViewById(INTERNAL_EMPTY_ID); if (mStandardEmptyView == null) { mEmptyView = root.findViewById(android.R.id.empty); } else { mStandardEmptyView.setVisibility(View.GONE); } mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID); mExpandableListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID); View rawExpandableListView = root.findViewById(android.R.id.list); if (!(rawExpandableListView instanceof ExpandableListView)) { if (rawExpandableListView == null) { throw new RuntimeException( "Your content must have a ListView whose id attribute is " + "'android.R.id.list'"); } throw new RuntimeException( "Content has view with id attribute 'android.R.id.list' " + "that is not a ListView class"); } mExpandableList = (ExpandableListView)rawExpandableListView; if (mEmptyView != null) { mExpandableList.setEmptyView(mEmptyView); } else if (mEmptyText != null) { mStandardEmptyView.setText(mEmptyText); mExpandableList.setEmptyView(mStandardEmptyView); } } mExpandableListShown = true; mExpandableList.setOnItemClickListener(mOnClickListener); if (mAdapter != null) { ExpandableListAdapter adapter = mAdapter; mAdapter = null; setListAdapter(adapter); } else { // We are starting without an adapter, so assume we won't // have our data right away and start with the progress indicator. if (mProgressContainer != null) { setListShown(false, false); } } mHandler.post(mRequestFocus); } /** * Override this to populate the context menu when an item is long pressed. menuInfo * will contain an {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo} * whose packedPosition is a packed position * that should be used with {@link ExpandableListView#getPackedPositionType(long)} and * the other similar methods. * <p> * {@inheritDoc} */ @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { } /** * Override this for receiving callbacks when a child has been clicked. * <p> * {@inheritDoc} */ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { return false; } /** * Override this for receiving callbacks when a group has been collapsed. */ public void onGroupCollapse(int groupPosition) { } /** * Override this for receiving callbacks when a group has been expanded. */ public void onGroupExpand(int groupPosition) { } // /** // * Ensures the expandable list view has been created before Activity restores all // * of the view states. // * // *@see Activity#onRestoreInstanceState(Bundle) // */ // @Override // protected void onRestoreInstanceState(Bundle state) { // ensureList(); // super.onRestoreInstanceState(state); // } /** * Updates the screen state (current list and other views) when the * content changes. * * @see Activity#onContentChanged() */ public void onContentChanged() { // super.onContentChanged(); View emptyView = getView().findViewById(android.R.id.empty); mExpandableList = (ExpandableListView)getView().findViewById(android.R.id.list); if (mExpandableList == null) { throw new RuntimeException( "Your content must have a ExpandableListView whose id attribute is " + "'android.R.id.list'"); } if (emptyView != null) { mExpandableList.setEmptyView(emptyView); } mExpandableList.setOnChildClickListener(this); mExpandableList.setOnGroupExpandListener(this); mExpandableList.setOnGroupCollapseListener(this); if (mFinishedStart) { setListAdapter(mAdapter); } mFinishedStart = true; } /** * Get the activity's expandable list view widget. This can be used to get the selection, * set the selection, and many other useful functions. * * @see ExpandableListView */ public ExpandableListView getExpandableListView() { ensureList(); return mExpandableList; } /** * Get the ExpandableListAdapter associated with this activity's * ExpandableListView. */ public ExpandableListAdapter getExpandableListAdapter() { return mAdapter; } /** * Gets the ID of the currently selected group or child. * * @return The ID of the currently selected group or child. */ public long getSelectedId() { return mExpandableList.getSelectedId(); } /** * Gets the position (in packed position representation) of the currently * selected group or child. Use * {@link ExpandableListView#getPackedPositionType}, * {@link ExpandableListView#getPackedPositionGroup}, and * {@link ExpandableListView#getPackedPositionChild} to unpack the returned * packed position. * * @return A packed position representation containing the currently * selected group or child's position and type. */ public long getSelectedPosition() { return mExpandableList.getSelectedPosition(); } /** * Sets the selection to the specified child. If the child is in a collapsed * group, the group will only be expanded and child subsequently selected if * shouldExpandGroup is set to true, otherwise the method will return false. * * @param groupPosition The position of the group that contains the child. * @param childPosition The position of the child within the group. * @param shouldExpandGroup Whether the child's group should be expanded if * it is collapsed. * @return Whether the selection was successfully set on the child. */ public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) { return mExpandableList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup); } /** * Sets the selection to the specified group. * @param groupPosition The position of the group that should be selected. */ public void setSelectedGroup(int groupPosition) { mExpandableList.setSelectedGroup(groupPosition); } }

希望它有時可以節省你。

+0

感謝您的代碼,非常好,不幸的是我不能把這個工作,你可以給你一個小例子,你如何從FragmentActivity實現這個? – Machete 2012-05-16 19:37:22

+3

jmachete,如果你想要一個例子,你可以訪問我在https://github.com/CUTR-at-USF/OpenTripPlanner-for-Android上工作的項目。具體來說,你想看看DirectionListFragment和MyActivity。 – 2012-05-18 23:01:38

+1

@ ktran9.lbs感謝您指出真實的樣本。對於那些討厭在Java項目中導航的人,這裏是ExpandableListFragment後代的直接鏈接:https://github.com/CUTR-at-USF/OpenTripPlanner-for-Android/blob/master/src/edu/usf/ cutr/opentripplanner/android/fragments/DirectionListFragment.java – 2012-06-22 20:16:05