2010-03-26 76 views
3

我想擴展BaseExpandableListAdapter,但是當我查看列表並選擇其中一個要展開的元素時,列表的順序就會顛倒過來。例如,如果我有一個包含4個元素的列表並選擇第一個元素,那麼順序(從頂部到底部)現在是4,3,2,1,第四個元素(現在在頂部)展開。如果我未展開第四個元素,則順序將恢復爲1,2,3,4而不會展開元素。Android擴展BaseExpandableListAdapter

這是我實現:

public class SensorExpandableAdapter extends BaseExpandableListAdapter {

private static final int FILTER_POSITION = 0; 
    private static final int FUNCTION_POSITION = 1; 
    private static final int NUMBER_OF_CHILDREN = 2; 
    ArrayList<SensorType> mParentGroups; 
    private Context mContext; 
    private LayoutInflater mInflater; 

    public SensorExpandableAdapter(ArrayList<SensorType> parentGroup, Context context) { 
     mParentGroups = parentGroup; 
     mContext = context; 
     mInflater = LayoutInflater.from(mContext); 
    } 
    @Override 
    public Object getChild(int groupPosition, int childPosition) { 
     // TODO Auto-generated method stub 
     if(childPosition == FILTER_POSITION) return "filter"; 
     else return "function"; 
    } 

    @Override 
    public long getChildId(int groupPosition, int childPosition) { 
     return childPosition; 
    } 

    @Override 
    public View getChildView(int groupPosition, int childPosition, 
      boolean isLastChild, View convertView, ViewGroup parent) { 
     if(convertView == null) 
     { 
      convertView = (RelativeLayout)mInflater.inflate(R.layout.sensor_row_list_item, parent, false); 
      if(childPosition == FILTER_POSITION) { 
       ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Filter"); 
      } else { 
       ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Function"); 
       ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setEnabled(false); 
      } 
     } 
     return convertView; 
    } 

    @Override 
    public int getChildrenCount(int groupPosition) { 
     // TODO Auto-generated method stub 
     return NUMBER_OF_CHILDREN; 
    } 

    @Override 
    public Object getGroup(int groupPosition) { 
     return mParentGroups.get(groupPosition); 
    } 

    @Override 
    public int getGroupCount() { 
     // TODO Auto-generated method stub 
     return mParentGroups.size(); 
    } 

    @Override 
    public long getGroupId(int groupPosition) { 
     // TODO Auto-generated method stub 
     return groupPosition; 
    } 

    @Override 
    public View getGroupView(int groupPosition, boolean isExpanded, 
      View convertView, ViewGroup parent) { 
     if(convertView == null) 
     { 
      convertView = mInflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false); 
      TextView tv = ((TextView)convertView.findViewById(android.R.id.text1)); 
      tv.setText(mParentGroups.get(groupPosition).toString()); 
     } 
     return convertView; 
    } 

    @Override 
    public boolean hasStableIds() { 
     // TODO Auto-generated method stub 
     return true; 
    } 

    @Override 
    public boolean isChildSelectable(int groupPosition, int childPosition) { 
     // TODO Auto-generated method stub 
     return true; 
    } 
} 

`

我只需要把我自己的SensorType類的簡單的ArrayList。所有課程的孩子都是一樣的,只有兩個。

另外,我該如何去做每組LongClickable中的父項?我已經在我的ExpandableListActivity中使用此getExpandableListView().setOnLongClickableListener() ...進行了嘗試,並在父級TextView上設置了它的OnLongClickableListener,但都不起作用。

任何幫助都非常感謝!

回答

3
public View getGroupView(int groupPosition, boolean isExpanded, 
      View convertView, ViewGroup parent) { 
     if(convertView == null) 
     { 

只是評論「如果」。這應該有所幫助。

+0

就遇到了這個問題。這個修復它。您必須禁用convertView檢查或使其更健壯一些。在展開或摺疊列表之後,如果它看到convertView(表示列表中該位置的緩存項目)不爲null,它將重新填充列表,它將重新使用該舊視圖。 因此,您必須按照陳述刪除空檢查或進行進一步檢查,例如比較ids/tags/etc以確保您重新使用您想要重用的視圖。 – Dan 2011-03-21 02:53:59

1

更新:這個答案來得太晚;但對於有同樣問題的人來說,這裏是我的解決方案。

我剛剛有同樣的問題,並設法在閱讀chome2phone源代碼後解決。

的關鍵是確實這個方法:

public View getChildView(int groupPosition, int childPosition, 
      boolean isLastChild, View convertView, ViewGroup parent) { 
     if(convertView == null) 
     { 
      convertView = (RelativeLayout)mInflater.inflate(R.layout.sensor_row_list_item, parent, false); 
      if(childPosition == FILTER_POSITION) { 
       ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Filter"); 
      } else { 
       ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Function"); 
       ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setEnabled(false); 
      } 
     } 
     return convertView; 
    } 

AS @丹說,convertView是一個高速緩存項,爲documentation說:

convertView:舊觀點重用, 如果可能的話。 在使用之前,您應檢查此視圖是否爲非空,並且是否爲合適的類型 。如果無法將 轉換爲此視圖以顯示 正確的數據,則此方法可創建 新視圖。不保證 的convertView將會是 以前由 創建的getChildView(int,int,boolean,View, ViewGroup)。

在我的情況下,傳遞給getChildView()的對象可能來自緩存,其順序與創建順序完全相反;一堆可能(LIFO)。

主要有兩種解決方案;要麼你將刪除

如果(convertView == NULL)

從而重建孩子的每一個展開/摺疊動作或在每個方向的改變,或(方法更好的性能明智)做一些這樣的:

public View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) { 
    RelativeLayout mItemView; 
    if (null == convertView || !(convertView instanceof RelativeLayout)) { 
     mItemView = (RelativeLayout)mInflater.inflate(R.layout.sensor_row_list_item, parent, false); 
    }else{ 
     mItemView = (RelativeLayout) convertView; 
    } 
    if(childPosition == FILTER_POSITION) { 
     ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Filter"); 
    } else { 
     ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setText("Add Function"); 
     ((CheckBox)convertView.findViewById(R.id.chkTextAddFilter)).setEnabled(false); 
    } 
} 
return convertView; 

這意味着您將使用對象convertView來渲染項目,而不是創建一個新項目。

我希望這也適用於你。

1

我希望這是你正在尋找

public class Sample extends ExpandableListActivity { 

    ExpandableListAdapter mAdapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
      mAdapter = new MyExpandableListAdapter(); 
      setListAdapter(mAdapter); 
      registerForContextMenu(getExpandableListView()); 
    } 

    @Override 
public void onCreateContextMenu(ContextMenu menu, View v, 
     ContextMenuInfo menuInfo) { 
    // TODO Auto-generated method stub 
    super.onCreateContextMenu(menu, v, menuInfo); 

     menu.setHeaderTitle("Sample menu"); 
     menu.add(0, 0, 0, R.string.expandable_list_sample_action); 

} 

    @Override 
    public boolean onContextItemSelected(MenuItem item) { 
     // TODO Auto-generated method stub 

     ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo(); 

     String title = ((TextView) info.targetView).getText().toString(); 



     int type = ExpandableListView.getPackedPositionType(info.packedPosition); 

     if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) { 
      int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
      int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition); 
      Toast.makeText(Sample.this, title + ": Child " + childPos + " clicked in group " + groupPos, 
        Toast.LENGTH_SHORT).show(); 
      return true; 
     } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { 
      int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
      Toast.makeText(this, title + ": Group " + groupPos + " clicked", Toast.LENGTH_SHORT).show(); 
      return true; 
     } 

     return false; 

    } 
    /** 
    * A simple adapter which maintains an ArrayList of photo resource Ids. 
    * Each photo is displayed as an image. This adapter supports clearing the 
    * list of photos and adding a new photo. 
    * 
    */ 
    public class MyExpandableListAdapter extends BaseExpandableListAdapter { 
     // Sample data set. children[i] contains the children (String[]) for groups[i]. 
     private String[] groups = { "People Names", "Dog Names", "Cat Names", "Fish Names" }; 
     private String[][] children = { 
       { "Arnold", "Barry", "Chuck", "David" }, 
       { "Ace", "Bandit", "Cha-Cha", "Deuce" }, 
       { "Fluffy", "Snuggles" }, 
       { "Goldy", "Bubbles" } 
     }; 

     public Object getChild(int groupPosition, int childPosition) { 
      return children[groupPosition][childPosition]; 
     } 

     public long getChildId(int groupPosition, int childPosition) { 
      return childPosition; 
     } 

     public int getChildrenCount(int groupPosition) { 
      return children[groupPosition].length; 
     } 

     public TextView getGenericView() { 
      // Layout parameters for the ExpandableListView 
      AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
        ViewGroup.LayoutParams.FILL_PARENT, 64); 

      TextView textView = new TextView(Sample.this); 
      textView.setLayoutParams(lp); 
      // Center the text vertically 
      textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); 
      // Set the text starting position 
      textView.setPadding(36, 0, 0, 0); 
      return textView; 
     } 

     public View getChildView(int groupPosition, int childPosition, boolean isLastChild, 
       View convertView, ViewGroup parent) { 
      TextView textView = getGenericView(); 
      textView.setText(getChild(groupPosition, childPosition).toString()); 
      return textView; 
     } 

     public Object getGroup(int groupPosition) { 
      return groups[groupPosition]; 
     } 

     public int getGroupCount() { 
      return groups.length; 
     } 

     public long getGroupId(int groupPosition) { 
      return groupPosition; 
     } 

     public View getGroupView(int groupPosition, boolean isExpanded, View convertView, 
       ViewGroup parent) { 
      TextView textView = getGenericView(); 
      textView.setText(getGroup(groupPosition).toString()); 
      return textView; 
     } 

     public boolean isChildSelectable(int groupPosition, int childPosition) { 
      return true; 
     } 

     public boolean hasStableIds() { 
      return true; 
     } 

    }} 
1

答案這是我第stackoverflow.com -answer。

今天我一直在努力解決這個問題,並且嘗試了以前的文章中提供的解決方案。

評論「if」條款確實解決了問題,但我相信這不是一個推薦的解決方案。如此ListView視頻(http://www.youtube.com/watch?v=wDBM6wVEO70)中所述,重新使用convertView對於處理大型數據集至關重要。

我的解決方案非常簡單,它在我的情況下非常完美。我從前面提到的視頻中獲得了這個想法:

public View getGroupView(int groupPosition, boolean isExpanded, 
      View convertView, ViewGroup parent)  { 

     // 1. Step: check if convertView can be re-used or if it should be created. 

     if (convertView == null) { 

       // create the view or inflate the view from xml here 
       // Note: inlating is expensive process, so do it only if needed 
       //  (it's needed when convertView can not be re-used) 
       // 
       // TODO: your code here 

     } 

     // 2. Step: populate the convertView with correct data. 
     // Correct data can be accessed through groupPosition. 
     // 
     // TODO: your code here 

     return convertView; 
    } 

我相信這個問題中提供的代碼中沒有第二步?

我希望這可以幫助有這個問題的人。

  • 圖奧馬斯