Skip to content

Commit

Permalink
Add snippets for interop page. (#20)
Browse files Browse the repository at this point in the history
* Add snippets for interop page.

* Add more snippets.

* Fix snippet tags.
  • Loading branch information
arriolac authored Dec 1, 2022
1 parent 66bb8fe commit c381c78
Show file tree
Hide file tree
Showing 16 changed files with 669 additions and 11 deletions.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ buildscript {
}
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath 'com.android.tools.build:gradle:7.2.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

// NOTE: Do not place your application dependencies here; they belong
Expand All @@ -21,7 +21,7 @@ buildscript {
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

Expand Down
17 changes: 12 additions & 5 deletions compose/snippets/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ android {
}
buildFeatures {
compose true
viewBinding true
}
composeOptions {
kotlinCompilerExtensionVersion compose_compiler_version
Expand All @@ -49,17 +50,23 @@ android {
dependencies {
def composeBom = platform('androidx.compose:compose-bom:2022.11.00')
implementation(composeBom)
implementation("io.coil-kt:coil-compose:2.2.2")
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.activity:activity-compose:1.6.1'
implementation "io.coil-kt:coil-compose:2.2.2"
implementation "androidx.compose.ui:ui"
implementation "androidx.compose.ui:ui-tooling-preview"
implementation "androidx.compose.ui:ui-viewbinding"
implementation "androidx.fragment:fragment:1.5.4"
implementation 'androidx.activity:activity-compose:1.6.1'
implementation 'androidx.compose.material3:material3:1.0.1'
implementation 'androidx.compose.runtime:runtime-livedata'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
implementation 'androidx.navigation:navigation-compose:2.5.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation(composeBom)
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4"
androidTestImplementation "androidx.compose.ui:ui-test-junit4:"
debugImplementation "androidx.compose.ui:ui-tooling"
debugImplementation "androidx.compose.ui:ui-test-manifest"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.compose.snippets.interop

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.platform.app.InstrumentationRegistry
import com.example.compose.snippets.MyActivity
import com.example.compose.snippets.R
import org.junit.Rule
import org.junit.Test

// [START android_compose_interop_add_compose_test_mixed]
class MyActivityTest {
@Rule
@JvmField
val composeTestRule = createAndroidComposeRule<MyActivity>()

@Test
fun testGreeting() {
val greeting = InstrumentationRegistry.getInstrumentation()
.targetContext.resources.getString(R.string.greeting)

composeTestRule.onNodeWithText(greeting).assertIsDisplayed()
}
}
// [END android_compose_interop_add_compose_test_mixed]
3 changes: 3 additions & 0 deletions compose/snippets/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
android:name="android.app.lib_name"
android:value="" />
</activity>

<activity android:name="MyActivity"
android:exported="false"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.compose.snippets

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text
import androidx.compose.ui.res.stringResource

class MyActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text(text = stringResource(id = R.string.greeting))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
@file:OptIn(ExperimentalMaterial3Api::class)

package com.example.compose.snippets.interop

import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController

// [START android_compose_interop_existing_arch_viewmodels_in_compose]
class GreetingActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContent {
MaterialTheme {
Column {
GreetingScreen("user1")
GreetingScreen("user2")
}
}
}
}
}

@Composable
fun GreetingScreen(
userId: String,
viewModel: GreetingViewModel = viewModel(
factory = GreetingViewModelFactory(userId)
)
) {
val messageUser by viewModel.message.observeAsState("")

Text(messageUser)
}

class GreetingViewModel(private val userId: String) : ViewModel() {
private val _message = MutableLiveData("Hi $userId")
val message: LiveData<String> = _message
}

class GreetingViewModelFactory(private val userId: String): ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return GreetingViewModel(userId) as T
}
}
// [END android_compose_interop_existing_arch_viewmodels_in_compose]

// [START android_compose_interop_existing_arch_viewmodels_in_compose_nav_graph]
@Composable
fun MyApp() {
NavHost(rememberNavController(), startDestination = "profile/{userId}") {
/* ... */
composable("profile/{userId}") { backStackEntry ->
GreetingScreen(backStackEntry.arguments?.getString("userId") ?: "")
}
}
}
// [END android_compose_interop_existing_arch_viewmodels_in_compose_nav_graph]

// [START android_compose_interop_existing_arch_views_sot]
class CustomViewGroup @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : LinearLayout(context, attrs, defStyle) {

// Source of truth in the View system as mutableStateOf
// to make it thread-safe for Compose
private var text by mutableStateOf("")

private val textView: TextView

init {
orientation = VERTICAL

textView = TextView(context)
val composeView = ComposeView(context).apply {
setContent {
MaterialTheme {
TextField(value = text, onValueChange = { updateState(it) })
}
}
}

addView(textView)
addView(composeView)
}

// Update both the source of truth and the TextView
private fun updateState(newValue: String) {
text = newValue
textView.text = newValue
}
}
// [END android_compose_interop_existing_arch_views_sot]
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.example.compose.snippets.interop

import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import androidx.activity.ComponentActivity
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.AbstractComposeView
import com.example.compose.snippets.R
import com.example.compose.snippets.databinding.ActivityExampleBinding

// [START android_compose_interop_existing_ui_shared]
@Composable
fun CallToActionButton(
text: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Button(
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.secondary
),
onClick = onClick,
modifier = modifier,
) {
Text(text)
}
}

class CallToActionViewButton @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : AbstractComposeView(context, attrs, defStyle) {

var text by mutableStateOf("")
var onClick by mutableStateOf({})

@Composable
override fun Content() {
YourAppTheme {
CallToActionButton(text, onClick)
}
}
}
// [START_EXCLUDE silent]
@Composable
fun YourAppTheme(content: @Composable () -> Unit) {
}
// [END_EXCLUDE]
// [END android_compose_interop_existing_ui_shared]

// [START android_compose_interop_existing_ui_shared_view_binding]
class ViewBindingActivity : ComponentActivity() {

private lateinit var binding: ActivityExampleBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityExampleBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.callToAction.apply {
text = getString(R.string.greeting)
onClick = { /* Do something */ }
}
}
}
// [END android_compose_interop_existing_ui_shared_view_binding]
Loading

0 comments on commit c381c78

Please sign in to comment.