Skip to content

Commit baf7cb6

Browse files
HayesGordonHayesGordon
HayesGordon
andcommitted
feat: android nested text runs
Diffs= 68d6cda32 feat: android nested text runs (#8126) Co-authored-by: Gordon <pggordonhayes@gmail.com>
1 parent d8b5aad commit baf7cb6

File tree

14 files changed

+508
-19
lines changed

14 files changed

+508
-19
lines changed

.rive_head

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c67b67083abe9d1448137122aeb76f20549ae89b
1+
68d6cda329f2252242dca46b92cb2bc552ee6bfa

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<activity android:name=".LowLevelActivity" />
4848
<activity android:name=".SimpleStateMachineActivity" />
4949
<activity android:name=".NestedInputActivity" />
50+
<activity android:name=".NestedTextRunActivity" />
5051
<activity android:name=".HttpActivity" />
5152
<activity android:name=".ButtonActivity" />
5253
<activity android:name=".BlendActivity" />

app/src/main/java/app/rive/runtime/example/DynamicTextActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class DynamicTextActivity : AppCompatActivity(), TextWatcher {
3838
textRun?.text?.let { Log.i("text-value-run", "Run before change: $it") }
3939

4040
// or you can get the current value with:
41-
// animationView.getTextRunValue("name")
41+
// animationView.getTextRunValue("name").let { Log.i("text-value-run", "Run before change: $it") }
4242
}
4343

4444
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

app/src/main/java/app/rive/runtime/example/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class MainActivity : AppCompatActivity() {
2121
Pair(R.id.go_http, HttpActivity::class.java),
2222
Pair(R.id.go_simple_state_machine, SimpleStateMachineActivity::class.java),
2323
Pair(R.id.go_nested_input, NestedInputActivity::class.java),
24+
Pair(R.id.go_nested_text_run, NestedTextRunActivity::class.java),
2425
Pair(R.id.go_button, ButtonActivity::class.java),
2526
Pair(R.id.go_blend, BlendActivity::class.java),
2627
Pair(R.id.go_metrics, MetricsActivity::class.java),
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package app.rive.runtime.example
2+
3+
import android.os.Bundle
4+
import android.util.Log
5+
import android.view.View
6+
import android.widget.Button
7+
import android.widget.RadioButton
8+
import androidx.appcompat.app.AppCompatActivity
9+
import app.rive.runtime.kotlin.RiveAnimationView
10+
11+
class NestedTextRunActivity : AppCompatActivity() {
12+
13+
private val animationView by lazy(LazyThreadSafetyMode.NONE) {
14+
findViewById<RiveAnimationView>(R.id.nested_text_run)
15+
}
16+
17+
fun onButtonClick(view: View) {
18+
if (view is Button) {
19+
when (view.id) {
20+
R.id.set_b1 -> {
21+
Log.d("nested-text-run", animationView.getTextRunValue("ArtboardBRun", "ArtboardB-1").toString())
22+
animationView.setTextRunValue(
23+
textRunName = "ArtboardBRun",
24+
textValue = "ArtboardB-1 Updated",
25+
path = "ArtboardB-1"
26+
)
27+
Log.d("nested-text-run", animationView.getTextRunValue("ArtboardBRun", "ArtboardB-1").toString())
28+
}
29+
R.id.set_b2 -> {
30+
animationView.setTextRunValue(
31+
"ArtboardBRun",
32+
"ArtboardB-2 Updated",
33+
"ArtboardB-2"
34+
)
35+
}
36+
R.id.set_b1_c1 -> {
37+
animationView.setTextRunValue(
38+
"ArtboardCRun",
39+
"ArtboardB-1/C-1 Updated",
40+
"ArtboardB-1/ArtboardC-1"
41+
)
42+
}
43+
R.id.set_b1_c2 -> {
44+
animationView.setTextRunValue(
45+
"ArtboardCRun",
46+
"ArtboardB-1/C-2 Updated",
47+
"ArtboardB-1/ArtboardC-2"
48+
)
49+
}
50+
R.id.set_b2_c1 -> {
51+
animationView.setTextRunValue(
52+
"ArtboardCRun",
53+
"ArtboardB-2/C-1 Updated",
54+
"ArtboardB-2/ArtboardC-1"
55+
)
56+
}
57+
R.id.set_b2_c2 -> {
58+
animationView.setTextRunValue(
59+
"ArtboardCRun",
60+
"ArtboardB-2/C-2 Updated",
61+
"ArtboardB-2/ArtboardC-2"
62+
)
63+
}
64+
}
65+
}
66+
}
67+
68+
override fun onCreate(savedInstanceState: Bundle?) {
69+
super.onCreate(savedInstanceState)
70+
setContentView(R.layout.nested_text_run)
71+
}
72+
}

app/src/main/res/layout/main.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@
127127
android:text="Nested Inputs"
128128
android:textColor="@color/textColorPrimary" />
129129

130+
<Button
131+
android:id="@+id/go_nested_text_run"
132+
style="@style/Widget.Material3.Button"
133+
android:layout_width="fill_parent"
134+
android:layout_height="wrap_content"
135+
android:layout_marginVertical="4dp"
136+
android:text="Nested Text Runs"
137+
android:textColor="@color/textColorPrimary" />
138+
130139
<Button
131140
android:id="@+id/go_button"
132141
style="@style/Widget.Material3.Button"
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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:layout_width="match_parent"
6+
android:layout_height="match_parent"
7+
tools:context=".MainActivity">
8+
9+
<LinearLayout
10+
android:layout_width="fill_parent"
11+
android:layout_height="fill_parent"
12+
android:orientation="vertical"
13+
app:layout_constraintStart_toStartOf="parent"
14+
app:layout_constraintTop_toTopOf="parent">
15+
16+
<app.rive.runtime.kotlin.RiveAnimationView
17+
android:id="@+id/nested_text_run"
18+
android:layout_width="match_parent"
19+
android:layout_height="400dp"
20+
app:riveResource="@raw/runtime_nested_text_runs"
21+
app:riveArtboard="ArtboardA"
22+
app:riveStateMachine="State Machine 1" />
23+
24+
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
25+
android:layout_width="match_parent"
26+
android:layout_height="wrap_content"
27+
28+
android:orientation="vertical">
29+
30+
<Button
31+
android:id="@+id/set_b1"
32+
android:layout_width="wrap_content"
33+
android:layout_height="wrap_content"
34+
android:onClick="onButtonClick"
35+
android:textColor="@color/textColorPrimary"
36+
android:text="Set B1" />
37+
38+
<Button
39+
android:id="@+id/set_b2"
40+
android:layout_width="wrap_content"
41+
android:layout_height="wrap_content"
42+
android:onClick="onButtonClick"
43+
android:textColor="@color/textColorPrimary"
44+
android:text="Set B2" />
45+
46+
<Button
47+
android:id="@+id/set_b1_c1"
48+
android:layout_width="wrap_content"
49+
android:layout_height="wrap_content"
50+
android:onClick="onButtonClick"
51+
android:textColor="@color/textColorPrimary"
52+
android:text="Set B1/C1" />
53+
54+
<Button
55+
android:id="@+id/set_b1_c2"
56+
android:layout_width="wrap_content"
57+
android:layout_height="wrap_content"
58+
android:onClick="onButtonClick"
59+
android:textColor="@color/textColorPrimary"
60+
android:text="Set B1/C2" />
61+
62+
<Button
63+
android:id="@+id/set_b2_c1"
64+
android:layout_width="wrap_content"
65+
android:layout_height="wrap_content"
66+
android:onClick="onButtonClick"
67+
android:textColor="@color/textColorPrimary"
68+
android:text="Set B2/C1" />
69+
70+
<Button
71+
android:id="@+id/set_b2_c2"
72+
android:layout_width="wrap_content"
73+
android:layout_height="wrap_content"
74+
android:onClick="onButtonClick"
75+
android:textColor="@color/textColorPrimary"
76+
android:text="Set B2/C2" />
77+
78+
</RadioGroup>
79+
</LinearLayout>
80+
81+
</androidx.constraintlayout.widget.ConstraintLayout>
Binary file not shown.

kotlin/src/androidTest/java/app/rive/runtime/kotlin/core/RiveTextValueRunTest.kt

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package app.rive.runtime.kotlin.core
22

33
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import androidx.test.internal.runner.junit4.statement.UiThreadStatement
5+
import app.rive.runtime.kotlin.RiveAnimationView
6+
import app.rive.runtime.kotlin.core.errors.RiveException
47
import app.rive.runtime.kotlin.core.errors.TextValueRunException
58
import app.rive.runtime.kotlin.test.R
69
import org.junit.Assert.assertEquals
10+
import org.junit.Assert.assertTrue
11+
import org.junit.Assert.fail
712
import org.junit.Before
813
import org.junit.Test
914
import org.junit.runner.RunWith
@@ -14,25 +19,162 @@ class RiveTextValueRunTest {
1419
private val testUtils = TestUtils()
1520
private val appContext = testUtils.context
1621
private lateinit var file: File
22+
private lateinit var nestePathFile: File
23+
private lateinit var mockView: RiveAnimationView
1724

1825
@Before
1926
fun init() {
2027
file = File(
2128
appContext.resources.openRawResource(R.raw.hello_world_text).readBytes()
2229
)
30+
nestePathFile= File(
31+
appContext.resources.openRawResource(R.raw.runtime_nested_text_runs).readBytes()
32+
)
33+
34+
mockView = TestUtils.MockRiveAnimationView(appContext)
2335
}
2436

2537
@Test
2638
fun read_and_update_text_run() {
27-
val textRun = file.firstArtboard.textRun("name")
39+
var artboard = file.firstArtboard;
40+
assertEquals(artboard.dependencies.count(), 0)
41+
42+
val textRun = artboard.textRun("name")
43+
44+
// Confirm original value
2845
assertEquals("world", textRun.text)
46+
assertEquals("world", artboard.getTextRunValue("name"))
47+
2948
var updateValue = "username"
49+
50+
// Setting the text run directly
3051
textRun.text = updateValue
3152
assertEquals(updateValue, textRun.text)
53+
assertEquals(updateValue, artboard.getTextRunValue("name"))
54+
55+
// Setting through the helper method
56+
updateValue = "new value"
57+
artboard.setTextRunValue("name",updateValue)
58+
assertEquals(updateValue, textRun.text)
59+
assertEquals(updateValue, artboard.getTextRunValue("name"))
60+
61+
// Only accessing .textRun should add to the dependencies.
62+
assertEquals(artboard.dependencies.count(), 1)
3263
}
3364

3465
@Test(expected = TextValueRunException::class)
3566
fun read_non_existing_text_run() {
3667
file.firstArtboard.textRun("wrong-name")
3768
}
69+
70+
@Test
71+
fun read_and_update_text_run_at_path() {
72+
val artboard = nestePathFile.firstArtboard;
73+
assertEquals(artboard.dependencies.count(), 0)
74+
75+
nestedTextRunHelper(artboard, "ArtboardBRun", "ArtboardB-1","Artboard B Run", "ArtboardB-1" )
76+
nestedTextRunHelper(artboard, "ArtboardBRun", "ArtboardB-2","Artboard B Run", "ArtboardB-2" )
77+
nestedTextRunHelper(artboard, "ArtboardCRun", "ArtboardB-1/ArtboardC-1","Artboard C Run", "ArtboardB-1/C-1" )
78+
nestedTextRunHelper(artboard, "ArtboardCRun", "ArtboardB-1/ArtboardC-2","Artboard C Run", "ArtboardB-1/C-2" )
79+
nestedTextRunHelper(artboard, "ArtboardCRun", "ArtboardB-2/ArtboardC-1","Artboard C Run", "ArtboardB-2/C-1" )
80+
nestedTextRunHelper(artboard, "ArtboardCRun", "ArtboardB-2/ArtboardC-2","Artboard C Run", "ArtboardB-2/C-2" )
81+
82+
// Only accessing the textRun directly should increase the dependency.
83+
// Calling getTextRunValue and setTextRunValue should not.
84+
assertEquals(artboard.dependencies.count(), 6)
85+
}
86+
87+
private fun nestedTextRunHelper(artboard: Artboard, name: String, path: String, originalValue: String, updatedValue: String) {
88+
// Get the text value run. This should increase the dependency count
89+
val textRun = artboard.textRun(name, path = path)
90+
91+
// Assert the original value is correct
92+
assertEquals(originalValue, textRun.text)
93+
assertEquals(originalValue, artboard.getTextRunValue(name, path = path))
94+
95+
// Update the `textRun` reference directly
96+
textRun.text = updatedValue
97+
assertEquals(updatedValue, textRun.text)
98+
assertEquals(updatedValue, artboard.getTextRunValue(name, path = path))
99+
100+
// Update the text run back to the original value through the helper method
101+
artboard.setTextRunValue(name, originalValue, path)
102+
assertEquals(originalValue, textRun.text)
103+
assertEquals(originalValue, artboard.getTextRunValue(name, path = path))
104+
}
105+
106+
@Test
107+
fun viewSetGetTextRun() {
108+
UiThreadStatement.runOnUiThread {
109+
mockView.setRiveResource(R.raw.hello_world_text, autoplay = false)
110+
mockView.play(listOf("State Machine 1"), areStateMachines = true)
111+
assertEquals(true, mockView.isPlaying)
112+
113+
assertEquals(mockView.controller.activeArtboard?.dependencies?.count(), 1)
114+
val textValue = mockView.getTextRunValue("name")
115+
assertEquals(textValue, "world")
116+
117+
var newValue = "New Value";
118+
mockView.setTextRunValue("name", newValue)
119+
val textValueUpdated = mockView.getTextRunValue("name")
120+
assertEquals(textValueUpdated, newValue)
121+
122+
assertEquals(mockView.controller.activeArtboard?.dependencies?.count(), 1)
123+
124+
// Test for throwing an error when giving a wrong text run name
125+
try {
126+
mockView.setTextRunValue("non_existent_text_run", "Some Value")
127+
fail("Expected an exception to be thrown")
128+
} catch (e: Exception) {
129+
assertTrue(e is RiveException)
130+
assertTrue(e.message?.contains("No Rive TextValueRun found") == true)
131+
}
132+
133+
// Test for throwing an error when giving a wrong text run name for a nested artboard
134+
try {
135+
mockView.setTextRunValue("non_existent_text_run", "Some Value", "ArtboardB-1")
136+
fail("Expected an exception to be thrown")
137+
} catch (e: Exception) {
138+
assertTrue(e is RiveException)
139+
assertTrue(e.message?.contains("No Rive TextValueRun found") == true)
140+
}
141+
}
142+
}
143+
@Test
144+
fun viewSetGetNestedTextRun() {
145+
UiThreadStatement.runOnUiThread {
146+
mockView.setRiveResource(R.raw.runtime_nested_text_runs, autoplay = false)
147+
mockView.play(listOf("State Machine 1"), areStateMachines = true)
148+
assertEquals(true, mockView.isPlaying)
149+
150+
assertEquals(mockView.controller.activeArtboard?.dependencies?.count(), 1)
151+
val textValue = mockView.getTextRunValue("ArtboardBRun", "ArtboardB-1")
152+
assertEquals(textValue, "Artboard B Run")
153+
154+
var newValue = "New Value";
155+
mockView.setTextRunValue("ArtboardBRun", newValue, "ArtboardB-1" )
156+
val textValueUpdated = mockView.getTextRunValue("ArtboardBRun", "ArtboardB-1")
157+
assertEquals(textValueUpdated, newValue)
158+
159+
assertEquals(mockView.controller.activeArtboard?.dependencies?.count(), 1)
160+
161+
// Test for throwing an error when giving a wrong text run name for a nested artboard
162+
try {
163+
mockView.setTextRunValue("non_existent_text_run", "Some Value", "ArtboardB-1")
164+
fail("Expected an exception to be thrown")
165+
} catch (e: Exception) {
166+
assertTrue(e is RiveException)
167+
assertTrue(e.message?.contains("No Rive TextValueRun found") == true)
168+
}
169+
170+
// Test for throwing an error when giving a wrong path for a nested artboard
171+
try {
172+
mockView.setTextRunValue("ArtboardBRun", "Some Value", "non_existent_path")
173+
fail("Expected an exception to be thrown")
174+
} catch (e: Exception) {
175+
assertTrue(e is RiveException)
176+
assertTrue(e.message?.contains("No Rive TextValueRun found") == true)
177+
}
178+
}
179+
}
38180
}
Binary file not shown.

0 commit comments

Comments
 (0)