UI そのものの動作の再検討も含めて入力検査・再入力の方法はいろいろで、これしか無いというのは無さそうに思います。
フォーカスが移動してしまうのがダメならフォーカスも戻すとか、逆に移動してもどこが問題なのかがはっきり分かるようにどうにかするというのも方法でしょう。
「TextWatcher 等でバリデートチェックして EditText#setError でエラーを表示するようにしフォーカスは自由に動かせる」というイメージで仕立ててみました。
DB の更新は考慮していませんが、エラーがあったら SEND ボタンを disable にしています。
MainActivity.java
java
1import androidx.annotation.NonNull;
2import androidx.appcompat.app.AppCompatActivity;
3import androidx.recyclerview.widget.RecyclerView;
4
5import android.os.*;
6import android.text.*;
7import android.util.Log;
8import android.view.*;
9import android.widget.*;
10
11import java.util.*;
12
13public class MainActivity extends AppCompatActivity {
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.activity_main);
18
19 Adapter adapter = new Adapter();
20 RecyclerView recyclerView = findViewById(R.id.recyclerView);
21 recyclerView.setAdapter(adapter);
22
23 Button cancelButton = findViewById(R.id.cancelButton);
24 cancelButton.setOnClickListener(v -> {
25 Log.d("MainActivity **", "cancel.");
26 });
27
28 Button sendButton = findViewById(R.id.sendButton);
29 sendButton.setOnClickListener(v -> {
30 Log.d("MainActivity **", "send.");
31 });
32 sendButton.setEnabled(false);
33
34 adapter.setEventListener(a -> {
35 sendButton.setEnabled(a.getErrorCount() == 0);
36 });
37 }
38
39 private static class Item {
40 final long id;
41 final String text;
42 Item(long id, String text) {
43 this.id = id;
44 this.text = text;
45 }
46 @Override
47 public String toString() {
48 return super.toString() + "[id=" + id + ", text='" + text + "']";
49 }
50 }
51
52 private static class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
53 interface AdapterListener extends EventListener {
54 void changeState(Adapter adapter);
55 }
56
57 private static class ViewHolder extends RecyclerView.ViewHolder {
58 final EditText editText;
59 public ViewHolder(@NonNull View itemView) {
60 super(itemView);
61 editText = itemView.findViewById(R.id.editText);
62 }
63 }
64
65 private List<Item> itemList = new ArrayList<>();
66 private Set<Long> errorSet = new HashSet<>();
67 private AdapterListener listener;
68
69 Adapter() {
70 //テストデータ
71 itemList.add(new Item(1, "ABC"));
72 itemList.add(new Item(2, "DEF"));
73 itemList.add(new Item(3, "GHI"));
74 itemList.add(new Item(4, "JKL"));
75 }
76
77 void setEventListener(AdapterListener listener) {
78 this.listener = listener;
79 if(listener != null) listener.changeState(this); //初期表示用
80 }
81
82 int getErrorCount() {
83 return errorSet.size();
84 }
85
86 @NonNull
87 @Override
88 public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
89 return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
90 }
91
92 private class EditValidator implements TextWatcher {
93 private EditText editText;
94 private Item item;
95
96 EditValidator(EditText editText, Item item) {
97 this.editText = editText;
98 this.item = item;
99 }
100
101 private boolean isValid(String text) {
102 return text.length() < 5; //テスト用でテキトウ
103 }
104
105 @Override
106 public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
107 @Override
108 public void onTextChanged(CharSequence s, int start, int before, int count) {}
109 @Override
110 public void afterTextChanged(Editable s) {
111 boolean changeState;
112 if(isValid(s.toString())) {
113 editText.setError(null);
114 changeState = errorSet.remove(item.id);
115 } else {
116 editText.setError("length Error");
117 changeState = errorSet.add(item.id);
118 }
119 if(changeState && listener != null) listener.changeState(Adapter.this);
120 }
121 }
122
123 @Override
124 public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
125 Item item = itemList.get(position);
126 holder.editText.setText(item.text);
127
128 TextWatcher validator = (TextWatcher)holder.editText.getTag();
129 if(validator != null) holder.editText.removeTextChangedListener(validator);
130 validator = new EditValidator(holder.editText, item);
131 holder.editText.setTag(validator);
132 holder.editText.addTextChangedListener(validator);
133 }
134
135 @Override
136 public int getItemCount() {
137 return itemList.size();
138 }
139 }
140}
res/layout/activity_main.xml
xml
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:tools="http://schemas.android.com/tools"
5 xmlns:app="http://schemas.android.com/apk/res-auto"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context=".MainActivity">
9
10 <androidx.recyclerview.widget.RecyclerView
11 android:id="@+id/recyclerView"
12 android:layout_width="0dp"
13 android:layout_height="0dp"
14 app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
15 app:layout_constraintBottom_toTopOf="@id/topOfButtons"
16 app:layout_constraintEnd_toEndOf="parent"
17 app:layout_constraintStart_toStartOf="parent"
18 app:layout_constraintTop_toTopOf="parent" />
19 <androidx.constraintlayout.widget.Barrier
20 android:id="@+id/topOfButtons"
21 android:layout_width="0dp"
22 android:layout_height="0dp"
23 app:barrierDirection="top"
24 app:constraint_referenced_ids="cancelButton,sendButton" />
25 <Button
26 android:id="@+id/cancelButton"
27 android:layout_width="wrap_content"
28 android:layout_height="wrap_content"
29 android:text="CANCEL"
30 app:layout_constraintBottom_toBottomOf="parent"
31 app:layout_constraintEnd_toStartOf="@id/sendButton"
32 app:layout_constraintStart_toStartOf="parent" />
33 <Button
34 android:id="@+id/sendButton"
35 android:layout_width="wrap_content"
36 android:layout_height="wrap_content"
37 android:text="SEND"
38 app:layout_constraintBottom_toBottomOf="parent"
39 app:layout_constraintEnd_toEndOf="parent"
40 app:layout_constraintStart_toEndOf="@id/cancelButton" />
41</androidx.constraintlayout.widget.ConstraintLayout>
res/layout/item.xml
xml
1<?xml version="1.0" encoding="utf-8"?>
2<EditText
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 android:id="@+id/editText"
5 android:layout_width="match_parent"
6 android:layout_height="wrap_content" />

