Skip to content

Commit 60e4005

Browse files
committed
Factored out custom answer view
1 parent 32dccf9 commit 60e4005

File tree

5 files changed

+103
-52
lines changed

5 files changed

+103
-52
lines changed

collect_app/src/main/java/org/odk/collect/android/widgets/BarcodeWidget.kt

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package org.odk.collect.android.widgets
33
import android.annotation.SuppressLint
44
import android.app.Activity
55
import android.content.Context
6-
import android.util.TypedValue
76
import android.view.View
87
import com.google.zxing.integration.android.IntentIntegrator
98
import org.javarosa.core.model.data.IAnswerData
@@ -43,59 +42,44 @@ class BarcodeWidget(
4342
} else {
4443
binding.barcodeButton.setOnClickListener { onButtonClick() }
4544
}
46-
binding.barcodeAnswerText.setTextSize(
47-
TypedValue.COMPLEX_UNIT_DIP,
48-
answerFontSize.toFloat()
49-
)
45+
binding.answerView.setHidden(hasAppearance(prompt, Appearances.HIDDEN_ANSWER))
46+
binding.answerView.setTextSize(answerFontSize.toFloat())
5047

5148
val answer = prompt.answerText
5249
if (!answer.isNullOrEmpty()) {
5350
binding.barcodeButton.text = getContext().getString(R.string.replace_barcode)
54-
binding.barcodeAnswerText.text = answer
5551
}
52+
binding.answerView.setAnswer(prompt.answerText)
5653

57-
updateVisibility()
5854
return binding.root
5955
}
6056

6157
override fun clearAnswer() {
62-
binding.barcodeAnswerText.text = null
58+
binding.answerView.setAnswer(null)
6359
binding.barcodeButton.text = context.getString(R.string.get_barcode)
6460
widgetValueChanged()
65-
updateVisibility()
6661
}
6762

6863
override fun getAnswer(): IAnswerData? {
69-
val answer = binding.barcodeAnswerText.text.toString()
64+
val answer = binding.answerView.getAnswer()
7065
return if (answer.isEmpty()) null else StringData(answer)
7166
}
7267

7368
override fun setData(answer: Any) {
74-
val response = answer as String
75-
binding.barcodeAnswerText.text = stripInvalidCharacters(response)
69+
binding.answerView.setAnswer(answer as String)
7670
binding.barcodeButton.text = context.getString(R.string.replace_barcode)
77-
updateVisibility()
7871
widgetValueChanged()
7972
}
8073

81-
private fun updateVisibility() {
82-
if (hasAppearance(formEntryPrompt, Appearances.HIDDEN_ANSWER)) {
83-
binding.barcodeAnswerText.visibility = GONE
84-
} else {
85-
binding.barcodeAnswerText.visibility =
86-
if (binding.barcodeAnswerText.text.toString().isBlank()) GONE else VISIBLE
87-
}
88-
}
89-
9074
override fun setOnLongClickListener(l: OnLongClickListener?) {
91-
binding.barcodeAnswerText.setOnLongClickListener(l)
9275
binding.barcodeButton.setOnLongClickListener(l)
76+
binding.answerView.setOnLongClickListener(l)
9377
}
9478

9579
override fun cancelLongPress() {
9680
super.cancelLongPress()
9781
binding.barcodeButton.cancelLongPress()
98-
binding.barcodeAnswerText.cancelLongPress()
82+
binding.answerView.cancelLongPress()
9983
}
10084

10185
private fun onButtonClick() {
@@ -122,9 +106,4 @@ class BarcodeWidget(
122106
}
123107
}
124108
}
125-
126-
// Remove control characters, invisible characters and unused code points.
127-
private fun stripInvalidCharacters(data: String?): String? {
128-
return data?.replace("\\p{C}".toRegex(), "")
129-
}
130109
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.odk.collect.android.widgets
2+
3+
import android.content.Context
4+
import android.util.AttributeSet
5+
import android.util.TypedValue
6+
import android.view.LayoutInflater
7+
import android.widget.FrameLayout
8+
import org.odk.collect.android.databinding.BarcodeWidgetAnswerBinding
9+
10+
class BarcodeWidgetAnswer @JvmOverloads constructor(
11+
context: Context,
12+
attrs: AttributeSet? = null,
13+
defStyle: Int = 0
14+
) : FrameLayout(context, attrs, defStyle) {
15+
private val binding = BarcodeWidgetAnswerBinding.inflate(LayoutInflater.from(context), this, true)
16+
private var hidden = false
17+
18+
fun setAnswer(answer: String?) {
19+
binding.answer.text = stripInvalidCharacters(answer)
20+
binding.root.visibility = if (hidden || binding.answer.text.isNullOrBlank()) GONE else VISIBLE
21+
}
22+
23+
fun setTextSize(textSize: Float) {
24+
binding.answer.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
25+
}
26+
27+
fun setHidden(hidden: Boolean) {
28+
this.hidden = hidden
29+
}
30+
31+
fun getAnswer(): String {
32+
return binding.answer.text.toString()
33+
}
34+
35+
// Remove control characters, invisible characters and unused code points.
36+
private fun stripInvalidCharacters(data: String?): String? {
37+
return data?.replace("\\p{C}".toRegex(), "")
38+
}
39+
}
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
4-
android:orientation="vertical"
54
android:layout_width="match_parent"
6-
android:layout_height="wrap_content">
5+
android:layout_height="match_parent">
76

87
<org.odk.collect.androidshared.ui.multiclicksafe.MultiClickSafeMaterialButton
98
android:id="@+id/barcode_button"
109
style="?widgetButtonIconQuestionWidgetStyle"
1110
android:text="@string/get_barcode"
1211
android:layout_width="match_parent"
1312
android:layout_height="wrap_content"
13+
app:layout_constraintTop_toTopOf="parent"
14+
app:layout_constraintStart_toStartOf="parent"
1415
app:icon="@drawable/ic_baseline_barcode_scanner_white_24" />
1516

16-
<com.google.android.material.textview.MaterialTextView
17-
android:id="@+id/barcode_answer_text"
18-
style="@style/Widget.Collect.TextView.WidgetAnswer" />
17+
<org.odk.collect.android.widgets.BarcodeWidgetAnswer
18+
android:id="@+id/answer_view"
19+
android:layout_width="wrap_content"
20+
android:layout_height="wrap_content"
21+
app:layout_constraintTop_toBottomOf="@id/barcode_button"
22+
app:layout_constraintStart_toStartOf="parent"
23+
app:layout_constraintEnd_toEndOf="parent"/>
1924

20-
</LinearLayout>
25+
</androidx.constraintlayout.widget.ConstraintLayout>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:id="@+id/barcode_widget_answer"
6+
android:layout_width="wrap_content"
7+
android:layout_height="wrap_content">
8+
9+
<ImageView
10+
android:id="@+id/icon"
11+
android:layout_width="wrap_content"
12+
android:layout_height="wrap_content"
13+
app:tint="?colorOnSurface"
14+
app:srcCompat="@drawable/ic_baseline_barcode_scanner_white_24"
15+
app:layout_constraintTop_toTopOf="@id/answer"
16+
app:layout_constraintBottom_toBottomOf="@id/answer"
17+
app:layout_constraintStart_toStartOf="parent" />
18+
19+
<com.google.android.material.textview.MaterialTextView
20+
android:id="@+id/answer"
21+
style="@style/Widget.Collect.TextView.WidgetAnswer"
22+
android:layout_width="wrap_content"
23+
android:layout_height="wrap_content"
24+
app:layout_constraintTop_toTopOf="parent"
25+
app:layout_constraintStart_toEndOf="@id/icon"
26+
tools:text="123456789" />
27+
28+
</androidx.constraintlayout.widget.ConstraintLayout>

collect_app/src/test/java/org/odk/collect/android/widgets/BarcodeWidgetTest.kt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import android.view.View.OnLongClickListener
55
import androidx.test.ext.junit.runners.AndroidJUnit4
66
import org.hamcrest.CoreMatchers.equalTo
77
import org.hamcrest.MatcherAssert.assertThat
8-
import org.hamcrest.Matchers
98
import org.javarosa.core.model.FormIndex
109
import org.javarosa.core.model.data.StringData
1110
import org.javarosa.form.api.FormEntryPrompt
@@ -15,14 +14,15 @@ import org.mockito.ArgumentMatchers
1514
import org.mockito.Mockito.verify
1615
import org.mockito.kotlin.mock
1716
import org.mockito.kotlin.whenever
17+
import org.odk.collect.android.R
1818
import org.odk.collect.android.fakes.FakePermissionsProvider
1919
import org.odk.collect.android.formentry.questions.QuestionDetails
2020
import org.odk.collect.android.support.MockFormEntryPromptBuilder
2121
import org.odk.collect.android.utilities.Appearances
2222
import org.odk.collect.android.widgets.support.FakeWaitingForDataRegistry
2323
import org.odk.collect.android.widgets.support.QuestionWidgetHelpers
2424
import org.odk.collect.androidshared.system.CameraUtils
25-
import org.odk.collect.strings.R
25+
import org.odk.collect.strings.R.string
2626
import org.robolectric.Shadows
2727
import org.robolectric.shadows.ShadowToast
2828

@@ -51,15 +51,15 @@ class BarcodeWidgetTest {
5151
val widget = createWidget(QuestionWidgetHelpers.promptWithAnswer(StringData("blah")))
5252
assertThat(
5353
widget.binding.barcodeButton.text.toString(),
54-
equalTo(widgetTestActivity.getString(R.string.replace_barcode))
54+
equalTo(widgetTestActivity.getString(string.replace_barcode))
5555
)
5656
}
5757

5858
@Test
5959
fun `Display the answer if answer is present`() {
6060
val widget = createWidget(QuestionWidgetHelpers.promptWithAnswer(StringData("blah")))
6161
assertThat(
62-
widget.binding.barcodeAnswerText.text.toString(),
62+
widget.binding.answerView.getAnswer(),
6363
equalTo("blah")
6464
)
6565
}
@@ -86,12 +86,12 @@ class BarcodeWidgetTest {
8686
widget.clearAnswer()
8787

8888
assertThat(
89-
widget.binding.barcodeAnswerText.text.toString(),
89+
widget.binding.answerView.getAnswer(),
9090
equalTo("")
9191
)
9292
assertThat(
9393
widget.binding.barcodeButton.text.toString(),
94-
equalTo(widgetTestActivity.getString(R.string.get_barcode))
94+
equalTo(widgetTestActivity.getString(string.get_barcode))
9595
)
9696
}
9797

@@ -109,7 +109,7 @@ class BarcodeWidgetTest {
109109
val widget = createWidget(QuestionWidgetHelpers.promptWithAnswer(null))
110110
widget.setData("\ud800blah\b")
111111
assertThat(
112-
widget.binding.barcodeAnswerText.text.toString(),
112+
widget.binding.answerView.getAnswer(),
113113
equalTo("blah")
114114
)
115115
}
@@ -120,7 +120,7 @@ class BarcodeWidgetTest {
120120
widget.setData("\ud800blah\b")
121121
assertThat(
122122
widget.binding.barcodeButton.text,
123-
equalTo(widgetTestActivity.getString(R.string.replace_barcode))
123+
equalTo(widgetTestActivity.getString(string.replace_barcode))
124124
)
125125
}
126126

@@ -138,10 +138,10 @@ class BarcodeWidgetTest {
138138
val widget = createWidget(QuestionWidgetHelpers.promptWithAnswer(null))
139139
widget.setOnLongClickListener(listener)
140140
widget.binding.barcodeButton.performLongClick()
141-
widget.binding.barcodeAnswerText.performLongClick()
141+
widget.binding.answerView.performLongClick()
142142

143143
verify(listener).onLongClick(widget.binding.barcodeButton)
144-
verify(listener).onLongClick(widget.binding.barcodeAnswerText)
144+
verify(listener).onLongClick(widget.binding.answerView)
145145
}
146146

147147
@Test
@@ -179,7 +179,7 @@ class BarcodeWidgetTest {
179179

180180
assertThat(
181181
ShadowToast.getTextOfLatestToast(),
182-
equalTo(widgetTestActivity.getString(R.string.error_front_camera_unavailable))
182+
equalTo(widgetTestActivity.getString(string.error_front_camera_unavailable))
183183
)
184184
}
185185

@@ -207,24 +207,24 @@ class BarcodeWidgetTest {
207207

208208
// Check initial value is not shown
209209
assertThat(
210-
widget.binding.barcodeAnswerText.visibility,
210+
widget.binding.answerView.findViewById<View>(R.id.barcode_widget_answer).visibility,
211211
equalTo(View.GONE)
212212
)
213213
assertThat(
214214
widget.binding.barcodeButton.text,
215-
equalTo(widgetTestActivity.getString(R.string.replace_barcode))
215+
equalTo(widgetTestActivity.getString(string.replace_barcode))
216216
)
217-
assertThat(widget.answer, Matchers.equalTo(StringData("original contents")))
217+
assertThat(widget.answer, equalTo(StringData("original contents")))
218218

219219
// Check updates aren't shown
220220
widget.setData("updated contents")
221221
assertThat(
222-
widget.binding.barcodeAnswerText.visibility,
222+
widget.binding.answerView.findViewById<View>(R.id.barcode_widget_answer).visibility,
223223
equalTo(View.GONE)
224224
)
225225
assertThat(
226226
widget.binding.barcodeButton.text,
227-
equalTo(widgetTestActivity.getString(R.string.replace_barcode))
227+
equalTo(widgetTestActivity.getString(string.replace_barcode))
228228
)
229229
assertThat(
230230
widget.answer,

0 commit comments

Comments
 (0)