2017-03-03 48 views
1

好的,这是我的问题。我有一个expandableListView和自定义适配器。我能够设置适配器来处理2个不同的子视图类型(一个带有开关,另一个没有)。我也使用ViewHolder来管理视图。ExpandableListView(Android):多个viewTypes - 通过onClickListener在它们之间传递数据?

我正在努力的是如何在没有从具有开关的viewType切换的情况下影响viewType。具体来说,带开关的viewType是一个childHeader,它出现在每个组的开头。当用户切换开关时,我希望能够更改组中其余子项的文本颜色(并禁止选择该行)。

因为切换是在rowType零中膨胀的,所以它只能看到存在于相同viewType中的其他视图。

此外:我需要这些更新通过零视图类型中的切换开关发生。所以当用户切换开关时,所有的视图都会受到影响。

这是我需要在活动中做的事吗?

任何想法如何做到这一点将不胜感激(请不要使用第三方库的建议)。

输出例如:

enter image description here

请参阅下面的示例代码:

适配器代码:

public class NavDrawerExpandableListAdapter extends BaseExpandableListAdapter { 

    private static final int CHILD_HEADER = 0; 
    private static final int CHILD_LINE_ITEM = 1; 

    private Context context; 
    private List<String> expandableListTitle; 
    private HashMap<String, List<String>> expandableListDetail; 

    private final Set<Pair<Long, Long>> mToggleSwitchedItems = new HashSet<Pair<Long, Long>>(); 

    public NavDrawerExpandableListAdapter(Context context, List<String> expandableListTitle, 
              HashMap<String, List<String>> expandableListDetail) { 
     this.context = context; 
     this.expandableListTitle = expandableListTitle; 
     this.expandableListDetail = expandableListDetail; 
    } 

    //view holder class to store our textView 
    private class ViewHolder { 
     TextView textView; 
     Switch childHeaderToggle; 
    } 

    //number of different types of views we're gonna inflate for the children 
    @Override 
    public int getChildTypeCount() { 
     return 2; 
    } 

    //specify which viewType to inflate in the getView method 
    @Override 
    public int getChildType (int groupPosition, int childPosition) { 
     switch(childPosition) { 
      case 0: 
       return CHILD_HEADER; 
      default: 
       return CHILD_LINE_ITEM; 
     } 
    } 

    @Override 
    public Object getChild(int groupPosition, int childPosition) { 
     return this.expandableListDetail.get(this.expandableListTitle.get(groupPosition)) 
       .get(childPosition); 
    } 

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

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

     //declare our view and viewholder objects 
     View view = convertView; 
     ViewHolder viewHolder; 
     String expandedListText; 

     //define childType 
     int childType = getChildType(groupPosition, childPosition); 
     //define the toggleTag position 
     Pair<Long, Long> childHeaderToggleTag = new Pair<Long, Long>(getGroupId(groupPosition), getChildId(groupPosition, childPosition)); 

     if (convertView == null) { 
      viewHolder = new ViewHolder(); 
      switch (childType) { 
       case CHILD_HEADER: 
        //inflate our layout and textview then setTag viewholder if the view is null 
        view = LayoutInflater.from(context).inflate(R.layout.navdrawer_list_item_header, null); 
        viewHolder.textView = (TextView) view.findViewById(R.id.expandedListItemChildHeader); 
        viewHolder.childHeaderToggle = (Switch) view.findViewById(R.id.toggle_allDevices); 
        viewHolder.textView.setText("All Teams"); 
        break; 
       case CHILD_LINE_ITEM: 
        expandedListText = (String) getChild(groupPosition, childPosition - 1); 
        //inflate our layout and textview then setTag viewholder if the view is null 
        view = LayoutInflater.from(context).inflate(R.layout.navdrawer_list_item, null); 
        viewHolder.textView = (TextView) view.findViewById(R.id.expandedListItem); 
        viewHolder.textView.setText(expandedListText); 
        break; 
       default: 
        expandedListText = (String) getChild(groupPosition, childPosition - 1); 
        //inflate our layout and textview then setTag viewholder if the view is null 
        view = LayoutInflater.from(context).inflate(R.layout.navdrawer_list_item, null); 
        viewHolder.textView = (TextView) view.findViewById(R.id.expandedListItem); 
        viewHolder.textView.setText(expandedListText); 
        break; 
      } 
      view.setTag(viewHolder); 
     } 
     else { 
      //otherwise if the view exists then gettag() our saved view 
      viewHolder = (ViewHolder) view.getTag(); 
     } 

     //control the state of the child header toggle switch 
     if (childPosition == 0) { 
      viewHolder.childHeaderToggle.setTag(childHeaderToggleTag); 
      // set switched on if groupId/childId is in switched list 
      viewHolder.childHeaderToggle.setChecked(mToggleSwitchedItems.contains(childHeaderToggleTag)); 
      // set OnClickListener to handle checked switches 
      viewHolder.childHeaderToggle.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View v) { 
        final Switch cb = (Switch) v; 
        final Pair<Long, Long> tag = (Pair<Long, Long>) v.getTag(); 
        if (cb.isChecked()) { 
         mToggleSwitchedItems.add(tag); 
        } else { 
         mToggleSwitchedItems.remove(tag); 
        } 
       } 
      }); 
     } 

     return view; 
    } 

    @Override 
    public int getChildrenCount(int listPosition) { 
     return (this.expandableListDetail.get(this.expandableListTitle.get(listPosition)) 
       .size() + 1); 
    } 

    @Override 
    public Object getGroup(int listPosition) { 
     return this.expandableListTitle.get(listPosition); 
    } 

    @Override 
    public int getGroupCount() { 
     return this.expandableListTitle.size(); 
    } 

    @Override 
    public long getGroupId(int listPosition) { 
     return listPosition; 
    } 

    @Override 
    public View getGroupView(int listPosition, boolean isExpanded, 
          View convertView, ViewGroup parent) { 
     String listTitle = (String) getGroup(listPosition); 
     if (convertView == null) { 
      LayoutInflater layoutInflater = (LayoutInflater) this.context. 
        getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = layoutInflater.inflate(R.layout.navdrawer_list_group, null); 
     } 
     TextView listTitleTextView = (TextView) convertView 
       .findViewById(R.id.listTitle); 
     listTitleTextView.setTypeface(null, Typeface.BOLD); 
     listTitleTextView.setText(listTitle); 
     return convertView; 
    } 

    @Override 
    public boolean hasStableIds() { 
     return false; 
    } 

    @Override 
    public boolean isChildSelectable(int listPosition, int expandedListPosition) { 
     return true; 
    } 
} 

MainActivity:

public class MainActivity extends AppCompatActivity { 

ExpandableListView expandableListView; 
NavDrawerExpandableListAdapter expandableListAdapter; 
List<String> expandableListTitle; 
HashMap<String, List<String>> expandableListDetail; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    expandableListView = (ExpandableListView) findViewById(R.id.expandableListView); 
    expandableListDetail = ExpandableListDataPump.getData(); 
    expandableListTitle = new ArrayList<String>(expandableListDetail.keySet()); 
    expandableListAdapter = new NavDrawerExpandableListAdapter(this, expandableListTitle, expandableListDetail); 
    expandableListView.setAdapter(expandableListAdapter); 

    expandableListView.setChoiceMode(expandableListView.CHOICE_MODE_SINGLE); 

    expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { 
     //initialize int var 
     int previousGroup = 0; 

     @Override 
     public void onGroupExpand(int groupPosition) { 
      //this conditional enables only one drop down group to open at a time 
      if(groupPosition != previousGroup) 
       expandableListView.collapseGroup(previousGroup); 
      previousGroup = groupPosition; 

      Toast.makeText(getApplicationContext(), 
        expandableListTitle.get(groupPosition) + " List Expanded.", 
        Toast.LENGTH_SHORT).show(); 
     } 
    }); 

    expandableListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() { 

     @Override 
     public void onGroupCollapse(int groupPosition) { 

      Toast.makeText(getApplicationContext(), 
        expandableListTitle.get(groupPosition) + " List Collapsed.", 
        Toast.LENGTH_SHORT).show(); 
     } 
    }); 

    expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { 

     @Override 
     public boolean onChildClick(ExpandableListView parent, View v, 
            int groupPosition, int childPosition, long id) { 

      if (childPosition == 0) { 
       Toast.makeText(
         getApplicationContext(), 
         "All Teams", Toast.LENGTH_SHORT 
       ).show(); 
      } 
      else { 

       Toast.makeText(
         getApplicationContext(), 
         expandableListTitle.get(groupPosition) 
           + " -> " 
           + expandableListDetail.get(
           expandableListTitle.get(groupPosition)).get(
           childPosition - 1), Toast.LENGTH_SHORT 
       ).show(); 
      } 

      return false; 
     } 
    }); 
} 

}

+0

在您的适配器中保留一个SparseArray 字段。将groupPosition值作为viewHolder.childHeaderToggle的标记(Integer值)传递。在交换机的监听器中,使用上面的SparseArray并将交换机的状态:* sparseArray.put((Integer)cb.getTag(),cb.isChecked())*。然后进一步修改getChildView()方法,将* else *子句添加到* if(childPosition == 0){... *,您可以根据需要修改其他行,方法是获取此组的开关状态: *布尔switchStatus = sparseArray.valueAt(groupPosition); ... * – Luksprog

+0

感谢您的快速反应Luksprog。如果我正确理解你的建议,那么除零以外的行中的视图将被更改,但它们不会通过onClickListener更改。我需要在交换机切换时更新这些值。对不起,也许我应该更具体一些,我可以通过使用简单的set()和get()方法来改变值。问题在于文字颜色不会更新,除非我重新打开组(这是getView被再次调用的时候)。 (这是我的错,因为没有在我的原始文章中包括这个 - 对此很抱歉) –

+0

更新后的原始文章包含onClickListener –

回答

0

好的。以下是我在交换机侦听器中使用notifyDataSetChanged()的解决方案。 Luksprog为viewTypes之间传递值提供了一个很好的(也许更合适的)解决方案,但是我使用了我在这个项目的测试版本中使用的set()get()方法。

下面是更新适配器代码: (要特别注意setChildtoggleCheckedState()和getChildToggleCheckedState()方法,以及在哪里我把notifyDataSetChanged())

public class NavDrawerExpandableListAdapter extends BaseExpandableListAdapter { 

private static final int CHILD_HEADER = 0; 
private static final int CHILD_LINE_ITEM = 1; 

private Context context; 
private List<String> expandableListTitle; 
private HashMap<String, List<String>> expandableListDetail; 

private final Set<Pair<Long, Long>> mToggleSwitchedItems = new HashSet<Pair<Long, Long>>(); 

public NavDrawerExpandableListAdapter(Context context, List<String> expandableListTitle, 
             HashMap<String, List<String>> expandableListDetail) { 
    this.context = context; 
    this.expandableListTitle = expandableListTitle; 
    this.expandableListDetail = expandableListDetail; 
} 

//set the toggle switch state of the child header so we can access it in other layouts 
private void setChildToggleCheckedState(boolean state) { 
    this.childToggleHeaderState = state; 
} 

//get the toggle switch state of the child header toggle so we can access it in other layouts 
public boolean getChildToggleCheckedState() { 
    return childToggleHeaderState; 
} 

//view holder class to store our textView 
private class ViewHolder { 
    TextView textView; 
    Switch childHeaderToggle; 
} 

//number of different types of views we're gonna inflate for the children 
@Override 
public int getChildTypeCount() { 
    return 2; 
} 

//specify which viewType to inflate in the getView method 
@Override 
public int getChildType (int groupPosition, int childPosition) { 
    switch(childPosition) { 
     case 0: 
      return CHILD_HEADER; 
     default: 
      return CHILD_LINE_ITEM; 
    } 
} 

@Override 
public Object getChild(int groupPosition, int childPosition) { 
    return this.expandableListDetail.get(this.expandableListTitle.get(groupPosition)) 
      .get(childPosition); 
} 

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

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

    //declare our view and viewholder objects 
    View view = convertView; 
    ViewHolder viewHolder; 
    String expandedListText; 

    //define childType 
    int childType = getChildType(groupPosition, childPosition); 
    //define the toggleTag position 
    Pair<Long, Long> childHeaderToggleTag = new Pair<Long, Long>(getGroupId(groupPosition), getChildId(groupPosition, childPosition)); 

    if (convertView == null) { 
     viewHolder = new ViewHolder(); 
     switch (childType) { 
      case CHILD_HEADER: 
       //inflate our layout and textview then setTag viewholder if the view is null 
       view = LayoutInflater.from(context).inflate(R.layout.navdrawer_list_item_header, null); 
       viewHolder.textView = (TextView) view.findViewById(R.id.expandedListItemChildHeader); 
       viewHolder.childHeaderToggle = (Switch) view.findViewById(R.id.toggle_allDevices); 
       break; 
      case CHILD_LINE_ITEM: 
       expandedListText = (String) getChild(groupPosition, childPosition - 1); 
       //inflate our layout and textview then setTag viewholder if the view is null 
       view = LayoutInflater.from(context).inflate(R.layout.navdrawer_list_item, null); 
       viewHolder.textView = (TextView) view.findViewById(R.id.expandedListItem); 
       viewHolder.textView.setText(expandedListText); 
       break; 
      default: 
       expandedListText = (String) getChild(groupPosition, childPosition - 1); 
       //inflate our layout and textview then setTag viewholder if the view is null 
       view = LayoutInflater.from(context).inflate(R.layout.navdrawer_list_item, null); 
       viewHolder.textView = (TextView) view.findViewById(R.id.expandedListItem); 
       viewHolder.textView.setText(expandedListText); 
       break; 
     } 
     view.setTag(viewHolder); 
    } 
    else { 
     //otherwise if the view exists then gettag() our saved view 
     viewHolder = (ViewHolder) view.getTag(); 
    } 

    //control the state of the child header toggle switch 
    if (childPosition == 0) { 
     viewHolder.childHeaderToggle.setTag(childHeaderToggleTag); 
     // set switched on if groupId/childId is in switched list 
     viewHolder.childHeaderToggle.setChecked(mToggleSwitchedItems.contains(childHeaderToggleTag)); 
     setChildToggleCheckedState(mToggleSwitchedItems.contains(childHeaderToggleTag)); 

     //depending on toggle state set our child header text colors 
     if (!getChildToggleCheckedState()) { 
      viewHolder.textView.setTextColor(ContextCompat.getColor(context, R.color.navDrawerInactiveText)); 
     } 
     else { 
      viewHolder.textView.setTextColor(ContextCompat.getColor(context, R.color.navDrawerDisabledText)); 
     } 

     // set OnClickListener to handle checked switches 
     viewHolder.childHeaderToggle.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       final Switch cb = (Switch) v; 
       final Pair<Long, Long> tag = (Pair<Long, Long>) v.getTag(); 
       if (cb.isChecked()) { 
       setChildToggleCheckedState(true); 
        mToggleSwitchedItems.add(tag); 
       } else { 
       setChildToggleCheckedState(false); 
        mToggleSwitchedItems.remove(tag); 
       } 
       //update our list when switch toggled 
       notifyDataSetChanged(); 
      } 
     }); 
     //set the text for our child header here 
     viewHolder.textView.setText("All Teams"); 
    } 
    else { 

     //depending on toggle state set our remaining text colors 
     if (!getChildToggleCheckedState()) { 
      viewHolder.textView.setTextColor(ContextCompat.getColor(context, R.color.navDrawerInactiveText)); 
     } 
     else { 
      viewHolder.textView.setTextColor(ContextCompat.getColor(context, R.color.navDrawerDisabledText)); 
     } 


     //set our text for all remaining children 
     expandedListText = (String) getChild(groupPosition, childPosition - 1); 
     viewHolder.textView.setText(expandedListText); 
    } 

    return view; 
} 

@Override 
public int getChildrenCount(int listPosition) { 
    return (this.expandableListDetail.get(this.expandableListTitle.get(listPosition)) 
      .size() + 1); 
} 

@Override 
public Object getGroup(int listPosition) { 
    return this.expandableListTitle.get(listPosition); 
} 

@Override 
public int getGroupCount() { 
    return this.expandableListTitle.size(); 
} 

@Override 
public long getGroupId(int listPosition) { 
    return listPosition; 
} 

@Override 
public View getGroupView(int listPosition, boolean isExpanded, 
         View convertView, ViewGroup parent) { 
    String listTitle = (String) getGroup(listPosition); 
    if (convertView == null) { 
     LayoutInflater layoutInflater = (LayoutInflater) this.context. 
       getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = layoutInflater.inflate(R.layout.navdrawer_list_group, null); 
    } 
    TextView listTitleTextView = (TextView) convertView 
      .findViewById(R.id.listTitle); 
    listTitleTextView.setTypeface(null, Typeface.BOLD); 
    listTitleTextView.setText(listTitle); 
    return convertView; 
} 

@Override 
public boolean hasStableIds() { 
    return false; 
} 

@Override 
public boolean isChildSelectable(int listPosition, int expandedListPosition) { 
    return true; 
} 

}

的活动没有改变做这项工作。

相关问题