EditText теряет свое содержание на RecyclerView. Как восстановить его содержимое? - PullRequest
1 голос
/ 22 мая 2019

У меня есть EditText в RecyclerView. Когда я редактирую содержимое EditText и прокручиваю вверх / вниз, это же содержимое отображается в другой строке. Кроме того, если я вернусь в ту же позицию, EditText будет пустым.

Вот макет для каждого элемента RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#F3F2F2"
            android:orientation="vertical"
            android:padding="5dp">

            <TextView
                android:id="@+id/txt_jantri_number"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:fontFamily="@font/quicksand_bold"
                android:text="1"
                android:textColor="@color/theme_color"
                android:textSize="10sp" />

            <EditText
                android:id="@+id/ed_jantri_number"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:background="@drawable/shape_jantri_edittext"
                android:fontFamily="@font/quicksand_bold"
                android:gravity="center"
                android:inputType="number"
                android:maxLines="1"
                android:minLines="1"
                android:padding="5dp"
                android:textSize="12dp" />
        </LinearLayout>
</LinearLayout>

Вот класс Adapter, в котором я устанавливаю текст для номера поля:

public class AdapterJantri extends RecyclerView.Adapter<AdapterJantri.Myholder> {
    @NonNull
    @Override
    public Myholder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        return new Myholder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_jantri_view, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(@NonNull Myholder myholder, int i) {
        myholder.txtJantriNumber.setText(String.valueOf(i + 1));
    }

    @Override
    public int getItemCount() {
        return 99;
    }

    public class Myholder extends RecyclerView.ViewHolder {
        EditText edJantriNumber;
        TextView txtJantriNumber;

        public Myholder(@NonNull View itemView) {
            super(itemView);
            edJantriNumber = itemView.findViewById(R.id.ed_jantri_number);
            txtJantriNumber = itemView.findViewById(R.id.txt_jantri_number);
        }
    }
}

Вот это занятие

public class JantriActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    SlideToActView slideToActView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jantri);
        initiliaization();
        recyclerView.setAdapter(new AdapterJantri());
    }

    private void initiliaization() {
        recyclerView = findViewById(R.id.recycler_jantri);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
        slideToActView = findViewById(R.id.swipe_save_transaction);
    }
}

1 Ответ

2 голосов
/ 22 мая 2019

A ViewAdapter повторно использует View. Таким образом, при прокрутке вместо создания новых видов Адаптер будет повторно использовать вид, который больше не виден. Итак, это главная причина, по которой у вас есть onBindViewHolder. С помощью этого метода Android дает вам возможность обновить содержимое просмотра, прежде чем оно станет видимым. Если вы не обновите все содержимое (TextView и EditText), вы увидите проблемы, подобные той, о которой вы упоминали.

Обратите внимание на этот код:

@Override
public void onBindViewHolder(@NonNull Myholder myholder, int i) {
    myholder.txtJantriNumber.setText(String.valueOf(i + 1));
}

Как видите, вы обновляете только TextView. Таким образом, TextView (используется повторно или нет) всегда будет отображать правильный текст. Однако вы не обновляете содержимое EditText. Таким образом, если представление было только что создано, EditText будет пустым. Если представление используется повторно, вы увидите старое значение (из другой строки).

Итак, чтобы правильно обновлять EditText, вы должны хранить все тексты в отдельном списке. Например:

public class AdapterJantri extends RecyclerView.Adapter<AdapterJantri.Myholder> {

    private String[] mTextList;

    public AdapterJantri() {
        mTextList = new String[getItemCount()];
    }

    @Override
    public void onBindViewHolder(@NonNull Myholder myholder, int i) {
        myholder.txtJantriNumber.setText(String.valueOf(i + 1));

        // Here, you update the EditText content
        myholder.edJantriNumber.setText(mTextList[i]);
    }

    @Override
    public void onViewRecycled(@NonNull final Myholder holder) {
        // Here, you save the text before the view gets recycled
        int index = holder.getAdapterPosition();
        if (index >= 0) {
            mTextList[index] = holder.edJantriNumber.getText().toString();
        }
    }
}

EDIT

Если у вас есть TextWatcher и вам необходимо временно его отключить, я предлагаю:

Первый

Не создавайте TextWatcher внутри bindViewHolder. Вам не нужно создавать новый каждый раз. Просто добавьте это и удалите это. Вы можете использовать свой MyHolder как TextWatcher

public class Myholder extends RecyclerView.ViewHolder implements TextWatcher {

    EditText edJantriNumber;
    TextView txtJantriNumber;

    public Myholder(@NonNull View itemView) {
        super(itemView);
        edJantriNumber = itemView.findViewById(R.id.ed_jantri_number);
        txtJantriNumber = itemView.findViewById(R.id.txt_jantri_number);
    }

    @Override
    public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
        // Add your code here
    }

    @Override
    public void onTextChanged(final CharSequence s, final int start, final int before,
            final int count) {
        // Add your code here
    }

    @Override
    public void afterTextChanged(final Editable s) {
        // Add your code here
    }

    public void disableTextChangeListner() {
        // This will remove the listener. So, it will stop to listen to new events
        edJantriNumber.removeTextChangedListener(this);
    }

    public void addTextChangeListner() {
        // This will add the listener. So, it will start to listen to new events
        edJantriNumber.addTextChangedListener(this);
    }
}

Затем, во время bindViewHolder, отключите прослушиватель, установите новый текст и снова добавьте прослушиватель следующим образом:

@Override
public void onBindViewHolder(@NonNull Myholder myholder, int i) {
    myholder.disableTextChangeListner();
    myholder.txtJantriNumber.setText(String.valueOf(i + 1));
    myholder.edJantriNumber.setText(mTextList[i]);
    myholder.addTextChangeListner();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...