EditText 转到 ExpandableListView 上的另一个 child

EditText goes to another child on ExpandableListView

你好有可扩展的列表视图,每个 header 展开时只有一个 child,里面有一些 EditText。问题是当我扩展一个 header 并在编辑文本上放置一些东西时,当我扩展另一个 header 时,我放置的值会转到原始值的另一个 child。我知道 ListViews 在滚动时会重用视图,我放了 ViewHolders,但我无法让它工作。

这是我的 CustomAdapter 代码:

public class ExpandableListAddDataAdapter extends BaseExpandableListAdapter {

private Context _context;
private List<String> _listDataHeader = new ArrayList<>(); // header titles
private Date sportsDate, medsDate, glucoseDate, mealDate, auxDate;

public  ExpandableListAddDataAdapter(Context context, List<String> listDataHeader) {
    this._context = context;
    this._listDataHeader = listDataHeader;
    this.sportsDate = new Date(1900,1,1);
    this.medsDate = new Date(1900,1,1);
    this.glucoseDate = new Date(1900,1,1);
    this.mealDate = new Date(1900,1,1);
    this.auxDate = new Date(1900,1,1);
}

@Override
public String[] getChild(int groupPosition, int childPosititon) {
    return null;
}


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

@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
    final ChildViewHolder holder;
    View row = convertView;

    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = infalInflater.inflate(R.layout.expandable_data_add_child, parent,false);
        holder = new ChildViewHolder(row);
        row.setTag(holder);
    }else{
        holder = (ChildViewHolder) row.getTag();
    }

    this.auxDate = new Date(1900,1,1);
    switch (groupPosition){
        case 0:
            auxDate = new Date(this.glucoseDate.getTime());
            break;
        case 1:
            auxDate = new Date(this.mealDate.getTime());
            break;
        case 2:
            auxDate = new Date(this.sportsDate.getTime());
            break;
        case 3:
            auxDate = new Date(this.medsDate.getTime());
            break;
    }


    final View finalConvertView = row;
    holder.txtDate.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int mYear, mMonth, mDay;
            if(auxDate.getYear() != 1900){
                mYear = auxDate.getYear();
                mMonth = auxDate.getMonth();
                mDay = auxDate.getDay();
            }else{
                Calendar mcurrentDate = Calendar.getInstance();
                mYear = mcurrentDate.get(Calendar.YEAR);
                mMonth = mcurrentDate.get(Calendar.MONTH);
                mDay = mcurrentDate.get(Calendar.DAY_OF_MONTH);
            }

            DatePickerDialog mDatePicker = new DatePickerDialog(finalConvertView.getContext(), new DatePickerDialog.OnDateSetListener() {
                @Override
                public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                    auxDate.setYear(year - 1900);
                    auxDate.setMonth(monthOfYear);
                    auxDate.setDate(dayOfMonth);
                    if (dayOfMonth < 10) {
                        holder.txtDate.setText(0 + dayOfMonth + "/" + (monthOfYear + 1) + "/" + year);
                    } else {
                        holder.txtDate.setText(dayOfMonth + "/" + (monthOfYear + 1) + "/" + year);
                    }
                    switch (groupPosition){
                        case 0:
                            glucoseDate = new Date(auxDate.getTime());
                            break;
                        case 1:
                            mealDate = new Date(auxDate.getTime());
                            break;
                        case 2:
                            sportsDate = new Date(auxDate.getTime());
                            break;
                        case 3:
                            medsDate = new Date(auxDate.getTime());
                            break;
                    }
                }
            }, mYear, mMonth, mDay);
            mDatePicker.show();
        }
    });
    holder.txtTime.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int mHour, mMinute;
            if(auxDate.getHours() != 0){
                mHour = auxDate.getHours();
                mMinute = auxDate.getMinutes();
            }else{
                Calendar mcurrentDate = Calendar.getInstance();
                mHour = mcurrentDate.get(Calendar.HOUR_OF_DAY);
                mMinute = mcurrentDate.get(Calendar.MINUTE);
            }

            TimePickerDialog mTimePicker = new TimePickerDialog(finalConvertView.getContext(), new TimePickerDialog.OnTimeSetListener() {
                @Override
                public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                    auxDate.setHours(hourOfDay);
                    auxDate.setMinutes(minute);
                    if (minute < 10) {
                        holder.txtTime.setText(hourOfDay + ":" + 0 + minute);
                    } else {
                        holder.txtTime.setText(hourOfDay + ":" + minute);
                    }
                    switch (groupPosition){
                        case 0:
                            glucoseDate = auxDate;
                            break;
                        case 1:
                            mealDate = auxDate;
                            break;
                        case 2:
                            sportsDate = auxDate;
                            break;
                        case 3:
                            medsDate = auxDate;
                            break;
                    }
                }
            }, mHour, mMinute, false);
            mTimePicker.show();
        }
    });
    return row;
}

@Override
public int getChildrenCount(int groupPosition) {
    return 1;
}

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

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

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

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    final HeaderViewHolder holder;
    View row = convertView;
    String headerTitle = (String) getGroup(groupPosition);
    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = infalInflater.inflate(R.layout.expandable_data_add_header, parent,false);
        holder = new HeaderViewHolder(row);
        row.setTag(holder);
    }else{
        holder = (HeaderViewHolder) row.getTag();
    }
    if (isExpanded) {
        holder.expandIndicator.setImageResource(R.drawable.minus);
    } else {
        holder.expandIndicator.setImageResource(R.drawable.plus);
    }
    holder.txtHeader.setTypeface(null, Typeface.BOLD);
    holder.txtHeader.setText(headerTitle);

    return row;
}

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

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

private static class ChildViewHolder {
    EditText txtDate;
    EditText txtTime;
    EditText txtGlucose;
    ChildViewHolder(View v)
    {
        txtDate = (EditText) v.findViewById(R.id.input_event_date);
        txtTime = (EditText) v.findViewById(R.id.input_event_time);
        txtGlucose = (EditText) v.findViewById(R.id.input_glucose);

    }
}

private static class HeaderViewHolder {
    TextView txtHeader;
    ImageView expandIndicator;

    HeaderViewHolder(View v)
    {
        txtHeader = (TextView) v.findViewById(R.id.expandable_add_data_header_text);
        expandIndicator = (ImageView) v.findViewById(R.id.expandable_add_data_header_icon);

    }
  }
}

这是我遇到的问题的一些截图

The first header expanded with the edittext

Second header expanded and the value of the firt edittext goes to the second header child

我终于找到了解决办法。解决方案是为每个 EditText 添加一个 TextWatcher,如下所示:

holder.position = groupPosition;
    holder.txtGlucose.setText(arrInput[groupPosition]);
    holder.txtGlucose.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            // TODO Auto-generated method stub

        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                      int arg3) {
            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub
            arrInput[holder.position] = arg0.toString();
        }
    });

其中 arrInput 是一个字符串[],我在其中存储此 EditText 的值