2017-03-03 2 views
1

오케이, 여기 내 문제가 있습니다. 확장 가능한 ListView 및 사용자 지정 어댑터가 있습니다. 나는 2 개의 다른 자식 viewTypes (하나는 스위치와 하나가없는)를 처리하도록 어댑터를 설정할 수있었습니다. ViewHolder를 사용하여 뷰를 관리하고 있습니다.ExpandableListView (안드로이드) : 여러 viewTypes - 그들을 통해 데이터를 전달하는 onClickListener?

내가 고민하고있는 것은 스위치가있는 viewType에서 스위치없이 viewType에 영향을주는 방법입니다. 특히 스위치가있는 viewType은 각 그룹의 시작 부분에 나타나는 childHeader입니다. 사용자가 스위치를 토글하면 그룹의 나머지 자식 텍스트의 색을 변경하고 행의 선택을 비활성화 할 수 있기를 원합니다.

토글은 rowType 0에서 확장되기 때문에 동일한 viewType 내에 존재하는 다른 뷰만 볼 수 있습니다.

추가 : zero viewType의 토글 스위치를 통해 이러한 업데이트가 필요합니다. 따라서 사용자가 전환을 전환하면 모든보기가 영향을받습니다.

이 활동에서해야 할 일이 있습니까?

이 작업을 수행하는 방법에 대한 아이디어는 제 3 자 라이브러리를 사용하기위한 제안이 아닙니다.

출력 예 :

어댑터 코드 :

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; 
     } 
    }); 
} 

enter image description here

아래의 샘플 코드를 참조하십시오}

+0

어댑터에는 SparseArray 필드를 유지하십시오. viewHolder.childHeaderToggle의 groupPosition 값을 태그 (정수 값)로 전달하십시오. 스위치의 리스너에서 위의 SparseArray를 사용하고 스위치의 상태를 저장합니다. * sparseArray.put (Integer) cb.getTag(), cb.isChecked()) *. 그런 다음 getChildView() 메서드를 수정하여 * if (childPosition == 0) {... *에 * else * 절을 추가하면이 그룹의 스위치 상태를 가져 와서 원하는대로 다른 행을 수정할 수 있습니다. * 부울 switchStatus = sparseArray.valueAt (groupPosition); ... * – Luksprog

+0

빠른 응답 주셔서 감사 Luksprog. 귀하가 제안한 것을 정확히 이해하면 0이 아닌 행의 뷰는 변경되지만 onClickListener를 통해 변경되지는 않습니다.스위치가 전환되면 값을 업데이트해야합니다. 죄송합니다. 좀 더 구체적이어야 했었습니다. 간단한 set() 및 get() 메서드를 사용하여 값을 변경할 수있었습니다. 문제는 그룹을 다시 열지 않는 한 텍스트 색상이 업데이트되지 않는다는 것입니다 (getView가 다시 호출 될 때). (그건 내 원래 게시물에 포함되지 않은 것에 대한 내 잘못이었습니다.) 미안합니다. –

+0

원래의 게시물에 onClickListener를 포함하도록 업데이트했습니다. –

답변

0

오케이. 여기에 스위치 리스너 내부에서 notifyDataSetChanged()를 사용하여 생각해 낸 해결책이 있습니다. Luksprog는 viewTypes 사이에서 값을 전달하기위한 좋은 (아마도 더 적절한) 솔루션을 가지고 있었지만이 프로젝트의 테스트 버전에서 가지고 있던 set() get() 메서드를 사용했다. 여기

업데이트 된 어댑터 코드입니다 : 이

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; 
} 

}

활동 (setChildtoggleCheckedState()와 getChildToggleCheckedState() 메소드뿐만 아니라 내가 notifyDataSetChanged()를 넣을 경우 등에 특히주의) 이 일을하기 위해 바뀌지 않았다.

관련 문제