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

|
204
|
+

|