java - 在 RecyclerView 中滚动后 EditText 丢失内容

标签 java android android-edittext android-recyclerview

我有几个星期没能解决的问题。我有一个应用程序,可以在单击按钮时添加两个 EditText 和一个 CheckBox。但是,每当我在 EditTexts 中键入一些内容,然后向下滚动时,当我向上滚动时内容就会消失。我无法解决这个问题。我发现了其他一些非常相似的帖子,但是我已经尝试了我能找到的所有解决方案,但似乎还没有一个对我有用。这是我发现的几个类似的帖子:

我最近对我的程序做了一些修改,试图解决这个问题。我将 ArrayList 添加到我的 MainActivity 并将其传递到我的适配器。我还制作了两个自定义文本监听器,其中 onTextChanged,我将字符串添加到 ArrayList。然后,在 onBindViewHolder 中,我更新文本监听器中的位置,然后在该位置将文本设置为 ArrayList 中的字符串。但是,这会产生一些奇怪的错误。现在,当我将内容添加到 EditText 并向下滚动时,它会将其添加到多个 EditText,甚至更改其中一些的内容。我不确定如何解决这个问题。

另外,另一方面,我为应用程序启用了拖放和滑动关闭功能。因此,如果您有解决方案,请也考虑到这一点。谢谢!

主 Activity

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

我的回收器适配器

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

列表项

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>

提前感谢您的帮助!我真的可以使用解决方案!

编辑:我现在注意到,假设我在第一个 EditText 中输入“aaaaaaa”,然后它会将“a”添加到列表下方的 EditText,然后将“aa”添加到那个之后的 EditText,然后“aaa”、“aaaa”,直到到达“aaaaaaa”。然后会有一些空的EditText,然后它会重新开始。这是视觉效果:Here

EDIT x2:有一段时间没有研究这个,也没有得到任何答案。甚至因为这篇文章获得了“风滚草”徽章!有人有什么想法吗?

最佳答案

虽然我不太确定,但我相信这是正在发生的,因为回收器 View 重新生成了它的位置。对于您的自定义编辑文本,您要添加字符串`@Override public void onTextChanged(CharSequence s, int start, int before, int count) { courseStrings.add(s.toString());

对于两个编辑文本。 在回收站 View 中,您已经实现了 this.courseText.addTextChangedListener(coursesCustomTextListener);

所以每次滚动时都会调用 onBind 方法,并且随着位置的变化,它也必须被调用。因此它一定是再生的。我请你先试试

holder.courseText.setTag(position); 

在 onBindViewHolder() 中。 分别尝试两种文本。如果它确实有效,请尝试

holder.view.setTag(position);

关于java - 在 RecyclerView 中滚动后 EditText 丢失内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37779059/

相关文章:

android - TouchableHighlight onPress 在导航时自动触发

android - 带按钮的 EditTextPreference

android - 在 EditText 上显示非常大的 double 值

仅使用运行时异常的 Java 数据对象规范?

android - 为什么我的面板在移动设备上向上滚动? jQuery手机

java - 如何提交当前的 guice-persist UnitOfWork?

java - 源代码中的密码 - 安全吗?

java - 为android做一个基本的定时器?

java - JunitParamsRunner 测试

java - 未找到 Hive UDF 类