Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EditText content inside ExpandableListView disappear when clicking next ExpandableListView header

I have an edittext inside an expandablelistview item child. Then, I entered a text inside this edittext, but whenever I click other expandablelistview header, the text I entered disappear.

I already used android:windowSoftInputMode="adjustPan" inside my Manifest.xml and many other possible fixes, but didn't work.

this is my adapter:

public class ExpendableAdapter extends BaseExpandableListAdapter {
    private Context _context;
    private List<String> _listDataHeader;
    private HashMap<String, List<ExpandItemModel>> _listDataChild;

public ExpendableAdapter(Context context, List<String> listDataHeader,
                             HashMap<String, List<ExpandItemModel>> listChildData) {
    this._context = context;
    this._listDataHeader = listDataHeader;
    this._listDataChild = listChildData;
}

@Override
public Object getChild(int groupPosition, int childPosititon) {
    return this._listDataChild.get(this._listDataHeader.get(groupPosition))
            .get(childPosititon);
}

@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 ExpandItemModel childText = (ExpandItemModel) getChild(groupPosition, childPosition);

    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.list_item, null);
    }

    final EditText etTotal = (EditText)convertView
            .findViewById(R.id.et_total);

    etTotal.setText(childText.getTotal);

    return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {
    return this._listDataChild.get(this._listDataHeader.get(groupPosition))
            .size();
}

@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) {
    String headerTitle = (String) getGroup(groupPosition);
    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.list_group, null);
    }



    TextView tvHeader = (TextView) convertView
            .findViewById(R.id.tv_header);
    tvHeader.setTypeface(null, Typeface.BOLD);
    tvHeader.setText(headerTitle);

    return convertView;
}

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


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

And this is the layout:

<RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/rl_expen_but"
        android:layout_below="@+id/rl_ats_draft2"
        android:layout_above="@+id/selanjutnya"
        >



        <ExpandableListView
            android:background="@color/cardview_light_background"
            android:id="@+id/lvExp"
            android:descendantFocusability="beforeDescendants"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:animateLayoutChanges="true"/>

        <View
            android:layout_below="@+id/lvExp"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#bebebe"/>

    </RelativeLayout>

Is there something wrong I did with above codes? Thank you.

EDIT:

This is how my code looks like after I edited it as suggested by chandil03. The expandablelistview no longer refreshes when I expand headers. But strangely, when I typed values in edittext at groupposition 0 and child position 0, then in some other edittext in different goupposition and childposition appear the same exact values I typed at previous edittext. Or even stranger, the values at previous edittext sometimes dissapeared.

static class ViewHolder {
    protected View et;

    public void addView(View et){
        this.et = et;
    }
}

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

       final ExpandItemModel childText = (ExpandItemModel) getChild(groupPosition, childPosition);

       ViewHolder viewHolder;

       if (convertView == null) {
           LayoutInflater infalInflater = (LayoutInflater) this._context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           convertView = infalInflater.inflate(R.layout.list_item, null);
           viewHolder = new ViewHolder();
           viewHolder.addView(convertView
                .findViewById(R.id.et_total));
           convertView.setTag(viewHolder);
       }else{
           viewHolder = (ViewHolder)convertView.getTag();
       }

       final EditText etTotal = (EditText)convertView
        .findViewById(R.id.et_total);

       etTotal.setText(childText.getTotal);

       return convertView;
  }
like image 245
zamroni hamim Avatar asked Apr 13 '16 09:04

zamroni hamim


3 Answers

Whenever you expand another group list refreshes and you get an other instance of EditText there that has no text. The EditText you entered text in would have become child of another groupView.

So I would recommend you to create a ViewHolder class and keep your view in it and set it as a tag and in getView() check if convertView is null that you have already done. Just add else part and getTag from convertView and set values accordingly.

For example:

@Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
    {
        View v = convertView;
        if (v == null)
        {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.my_layout, parent, false);
            ViewHolder holder = new ViewHolder(); // View holder to save views.
            holder.addView(v.findViewById(R.id.myView));
            v.setTag(holder);
        }
        else{
        ViewHolder holder = (ViewHolder) v.getTag();  // get tag and set values
        // Do whatever you need to with the group view
        }
        return v;
    }

EDIT 1

I have modified your code. Check out comments also.

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

        final ExpandItemModel childText = (ExpandItemModel) getChild(groupPosition, childPosition);
        ViewHolder holder;
        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) this._context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_item, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.editText.setText(childText.getTotal); // Here whatever you will type in edittext will be overwritten by the value of 'childText.getTotal'. So after you are done writing in edit text make sore you change that in "_listDataChild" list. 

        return convertView;
    }

    /**This is a class that holds view, Here i m not talking about support.v7.widget.RecyclerView.ViewHolder class. Though concept is more or less same.*/
    class ViewHolder{
        EditText editText;

        public ViewHolder(View v)
        {
            editText = (EditText) v.findViewById(R.id.et_total);
        }
    }

EDIT 2

Add following code in getChildView() method.

holder.editText.setOnFocusChangeListener(new View.OnFocusChangeListener()
    {
        @Override
        public void onFocusChange(View v, boolean hasFocus)
        {
            if(!hasFocus)
                childText.getTotal = holder.editText.getText().toString(); 
// In java variable contains reference of Object so when you change childText object, it will be reflected in same HashMap you are getting data from.

        }
    });
like image 143
chandil03 Avatar answered Nov 06 '22 16:11

chandil03


The EditText is recycled every time you scroll down or click on another header in the ExpandableListView.

Your best bet will be to save the text the user enters in your model e.g:

etTotal.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                childText.setTotal(etTotal.getText().toString().trim());
            }
        }
    });
like image 1
ayz4sci Avatar answered Nov 06 '22 16:11

ayz4sci


First create a dummy model class to store your data from edittext like this :

public class DummyModel {
    String edt_field;
    //
    //And any other data you might want to store
    //
    public DummyModel(String field)
    {
        this.edt_field=field;
    }
}

Then create a static arraylist to store your data :

public class DummyStatic  {
public static ArrayList<DummyModel> arl_static=new ArrayList();
}

Then in your adapter class change your getChildView() method like this :

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

    final ExpandItemModel childText = (ExpandItemModel) getChild(groupPosition, childPosition);

    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.list_item, null);
    }

    final EditText etTotal = (EditText)convertView
            .findViewById(R.id.et_total);
    etTotal.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
             DummyStatic.arl_static.add(childPosition,new DummyModel(charSequence.toString()));
        }

        @Override
        public void afterTextChanged(Editable editable) {

        }
    });

    etTotal.setText(childText.getTotal);

    return convertView;
}

What this code is going to do is that as you type the characters in the edittext they will get stored in the DummyModel object inside the arraylist.

You can retrieve this data by :

String value = DummyStatic.arl_static.get(position).edt_field;
like image 1
Akhil Soman Avatar answered Nov 06 '22 18:11

Akhil Soman