3

I'm having an issue that I have not been able to solve for a couple weeks now. I have an app that adds two EditTexts and one CheckBox on button click. However, whenever I type some content in the EditTexts, and then scroll down, the content disappears when I scroll back up. I cannot figure out a fix for this. I have found a few other very similar posts, however I have tried all solutions I can find, but none have seemed to do the trick for me yet. Here are a couple similar posts I found:

I've recently done some changes to my program in attempt to fix this as well. I added an ArrayList to my MainActivity and passed it to my adapter. I also made two custom text listeners in which onTextChanged, I add the string to the ArrayList. Then, in onBindViewHolder, I update the position in the text listeners, then set the text to the String in the ArrayList at that position. However, this is giving some strange errors. Now, when I add content to an EditText and scroll down, it adds it to multiple EditTexts, and even changes the content in some of them. I'm not sure how to go about fixing this.

Also, on another note, I have the app enabled for drag and drop and swipe to dismiss. So please take that into account as well if you have a solution. Thank you!

MainActivity

import android.content.ClipData;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ArrayList<ListItems> itemsList;
    private RecyclerView mRecyclerView;
    private MyRecyclerAdapter adapter;
    private List<String> courseStrings = new ArrayList<>();
    private List<String> creditStrings =  new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        courseStrings.add("");
        creditStrings.add("");

        // Toast variable in order to fix toast queueing issue.
        final Toast toast = Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT);

        // For the recycler view.
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);

        itemsList = new ArrayList<>();
        adapter = new MyRecyclerAdapter(MainActivity.this, itemsList, courseStrings, creditStrings);
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setLayoutManager(linearLayoutManager);

        // For the addCourse button.
        final Button addCourse = (Button) findViewById(R.id.addCourse);
        addCourse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                adapter.createListItem(new ListItems(null, null, false), toast);
                toast.setText("New course added");
                toast.show();
            }
        });

        final Button clearAll = (Button) findViewById(R.id.clearAll);
        clearAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // In order to clear the list.
                if (itemsList.size() == 0) {
                    toast.setText("All courses have already been cleared.");
                    toast.show();
                } else {
                    adapter.clearAdapter();
                    toast.setText("All courses have been cleared.");
                    toast.show();
                }
            }
        });

        // For the drag and drop/swipe to dismiss.
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(
                new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
                        ItemTouchHelper.LEFT) {
                    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                        final int fromPos = viewHolder.getAdapterPosition();
                        final int toPos = target.getAdapterPosition();
                        Collections.swap(itemsList, fromPos, toPos);
                        adapter.notifyItemMoved(fromPos, toPos);
                        return true;
                    }
                    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                       adapter.onItemDismiss(viewHolder.getAdapterPosition());
                    }
                });
        itemTouchHelper.attachToRecyclerView(mRecyclerView);
    } // End of onCreate
} // End of MainActivity

MyRecyclerAdapter

import android.app.Activity;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.view.LayoutInflater;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.CustomRowViewHolder> {

     private ArrayList<ListItems> itemsList;
     private Context mContext;
     private List<String> courseStrings;
     private List<String> creditStrings;


    public MyRecyclerAdapter(Context context, ArrayList<ListItems> itemsList, List<String> courseStrings, List<String> creditStrings){
        this.itemsList = itemsList;
        this.mContext = context;
        this.courseStrings = courseStrings;
        this.creditStrings = creditStrings;
    }

     @Override
     public MyRecyclerAdapter.CustomRowViewHolder onCreateViewHolder(final ViewGroup viewGroup, int position) {
         View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.new_course_row, null);
         final CustomRowViewHolder holder = new CustomRowViewHolder(v, new CoursesCustomTextListener(), new CreditsCustomTextListener());
         holder.creditsText.setInputType(InputType.TYPE_CLASS_NUMBER);
         holder.checkBox.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 if(holder.checkBox.isChecked()) {
                     holder.courseText.setEnabled(false);
                     holder.courseText.setFocusable(false);
                     holder.courseText.setInputType(InputType.TYPE_NULL);
                     holder.creditsText.setEnabled(false);
                     holder.creditsText.setFocusable(false);
                     holder.creditsText.setInputType(InputType.TYPE_NULL);
                 } else {
                     holder.courseText.setEnabled(true);
                     holder.courseText.setFocusable(true);
                     holder.courseText.setFocusableInTouchMode(true);
                     holder.courseText.setInputType(InputType.TYPE_CLASS_TEXT);
                     holder.creditsText.setEnabled(true);
                     holder.creditsText.setFocusable(true);
                     holder.creditsText.setFocusableInTouchMode(true);
                     holder.creditsText.setInputType(InputType.TYPE_CLASS_NUMBER);
                 } // End if else
             }
         });
         return holder;
     } // End of onCreateViewHolder

     @Override
     public void onBindViewHolder(CustomRowViewHolder holder, final int position) {
         ListItems listItem = itemsList.get(position);
         int focusedItem = 0;
         holder.itemView.setSelected(focusedItem == position);
         holder.getLayoutPosition();

         holder.creditsCustomTextListener.updatePosition(position);
         holder.creditsCustomTextListener.updatePosition(position);

         holder.courseText.setText(courseStrings.get(position));
         holder.creditsText.setText(creditStrings.get(position));

         // Set listener to check box.
         holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
             @Override
             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                 itemsList.get(position).setIsComplete(b);
             }
         });
         holder.checkBox.setChecked(  itemsList.get(position).getIsComplete());
     } // End of onBindViewHolder

     public void clearAdapter() {
         itemsList.clear();
         notifyDataSetChanged();
     } // End of clearAdapter

     public int getItemCount() {
         return(null != itemsList ? itemsList.size() : 0);
     } // End of getItemCount

     public void onItemDismiss(int position) {
         itemsList.remove(position);
         notifyItemRemoved(position);
         notifyItemRangeChanged(position, itemsList.size());
     } // End of onItemDismiss

     public void createListItem(ListItems listItem, Toast toast) {
         itemsList.add(listItem);
         int position = itemsList.indexOf(listItem);
         notifyItemInserted(position);
     } // End of createListItem

     ///////////////////////////////////// CustomRowViewHolder /////////////////////////////////////

     public static class CustomRowViewHolder extends RecyclerView.ViewHolder {

         public EditText courseText;
         public EditText creditsText;
         public CheckBox checkBox;
         public RelativeLayout relativeLayout;
         public CoursesCustomTextListener coursesCustomTextListener;
         public CreditsCustomTextListener creditsCustomTextListener;

         public CustomRowViewHolder(View view, CoursesCustomTextListener coursesCustomTextListener, CreditsCustomTextListener creditsCustomTextListener) {
             super(view);
             this.coursesCustomTextListener = coursesCustomTextListener;
             this.creditsCustomTextListener = creditsCustomTextListener;
             this.courseText = (EditText) view.findViewById(R.id.course);
             this.creditsText = (EditText) view.findViewById(R.id.credits);
             this.checkBox = (CheckBox) view.findViewById(R.id.complete);
             this.relativeLayout = (RelativeLayout) view.findViewById(R.id.relLayout);
             this.courseText.addTextChangedListener(coursesCustomTextListener);
             this.creditsText.addTextChangedListener(creditsCustomTextListener);
         }
     }

     ////////////////////////////////// CoursesCustomTextListener //////////////////////////////////

     private class CoursesCustomTextListener implements TextWatcher {
         private int position;

         public void updatePosition(int position) {
             this.position = position;
         }
         @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
             // No operation to perform.
         }

         @Override
         public void onTextChanged(CharSequence s, int start, int before, int count) {
             courseStrings.add(s.toString());
         }

         @Override
         public void afterTextChanged(Editable s) {
             // No operation to perform.
         }
     }

     ////////////////////////////////// CreditsCustomTextListener //////////////////////////////////

     private class CreditsCustomTextListener implements TextWatcher {
         private int position;

         public void updatePosition(int position) {
             this.position = position;
         }
         @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
             // No operation to perform.
         }

         @Override
         public void onTextChanged(CharSequence s, int start, int before, int count) {
             creditStrings.add(s.toString());
         }

         @Override
         public void afterTextChanged(Editable s) {
             // No operation to perform.
         }
     }
} // End of MyRecyclerAdapter

ListItems

import java.util.ArrayList;

public class ListItems {
    private String course;
    private String credits;
    private Boolean complete;

    public ListItems(String mCourse, String mCredits, Boolean mComplete) {
        course = mCourse;
        credits = mCredits;
        complete = mComplete;
    }

    public String getCourse() {
        return course;
    }

    public void setCourse(String course) {
        this.course = course;
    }

    public String getCredits() {
        return credits;
    }

    public void setCredits(String credits) {
        this.credits = credits;
    }

    public Boolean getIsComplete() {
        return complete;
    }

    public void setIsComplete(Boolean complete) {
        this.complete = complete;
    }
} // End of ListItems

new_course_row.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/relLayout"
    android:layout_margin="5dp">

    <EditText
        android:layout_width="130dp"
        android:layout_height="wrap_content"
        android:id="@+id/course"
        android:hint="Enter Course ID"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:textSize="16sp"
        android:maxLines="1" />

    <EditText
        android:layout_width="115dp"
        android:layout_height="wrap_content"
        android:id="@+id/credits"
        android:hint="Enter Credits"
        android:layout_alignBottom="@+id/course"
        android:textSize="16sp"
        android:layout_toRightOf="@+id/course"
        android:maxLines="1" />

    <CheckBox
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="Check if complete"
        android:id="@+id/complete"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignBottom="@+id/course"
        android:textSize="13sp"
        android:paddingBottom="4dp"
        android:paddingTop="4dp" />

</RelativeLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingRight="10dp"
    android:paddingLeft="10dp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:id="@+id/rl"
    tools:context=".MainActivity" >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add Course"
        android:id="@+id/addCourse"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:textColor="#FFF"
        android:background="@drawable/my_button"
        android:textSize="18dp"
        android:paddingRight="5dp"
        android:paddingLeft="5dp"
        android:paddingTop="15dp"
        android:paddingBottom="15dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Clear All"
        android:id="@+id/clearAll"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:textColor="#FFF"
        android:background="@drawable/my_button"
        android:textSize="18dp"
        android:paddingRight="5dp"
        android:paddingLeft="5dp"
        android:paddingTop="15dp"
        android:paddingBottom="15dp"/>

    <android.support.v7.widget.RecyclerView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/recycler_view"
        android:layout_below="@+id/addCourse"
        android:layout_marginTop="10dp"
        />
</RelativeLayout>

Thank you in advance for any help! I could REALLY use a solution!

EDIT: I've noticed now that, say I enter "aaaaaaa" in the first EditText, then it will add "a" to an EditText further down the list, then "aa" to the EditText after that one, then "aaa", "aaaa", until it reaches "aaaaaaa". Then there will be a few empty EditText's, and then it will start it over again. Here is a visual:Here

EDIT x2: Haven't worked on this in a while, and haven't been getting any answers. Even got the "Tumbleweed" badge for this post! Anyone have any ideas?

Community
  • 1
  • 1
tlochner95
  • 127
  • 3
  • 15

1 Answers1

1

Though I am not quite sure but I believe this is happening because recycler view regenerates its positons . For your custom edit text you are adding the string ` @Override public void onTextChanged(CharSequence s, int start, int before, int count) { courseStrings.add(s.toString()); }

for both edit texts. In recyler view you have implemented this.courseText.addTextChangedListener(coursesCustomTextListener);

so everytime you scroll the onBind Method is called and as the position changes this must be getting called too. Hence it must be regenerating . I request you to first try

holder.courseText.setTag(position); 

in onBindViewHolder(). Try it for both texts individually.If it does work then try

holder.view.setTag(position);
Pritish
  • 1,284
  • 1
  • 19
  • 42