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:
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?