Android RecyclerView's EditText swaps its position after entering data and scroll down

I have a RecyclerView which consists of a TextView and EditText, for the TextView the RecyclerView working perfectly fine with me, but for the EditText, if I enter value in first cell and keep on entering for other cell and scroll the entered value above will be not present.

public class Assesment_MarkcardAdapter extends RecyclerView.Adapter<Assesment_MarkcardAdapter.ContactViewHolder> {

    private String[] mDataset;

    public Assesment_MarkcardAdapter(String[] myDataset)
    {
        mDataset = myDataset;
    }

    private List<Assesment_cardinfo> contactList;
    private static String LOG_TAG = "Assesment_MarkcardAdapter";


    public Assesment_MarkcardAdapter(List<Assesment_cardinfo> contactList) {
        this.contactList = contactList;
    }


    @Override
    public int getItemCount() {
        return contactList.size();
    }

    @Override
    public void onBindViewHolder(ContactViewHolder contactViewHolder, int i)
    {

        mDataset = new String[contactList.size()];
        Assesment_cardinfo ci = contactList.get(i);
        contactViewHolder.studentname.setText(ci.getStudentname());
        contactViewHolder.studentid.setText(ci.getStudentid());
        contactViewHolder.grade.setText(ci.getGrade());
        contactViewHolder.improvement.setText(ci.getImprovements());
        contactViewHolder.grade.setTag(ci);
        contactViewHolder.improvement.setTag(ci);
        contactViewHolder.myCustomEditTextListener.updatePosition(i);
        contactViewHolder.myCustomEditTextListener2.updatePosition2(i);
        //contactViewHolder.grade.setText(mDataset[i]);
    }

    @Override
    public Assesment_MarkcardAdapter.ContactViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
    {
        View itemView = LayoutInflater.
                from(viewGroup.getContext()).
                inflate(R.layout.assesment_markcard, viewGroup, false);

        return new ContactViewHolder(itemView , new MyCustomEditTextListener(),new MyCustomEditTextListener2());
    }

    public static class ContactViewHolder extends RecyclerView.ViewHolder {

        public MyCustomEditTextListener myCustomEditTextListener;
        public MyCustomEditTextListener2 myCustomEditTextListener2;

        protected TextView studentname;
        protected TextView studentid;
        protected EditText grade;
        protected EditText improvement;


        public ContactViewHolder(View v, MyCustomEditTextListener myCustomEditTextListener, MyCustomEditTextListener2 myCustomEditTextListener2 ) {
            super(v);
            studentname = (TextView) v.findViewById(R.id.txt_student_name);
            studentid = (TextView) v.findViewById(R.id.txt_student_id);
            grade = (EditText) v.findViewById(R.id.edtxt_grade);
            this.myCustomEditTextListener = myCustomEditTextListener;
            grade.addTextChangedListener(myCustomEditTextListener);
            improvement = (EditText) v.findViewById(R.id.edtxt_improvement);
            this.myCustomEditTextListener2 = myCustomEditTextListener2;
            improvement.addTextChangedListener(myCustomEditTextListener2);

        }

    }
    private class MyCustomEditTextListener implements TextWatcher
    {
        private int position;

        public void updatePosition(int position)
        {
            this.position = position;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            // no op
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            contactList.get(position).setGrade(charSequence.toString());
        }

        @Override
        public void afterTextChanged(Editable editable) {
            // no op
        }
    }

    private class MyCustomEditTextListener2 implements TextWatcher
    {
        private int position;

        public void updatePosition2(int position)
        {
            this.position = position;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            // no op
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
        {
            contactList.get(position).setImprovements(charSequence.toString());
        }

        @Override
        public void afterTextChanged(Editable editable) {
            // no op
        }
    }
    public List<Assesment_cardinfo> getStudentLists()
    {
        return contactList;
    }
}

Upvotes: 4

Views: 4231

Answers (3)

Raja Peela
Raja Peela

Reputation: 1386

I have faced the same problem.

holder.editQty.addTextChangedListener

When you're adding a Textwatcher to Edittext that was added to array of listeners so this is bad practice.

Either you have to remove all old listener with set null.

 holder.editQty.addTextChangedListener(null);
 holder.editQty.addTextChangedListener(new TextWatcher())

It will resolve the problem.

Upvotes: 1

Nigam Patro
Nigam Patro

Reputation: 2770

Add these two lines, inside your onBindViewHolder()

contactViewHolder.grade.setText(ci.getGrade());
contactViewHolder.improvement.setText(ci.getImprovement());

after setting the listeners, that means after

contactViewHolder.myCustomEditTextListener.updatePosition(i);
contactViewHolder.myCustomEditTextListener2.updatePosition2(i);

these two lines of code.

this will work for sure.This happens because you are not setting text to the EditText and after recycle, the text is already gone. So, try this, it will definitly work.

Upvotes: 1

Nitin Mesta
Nitin Mesta

Reputation: 1504

Its really bad to put input fields in recycler view. Try restructring your UI design. Recycler view should always have read only fields. Even then you want to achieve this try creating views dynamically and adding it to the rooot layout. For instance Have a XML file where linear layout would be your root. Create one more XML file and keep adding this template to your root view.

Probably Something like this this will be your root layout instear od recycler view

<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

//Create a template layout.You need to add the property i am just skippint it
<LinearLayout>
<TextView/>
<EditText/>


// In you activity write a method to create a view dynamically from template and add it to your root Layout. 

LinearLayout rootLayout=(LinearLayout)findViewById(R.id.container);

createChilds(rootLayout);

private void createChilds(LinearLayout rootLayout)
{
LinearLayout  childContainer=(LinearLayout)LayoutInflater.from(context).inflate(R.layout.template_layout,null);
TextView tv=childContainer.findViewById(R.id.textviewid);
EditText et=childContainer.findViewById(R.id.edittextviewid);

// you can register for textwatcher for edit text if you want

//Add it to roolayout
rootLayout.addView(childContainer);
}

Upvotes: 0

Related Questions