Skip to content

Commit c381c78

Browse files
authored
Add snippets for interop page. (#20)
* Add snippets for interop page. * Add more snippets. * Fix snippet tags.
1 parent 66bb8fe commit c381c78

File tree

16 files changed

+669
-11
lines changed

16 files changed

+669
-11
lines changed

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ buildscript {
77
}
88
repositories {
99
google()
10-
jcenter()
10+
mavenCentral()
1111
}
1212
dependencies {
13-
classpath 'com.android.tools.build:gradle:7.1.3'
13+
classpath 'com.android.tools.build:gradle:7.2.2'
1414
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1515

1616
// NOTE: Do not place your application dependencies here; they belong
@@ -21,7 +21,7 @@ buildscript {
2121
allprojects {
2222
repositories {
2323
google()
24-
jcenter()
24+
mavenCentral()
2525
}
2626
}
2727

compose/snippets/build.gradle

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ android {
3535
}
3636
buildFeatures {
3737
compose true
38+
viewBinding true
3839
}
3940
composeOptions {
4041
kotlinCompilerExtensionVersion compose_compiler_version
@@ -49,17 +50,23 @@ android {
4950
dependencies {
5051
def composeBom = platform('androidx.compose:compose-bom:2022.11.00')
5152
implementation(composeBom)
52-
implementation("io.coil-kt:coil-compose:2.2.2")
53-
implementation 'androidx.core:core-ktx:1.9.0'
54-
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
55-
implementation 'androidx.activity:activity-compose:1.6.1'
53+
implementation "io.coil-kt:coil-compose:2.2.2"
5654
implementation "androidx.compose.ui:ui"
5755
implementation "androidx.compose.ui:ui-tooling-preview"
56+
implementation "androidx.compose.ui:ui-viewbinding"
57+
implementation "androidx.fragment:fragment:1.5.4"
58+
implementation 'androidx.activity:activity-compose:1.6.1'
5859
implementation 'androidx.compose.material3:material3:1.0.1'
60+
implementation 'androidx.compose.runtime:runtime-livedata'
61+
implementation 'androidx.core:core-ktx:1.9.0'
62+
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
63+
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
64+
implementation 'androidx.navigation:navigation-compose:2.5.3'
5965
testImplementation 'junit:junit:4.13.2'
66+
androidTestImplementation(composeBom)
6067
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
6168
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
62-
androidTestImplementation "androidx.compose.ui:ui-test-junit4"
69+
androidTestImplementation "androidx.compose.ui:ui-test-junit4:"
6370
debugImplementation "androidx.compose.ui:ui-tooling"
6471
debugImplementation "androidx.compose.ui:ui-test-manifest"
6572
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.example.compose.snippets.interop
2+
3+
import androidx.compose.ui.test.assertIsDisplayed
4+
import androidx.compose.ui.test.junit4.createAndroidComposeRule
5+
import androidx.compose.ui.test.onNodeWithText
6+
import androidx.test.platform.app.InstrumentationRegistry
7+
import com.example.compose.snippets.MyActivity
8+
import com.example.compose.snippets.R
9+
import org.junit.Rule
10+
import org.junit.Test
11+
12+
// [START android_compose_interop_add_compose_test_mixed]
13+
class MyActivityTest {
14+
@Rule
15+
@JvmField
16+
val composeTestRule = createAndroidComposeRule<MyActivity>()
17+
18+
@Test
19+
fun testGreeting() {
20+
val greeting = InstrumentationRegistry.getInstrumentation()
21+
.targetContext.resources.getString(R.string.greeting)
22+
23+
composeTestRule.onNodeWithText(greeting).assertIsDisplayed()
24+
}
25+
}
26+
// [END android_compose_interop_add_compose_test_mixed]

compose/snippets/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
android:name="android.app.lib_name"
2424
android:value="" />
2525
</activity>
26+
27+
<activity android:name="MyActivity"
28+
android:exported="false"/>
2629
</application>
2730

2831
</manifest>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.example.compose.snippets
2+
3+
import android.os.Bundle
4+
import androidx.activity.ComponentActivity
5+
import androidx.activity.compose.setContent
6+
import androidx.compose.material3.Text
7+
import androidx.compose.ui.res.stringResource
8+
9+
class MyActivity : ComponentActivity() {
10+
override fun onCreate(savedInstanceState: Bundle?) {
11+
super.onCreate(savedInstanceState)
12+
setContent {
13+
Text(text = stringResource(id = R.string.greeting))
14+
}
15+
}
16+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
@file:OptIn(ExperimentalMaterial3Api::class)
2+
3+
package com.example.compose.snippets.interop
4+
5+
import android.content.Context
6+
import android.os.Bundle
7+
import android.util.AttributeSet
8+
import android.widget.LinearLayout
9+
import android.widget.TextView
10+
import androidx.activity.ComponentActivity
11+
import androidx.activity.compose.setContent
12+
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.material3.ExperimentalMaterial3Api
14+
import androidx.compose.material3.MaterialTheme
15+
import androidx.compose.material3.Text
16+
import androidx.compose.material3.TextField
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.runtime.getValue
19+
import androidx.compose.runtime.livedata.observeAsState
20+
import androidx.compose.runtime.mutableStateOf
21+
import androidx.compose.runtime.setValue
22+
import androidx.compose.ui.platform.ComposeView
23+
import androidx.lifecycle.LiveData
24+
import androidx.lifecycle.MutableLiveData
25+
import androidx.lifecycle.ViewModel
26+
import androidx.lifecycle.ViewModelProvider
27+
import androidx.lifecycle.viewmodel.compose.viewModel
28+
import androidx.navigation.compose.NavHost
29+
import androidx.navigation.compose.composable
30+
import androidx.navigation.compose.rememberNavController
31+
32+
// [START android_compose_interop_existing_arch_viewmodels_in_compose]
33+
class GreetingActivity : ComponentActivity() {
34+
override fun onCreate(savedInstanceState: Bundle?) {
35+
super.onCreate(savedInstanceState)
36+
37+
setContent {
38+
MaterialTheme {
39+
Column {
40+
GreetingScreen("user1")
41+
GreetingScreen("user2")
42+
}
43+
}
44+
}
45+
}
46+
}
47+
48+
@Composable
49+
fun GreetingScreen(
50+
userId: String,
51+
viewModel: GreetingViewModel = viewModel(
52+
factory = GreetingViewModelFactory(userId)
53+
)
54+
) {
55+
val messageUser by viewModel.message.observeAsState("")
56+
57+
Text(messageUser)
58+
}
59+
60+
class GreetingViewModel(private val userId: String) : ViewModel() {
61+
private val _message = MutableLiveData("Hi $userId")
62+
val message: LiveData<String> = _message
63+
}
64+
65+
class GreetingViewModelFactory(private val userId: String): ViewModelProvider.Factory {
66+
@Suppress("UNCHECKED_CAST")
67+
override fun <T : ViewModel> create(modelClass: Class<T>): T {
68+
return GreetingViewModel(userId) as T
69+
}
70+
}
71+
// [END android_compose_interop_existing_arch_viewmodels_in_compose]
72+
73+
// [START android_compose_interop_existing_arch_viewmodels_in_compose_nav_graph]
74+
@Composable
75+
fun MyApp() {
76+
NavHost(rememberNavController(), startDestination = "profile/{userId}") {
77+
/* ... */
78+
composable("profile/{userId}") { backStackEntry ->
79+
GreetingScreen(backStackEntry.arguments?.getString("userId") ?: "")
80+
}
81+
}
82+
}
83+
// [END android_compose_interop_existing_arch_viewmodels_in_compose_nav_graph]
84+
85+
// [START android_compose_interop_existing_arch_views_sot]
86+
class CustomViewGroup @JvmOverloads constructor(
87+
context: Context,
88+
attrs: AttributeSet? = null,
89+
defStyle: Int = 0
90+
) : LinearLayout(context, attrs, defStyle) {
91+
92+
// Source of truth in the View system as mutableStateOf
93+
// to make it thread-safe for Compose
94+
private var text by mutableStateOf("")
95+
96+
private val textView: TextView
97+
98+
init {
99+
orientation = VERTICAL
100+
101+
textView = TextView(context)
102+
val composeView = ComposeView(context).apply {
103+
setContent {
104+
MaterialTheme {
105+
TextField(value = text, onValueChange = { updateState(it) })
106+
}
107+
}
108+
}
109+
110+
addView(textView)
111+
addView(composeView)
112+
}
113+
114+
// Update both the source of truth and the TextView
115+
private fun updateState(newValue: String) {
116+
text = newValue
117+
textView.text = newValue
118+
}
119+
}
120+
// [END android_compose_interop_existing_arch_views_sot]
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.example.compose.snippets.interop
2+
3+
import android.app.Activity
4+
import android.content.Context
5+
import android.os.Bundle
6+
import android.util.AttributeSet
7+
import androidx.activity.ComponentActivity
8+
import androidx.compose.material3.Button
9+
import androidx.compose.material3.ButtonDefaults
10+
import androidx.compose.material3.MaterialTheme
11+
import androidx.compose.material3.Text
12+
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.getValue
14+
import androidx.compose.runtime.mutableStateOf
15+
import androidx.compose.runtime.setValue
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.platform.AbstractComposeView
18+
import com.example.compose.snippets.R
19+
import com.example.compose.snippets.databinding.ActivityExampleBinding
20+
21+
// [START android_compose_interop_existing_ui_shared]
22+
@Composable
23+
fun CallToActionButton(
24+
text: String,
25+
onClick: () -> Unit,
26+
modifier: Modifier = Modifier,
27+
) {
28+
Button(
29+
colors = ButtonDefaults.buttonColors(
30+
containerColor = MaterialTheme.colorScheme.secondary
31+
),
32+
onClick = onClick,
33+
modifier = modifier,
34+
) {
35+
Text(text)
36+
}
37+
}
38+
39+
class CallToActionViewButton @JvmOverloads constructor(
40+
context: Context,
41+
attrs: AttributeSet? = null,
42+
defStyle: Int = 0
43+
) : AbstractComposeView(context, attrs, defStyle) {
44+
45+
var text by mutableStateOf("")
46+
var onClick by mutableStateOf({})
47+
48+
@Composable
49+
override fun Content() {
50+
YourAppTheme {
51+
CallToActionButton(text, onClick)
52+
}
53+
}
54+
}
55+
// [START_EXCLUDE silent]
56+
@Composable
57+
fun YourAppTheme(content: @Composable () -> Unit) {
58+
}
59+
// [END_EXCLUDE]
60+
// [END android_compose_interop_existing_ui_shared]
61+
62+
// [START android_compose_interop_existing_ui_shared_view_binding]
63+
class ViewBindingActivity : ComponentActivity() {
64+
65+
private lateinit var binding: ActivityExampleBinding
66+
67+
override fun onCreate(savedInstanceState: Bundle?) {
68+
super.onCreate(savedInstanceState)
69+
binding = ActivityExampleBinding.inflate(layoutInflater)
70+
setContentView(binding.root)
71+
72+
binding.callToAction.apply {
73+
text = getString(R.string.greeting)
74+
onClick = { /* Do something */ }
75+
}
76+
}
77+
}
78+
// [END android_compose_interop_existing_ui_shared_view_binding]

0 commit comments

Comments
 (0)