2

我想在我的應用程序中創建ExpandableListView。它有兩組:第一組是顏色,第二組是符號。第一組點擊工作正常。然而,第二組顯示來自第一組的行(如果第二組中有更多項目,那麼'額外'項目將是正確的)。如何使用Viewholder和ExpandableListView?

例如,讓我們說的「顏色」是白色,黑色,紅色和藍色,而符號「/」和「」。

如果我開始活動並單擊顏色,則它們顯示正確。如果我點擊'符號',我會看到白色和黑色。

如果我點擊「符號」第一,那麼,我認爲「/」和「‘但是當我然後點擊顏色我看到‘/’,’。」,紅,藍。

我在網上搜索,並建立了我需要使用ViewHolders,以避免重複使用相同的看法時,我改變組。儘管如此,我還是無法實現它。起初它沒有任何區別,當我點擊第二組時,當前版本崩潰了。我認爲問題的一部分是我爲每個組別設置了不同的子佈局(即符號顯示與顏色不同)。

目前這裏是我已(我已經證明我的想法是相關的位;如果我漏掉了什麼重要的東西,我可以將它添加):

public class ColourSymbolKeyAdapter extends BaseExpandableListAdapter { 

    private Context context; 
    private HashMap<String, List<KeyItem>> childDataSource; 
    private List<String> parentDataSource; 

    public ColourSymbolKeyAdapter(Context context, 
            List<String> childParent, 
            HashMap<String, List<KeyItem>> child) { 

     this.context = context; 
     this.parentDataSource = childParent; 
     this.childDataSource = child; 
    } 

... Left out various override functions ... 

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

     View v = convertView; 
     GroupViewHolder holder; 

     if(v == null) { 
      LayoutInflater inflater = 
        (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = inflater.inflate(R.layout.expandablelist_parent, parent, false); 
      holder = new GroupViewHolder(); 

      holder.mGroupName = (TextView) v.findViewById(R.id.textViewParent); 
      v.setTag(holder); 
     }else { 
      holder = (GroupViewHolder) v.getTag(); 
     } 

     String parentHeader = (String) getGroup(groupPosition); 
     holder.mGroupName.setText(parentHeader); 
     return v; 
    } 

    @Override 
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { 

     View row = convertView; 
     KeyItem childItem = (KeyItem) getChild(groupPosition, childPosition); 
     ColourViewHolder colourviewholder; 
     SymbolViewHolder symbolviewholder; 

     LayoutInflater inflater = 
       (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

     if(childItem.getPatternColour() == null) { // This is a symbol row 

      if(row == null) { 
       symbolviewholder = new SymbolViewHolder(); 
       row = inflater.inflate(R.layout.expandablelist_child_symbol, parent, false); 
       symbolviewholder.mChildName = (TextView) row.findViewById(R.id.symbol_desc); 
       symbolviewholder.mSymbolCell = (SymbolCell) row.findViewById(R.id.symbol_cell); 
       row.setTag(symbolviewholder); 
      }else { 
       symbolviewholder = (SymbolViewHolder) row.getTag(); 
      } 

      String drawableName = childItem.getPatternSymbol().getDrawable(); 
      final int resourceId = context.getResources().getIdentifier(drawableName, "drawable", context.getPackageName()); 
      Drawable drawable; 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       drawable = context.getResources().getDrawable(resourceId, context.getTheme()); 
      } else { 
       drawable = context.getResources().getDrawable(resourceId); 
      } 

      symbolviewholder.mSymbolCell.setDrawable(drawable); 
      symbolviewholder.mChildName.setText(childItem.getPatternSymbol().getSymbolDescription()); 

     }else { // This is a colour row 
      if(row == null) { 
       colourviewholder = new ColourViewHolder(); 
       row = inflater.inflate(R.layout.expandablelist_child_colour, parent, false); 
       colourviewholder.mChildName = (TextView) row.findViewById(R.id.colour_name); 
       colourviewholder.mChildDesc = (TextView) row.findViewById(R.id.colour_desc); 
       colourviewholder.mColourCell = (ColourCell) row.findViewById(R.id.colour_cell); 
       row.setTag(colourviewholder); 
      }else { 
       colourviewholder = (ColourViewHolder) row.getTag(); 
      } 

      colourviewholder.mColourCell.setColour(childItem.getPatternColour()); 
      colourviewholder.mChildName.setText(childItem.getPatternColour().getName()); 
      colourviewholder.mChildDesc.setText(childItem.getPatternColour().getDescription()); 
     } 

     return row; 
    } 

    public final class GroupViewHolder { 

     TextView mGroupName; 
    } 

    public final class ColourViewHolder { 

     ColourCell mColourCell; 
     TextView mChildName, mChildDesc; 
    } 

    public final class SymbolViewHolder { 

     SymbolCell mSymbolCell; 
     TextView mChildName; 
    } 
} 

佈局父( expandablelist_parent.xml):

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/parentView"> 

    <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:id="@+id/textViewParent" 
     android:textColor="#000000" 
     android:textAppearance="@style/ParagraphBold"> 
    </TextView> 

</LinearLayout> 

佈局的顏色行(expandablelist_child_colour.xml):

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:padding="@dimen/small_padding" 
    android:id="@+id/childViewColour" 
    android:orientation="horizontal"> 

    <com.myname.appname.ColourCell xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="@dimen/grid_cell_column_width" 
     android:layout_height="@dimen/grid_cell_column_width" 
     android:id="@+id/colour_cell" 
     android:layout_marginRight="@dimen/small_padding" /> 

    <LinearLayout 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:orientation="vertical"> 

     <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textAppearance="@style/ParagraphBold" 
      android:textColor="@color/colorPrimaryDark" 
      android:id="@+id/colour_name"> 
     </TextView> 

     <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textAppearance="@style/Paragraph" 
      android:textColor="@color/colorPrimaryDark" 
      android:id="@+id/colour_desc"> 
     </TextView> 

    </LinearLayout> 

</LinearLayout> 

和用於符號行(expandablelist_child_symbol.xml):

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/childViewSymbol" 
    android:padding="@dimen/small_padding"> 

    <com.myname.appname.SymbolCell xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="@dimen/grid_cell_column_width" 
     android:layout_height="@dimen/grid_cell_column_width" 
     android:textAppearance="@style/Paragraph" 
     android:id="@+id/symbol_cell" 
     android:layout_marginRight="@dimen/small_padding" /> 

    <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:textColor="@color/colorPrimaryDark" 
     android:id="@+id/symbol_desc"> 
    </TextView> 

</LinearLayout> 

如果單擊「顏色」第一組,然後將「符號」基團,它崩潰出來就行:symbolviewholder =(SymbolViewHolder)行.getTag();

我真的很感激任何幫助。謝謝!

+0

您能添加一部分異常的堆棧跟蹤嗎? –

+0

嘗試每次都使用新的行視圖,不要檢查如果row == null並且每次都創建新行並檢查 – Vickyexpert

+0

@Vickyexpert每次創建一個新行都會禁用視圖回收,這是不好的。它也使ViewHolders無用。 – BladeCoder

回答

1

由於您有2個不同的子佈局,因此您需要覆蓋getChildTypeCount()getChildType(),以便適配器將收到適當的視圖類型以供重用。否則,在某些情況下,當您嘗試檢索您的ViewHolder時,您將收到ClassCastException

@Override 
public int getChildTypeCount() { 
    return 2; 
} 

@Override 
public int getChildType(int groupPosition, int childPosition) { 
    KeyItem childItem = (KeyItem) getChild(groupPosition, childPosition); 
    return (childItem.getPatternColour() == null) ? 0 : 1; 
} 

有關更多信息,請參見HeterogeneousExpandableList文檔。

+0

謝謝。我會試試這個 - 給它賞金,因爲它指向我有助於理解的文檔。目前我無法嘗試,因爲我有adb調試橋接的麻煩,但是想要在賞金過期之前授予獎勵。 – Sharon

+1

謝謝,讓我知道它是否適用於您或您需要更多信息。 – BladeCoder

+0

它工作!謝謝!現在也更有意義了! – Sharon

1

你可以用這個library輕鬆實現它,有一個完整的例子here

基本上你組你的項目分爲幾個部分:

class MySection extends StatelessSection { 

    String header; 
    List<String> list; 
    boolean expanded = true; 

    public MySection(String header, List<String> list) { 
     // call constructor with layout resources for this Section header and items 
     super(R.layout.section_header, R.layout.section_item); 
     this.myHeader = header; 
     this.myList = list; 
    } 

    @Override 
    public int getContentItemsTotal() { 
     return expanded? list.size() : 0; 
    } 

    @Override 
    public RecyclerView.ViewHolder getHeaderViewHolder(View view) { 
     return new HeaderViewHolder(view); 
    } 

    @Override 
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) { 
     final HeaderViewHolder headerHolder = (HeaderViewHolder) holder; 

     headerHolder.tvTitle.setText(title); 

     headerHolder.rootView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       expanded = !expanded; 
       headerHolder.imgArrow.setImageResource(
         expanded ? R.drawable.ic_keyboard_arrow_up_black_18dp : R.drawable.ic_keyboard_arrow_down_black_18dp 
       ); 
       sectionAdapter.notifyDataSetChanged(); 
      } 
     }); 
    } 

    @Override 
    public RecyclerView.ViewHolder getItemViewHolder(View view) { 
     // return a custom instance of ViewHolder for the items of this section 
     return new MyItemViewHolder(view); 
    } 

    @Override 
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) { 
     MyItemViewHolder itemHolder = (MyItemViewHolder) holder; 

     // bind your view here 
     itemHolder.tvItem.setText(list.get(position)); 
    } 
} 

然後創建您的部分實例,並設置你的適配器:

// Create an instance of SectionedRecyclerViewAdapter 
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter(); 

// Add your Sections 
sectionAdapter.addSection(new MySection("Colours", Arrays.asList(new String[] {"white", "red", "black", "blue" }))); 
sectionAdapter.addSection(new MySection("Symbols", Arrays.asList(new String[] {"/", "." }))); 

// Set up your RecyclerView with the SectionedRecyclerViewAdapter 
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); 
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 
recyclerView.setAdapter(sectionAdapter); 
1

試試這個library。你可以repalce ExpandableListView