100% found this document useful (1 vote)
345 views

Learn Jetpack Compose by Example

The document discusses Jetpack Compose, a new UI toolkit for Android that uses declarative UI definitions instead of imperative code. It provides examples of creating simple UI elements like text, images, alerts and layouts using Compose. The examples demonstrate how Compose allows defining UI in a declarative way using composable functions instead of traditional Android views and layouts. It also notes that Compose is still in early pre-alpha stage and the API is subject to change.

Uploaded by

Carott Vu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
345 views

Learn Jetpack Compose by Example

The document discusses Jetpack Compose, a new UI toolkit for Android that uses declarative UI definitions instead of imperative code. It provides examples of creating simple UI elements like text, images, alerts and layouts using Compose. The examples demonstrate how Compose allows defining UI in a declarative way using composable functions instead of traditional Android views and layouts. It also notes that Compose is still in early pre-alpha stage and the API is subject to change.

Uploaded by

Carott Vu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 95

Why do we need

Jetpack Compose?
Why do I need to
learn new things?

UI Toolkit is tied to the OS


State Management is tricky
Lots of context switching
Simple things still require a lot of code
Why do I need to
learn new things?

UI Toolkit is tied to the OS


State Management is tricky
Lots of context switching
Simple things still require a lot of code
Why do I need to
learn new things?

UI Toolkit is tied to the OS


State Management is tricky
Lots of context switching
Simple things still require a lot of code
Why do I need to
learn new things?

UI Toolkit is tied to the OS


State Management is tricky
Lots of context switching
Simple things still require a lot of code
Why do I need to
learn new things?

UI Toolkit is tied to the OS


State Management is tricky
Lots of context switching
Simple things still require a lot of code
Examples
Disclaimer

Examples are based on 0.1.0-dev14 version

Compose is still pre-alpha so things are constantly changing and


will continue to do so

Alpha release is expected in the next few months


Disclaimer

Examples are based on 0.1.0-dev14 version

Compose is still pre-alpha so things are constantly changing and


will continue to do so

Alpha release is expected in the next few months


Disclaimer

Examples are based on 0.1.0-dev14 version

Compose is still pre-alpha so things are constantly changing and


will continue to do so

Alpha release is expected in the next few months


Disclaimer

Examples are based on 0.1.0-dev14 version

Compose is still pre-alpha so things are constantly changing and


will continue to do so

Alpha release is expected in the next few months


Example: Hello World
class HelloWorldActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
class HelloWorldActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {

}
}
}
fun ComponentActivity.setContent(
recomposer: Recomposer = Recomposer.current(),
content: @Composable () -> Unit
): Composition {
// Some magic ✨🦄
}
class HelloWorldActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {

}
}
}
class HelloWorldActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text(text = "Hello World")
}
}
}
class HelloWorldActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text(text = "Hello World")
}
}
}
class HelloWorldActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text(text = "Hello World")
}
}
}
@Composable
fun CustomTextComponent() {
Text(text = "Hello World")
}
@Composable
fun CustomTextComponent(displayText: String) {
Text(
text = displayText,
style = TextStyle(
fontSize = 18.sp,
fontFamily = FontFamily.Monospace
)
)
}
@Composable
fun CustomTextComponent(displayText: String) {
Text(
text = displayText,
style = TextStyle(
fontSize = 18.sp,
fontFamily = FontFamily.Monospace
)
)
}
@Composable
fun CustomTextComponent(displayText: String) {
Text(
text = displayText,
style = TextStyle(
fontSize = 18.sp,
fontFamily = FontFamily.Monospace
)
)
}

@Preview
@Composable
fun CustomTextComponentPreview() {
CustomTextComponent("Hello World")
}
Example: Show an Image
@Composable
fun DrawableImage() {

}
@Composable
fun DrawableImage() {
val image = loadImageResource(R.drawable.lena)
}
@Composable
fun DrawableImage() {
val image = loadImageResource(R.drawable.lena)
image.resource.resource?.let {
Image(asset = it, modifier = Modifier.preferredSize(200.dp))
}
}
@Composable
fun DrawableImage(@DrawableRes resId: Int) {
val image = loadImageResource(resId)
image.resource.resource?.let {
Image(asset = it, modifier = Modifier.preferredSize(200.dp))
}
}
@Composable
fun DrawableImage(@DrawableRes resId: Int) {
val image = loadImageResource(resId)
image.resource.resource?.let {
Image(asset = it, modifier = Modifier.preferredSize(200.dp))
}
}
Example: Alert Dialog
// Classic Android

AlertDialog.Builder(context)
.setTitle("360|AnDev")
.setMessage("Isn't this conference amazing?")
.setPositiveButton(android.R.string.yes, null)
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
@Composable
fun AlertDialogComponent() {

}
@Composable
fun AlertDialogComponent() {
var showPopup by state { false }
}
@Composable
fun AlertDialogComponent() {
var showPopup by state { false }

Button(onClick = { showPopup = true }, backgroundColor = Color.DarkGray) {


Text(text = "Click Me")
}
}
@Composable
fun AlertDialogComponent() {
var showPopup by state { false }

Button(onClick = { showPopup = true }, backgroundColor = Color.DarkGray) {


Text(text = "Click Me")
}

if (showPopup) {
AlertDialog(
onCloseRequest = { showPopup = false },
text = {
Text("Congratulations! You just clicked the text successfully")
},
confirmButton = {
Button(
onClick = onPopupDismissed
){
Text(text = "Ok")
}
}
)
}
}
@Composable
fun AlertDialogComponent() {
var showPopup by state { false }

Button(onClick = { showPopup = true }, backgroundColor = Color.DarkGray) {


Text(text = "Click Me")
}

if (showPopup) {
AlertDialog(
onCloseRequest = { showPopup = false },
text = {
Text("Congratulations! You just clicked the text successfully")
},
confirmButton = {
Button(
onClick = onPopupDismissed
){
Text(text = "Ok")
}
}
)
}
}
@Composable
fun AlertDialogComponent() {
var showPopup by remember { mutableStateOf(false) }
val onButtonClicked = { showPopup = true }
val onPopupDismissed = { showPopup = false }

if (!showPopup) {
Button(onClick = onButtonClicked, backgroundColor = Color.DarkGray) {
Text(text = "Click Me")
}
} else {
AlertDialog(
onCloseRequest = onPopupDismissed,
text = {
Text("Congratulations! You just clicked the text successfully")
},
confirmButton = {
Button(
onClick = onPopupDismissed
){
Text(text = "Ok")
}
}
)
}
}
Example: Simple Layouts
Row
Row

1 2
Row

1
2

Column
@Composable
fun ImageWithTitleSubtitleComponent() {

}
@Composable
fun ImageWithTitleSubtitleComponent() {
Row() {
Column() {

}
}
}
@Composable
fun ImageWithTitleSubtitleComponent() {
Row(modifier = Modifier.fillMaxWidth() + Modifier.padding(16.dp)) {
Column(modifier = Modifier.padding(start = 16.dp)) {

}
}
}
@Composable
fun ImageWithTitleSubtitleComponent() {
Row(modifier = Modifier.fillMaxWidth() + Modifier.padding(16.dp)) {
DrawableImage(R.drawable.lenna)
Column(modifier = Modifier.padding(start = 16.dp)) {
CustomTextComponent(displayText = "Title")
CustomTextComponent(displayText = "Subtitle")
}
}
}
@Composable
fun ImageWithTitleSubtitleComponent(title: String, subtitle: String, imageUrl: String) {
Row(modifier = Modifier.fillMaxWidth() + Modifier.padding(16.dp)) {
NetworkImage(imageUrl)
Column(modifier = Modifier.padding(start = 16.dp)) {
CustomTextComponent(displayText = title)
CustomTextComponent(displayText = subtitle)
}
}
}
@Composable
fun ImageWithTitleSubtitleComponent(title: String, subtitle: String, imageUrl: String) {
Row(modifier = Modifier.fillMaxWidth() + Modifier.padding(16.dp)) {
NetworkImage(imageUrl)
Column(modifier = Modifier.padding(start = 16.dp)) {
CustomTextComponent(displayText = title)
CustomTextComponent(displayText = subtitle)
}
}
}
Example: ConstraintLayout
@Composable
fun SimpleRowComponent(titleText: String, subtitleText: String, imageUrl: String) {

}
@Composable
fun SimpleRowComponent(titleText: String, subtitleText: String, imageUrl: String) {
ConstraintLayout {
val (title, subtitle, image) = createRefs()
}
}
@Composable
fun SimpleRowComponent(titleText: String, subtitleText: String, imageUrl: String) {
ConstraintLayout {
val (title, subtitle, image) = createRefs()

CustomTextComponent(
displayText = titleText,
)
CustomTextComponent(
displayText = subtitleText,
)
NetworkImage(
url = imageUrl,
)
}
}
@Composable
fun SimpleRowComponent(titleText: String, subtitleText: String, imageUrl: String) {
ConstraintLayout {
val (title, subtitle, image) = createRefs()

CustomTextComponent(
displayText = titleText,
modifier = Modifier.constrainAs(title) {
start.linkTo(image.end, margin = 8.dp)
top.linkTo(image.top)
}
)
CustomTextComponent(
displayText = subtitleText,
)
NetworkImage(
url = imageUrl,
)
}
}
@Composable
fun SimpleRowComponent(titleText: String, subtitleText: String, imageUrl: String) {
ConstraintLayout {
val (title, subtitle, image) = createRefs()

CustomTextComponent(
displayText = titleText,
modifier = Modifier.constrainAs(title) {
start.linkTo(image.end, margin = 8.dp)
top.linkTo(image.top)
}
)
CustomTextComponent(
displayText = subtitleText,
modifier = Modifier.constrainAs(subtitle) {
bottom.linkTo(image.bottom)
start.linkTo(image.end, margin = 8.dp)
}
)
NetworkImage(
url = imageUrl,
modifier = Modifier.constrainAs(image) {
centerVerticallyTo(parent)
start.linkTo(parent.start, margin = 16.dp)
top.linkTo(parent.top, margin = 16.dp)
bottom.linkTo(parent.bottom, margin = 16.dp)
}
)
}
}
@Composable
fun SimpleRowComponent(titleText: String, subtitleText: String, imageUrl: String) {
Card(
modifier = Modifier.fillMaxWidth() + Modifier.padding(8.dp),
shape = RoundedCornerShape(4.dp)
){
ConstraintLayout {
val (title, subtitle, image) = createRefs()

CustomTextComponent(
displayText = titleText,
modifier = Modifier.constrainAs(title) {
start.linkTo(image.end, margin = 8.dp)
top.linkTo(image.top)
}
)
CustomTextComponent(
displayText = subtitleText,
modifier = Modifier.constrainAs(subtitle) {
bottom.linkTo(image.bottom)
start.linkTo(image.end, margin = 8.dp)
}
)
NetworkImage(
url = imageUrl,
modifier = Modifier.constrainAs(image) {
centerVerticallyTo(parent)
start.linkTo(parent.start, margin = 16.dp)
top.linkTo(parent.top, margin = 16.dp)
bottom.linkTo(parent.bottom, margin = 16.dp)
})
}
}
}
@Composable
fun SimpleRowComponent(titleText: String, subtitleText: String, imageUrl: String) {
Card(
modifier = Modifier.fillMaxWidth() + Modifier.padding(8.dp),
shape = RoundedCornerShape(4.dp)
){
ConstraintLayout {
val (title, subtitle, image) = createRefs()

CustomTextComponent(
displayText = titleText,
modifier = Modifier.constrainAs(title) {
start.linkTo(image.end, margin = 8.dp)
top.linkTo(image.top)
}
)
CustomTextComponent(
displayText = subtitleText,
modifier = Modifier.constrainAs(subtitle) {
bottom.linkTo(image.bottom)
start.linkTo(image.end, margin = 8.dp)
}
)
NetworkImage(
url = imageUrl,
modifier = Modifier.constrainAs(image) {
centerVerticallyTo(parent)
start.linkTo(parent.start, margin = 16.dp)
top.linkTo(parent.top, margin = 16.dp)
bottom.linkTo(parent.bottom, margin = 16.dp)
})
}
}
}
Example: List
www.JetpackCompose.app
@Composable
fun ListComponent(superheroList: List<Person>) {

}
@Composable
fun ListComponent(superheroList: List<Person>) {
LazyColumnItems(items = superheroList) { person ->

}
}
@Composable
fun ListComponent(superheroList: List<Person>) {
LazyColumnItems(items = superheroList) { person ->
SimpleRowComponent(
person.name,
person.age,
person.profilePictureUrl
)
}
}
@Composable
fun ListComponent(superheroList: List<Person>) {
LazyColumnItems(items = superheroList) { person ->
SimpleRowComponent(
person.name,
person.age,
person.profilePictureUrl
)
}
}
Example: Click
@Composable
fun SimpleRowComponent(
titleText: String,
subtitleText: String,
imageUrl: String
){
Card(
modifier = Modifier.fillMaxWidth() +
Modifier.padding(8.dp),
shape = RoundedCornerShape(4.dp)
){
....
....
}
}
@Composable
fun SimpleRowComponent(
titleText: String,
subtitleText: String,
imageUrl: String,
viewModel: SuperheroViewModel
){
Card(
modifier = Modifier.fillMaxWidth() +
Modifier.padding(8.dp) +
Modifier.cl
shape = RoundedCornerShape(4.dp)
){
....
....
}
}
@Composable
fun SimpleRowComponent(
titleText: String,
subtitleText: String,
imageUrl: String,
viewModel: SuperheroViewModel
){
Card(
modifier = Modifier.fillMaxWidth() +
Modifier.padding(8.dp) +
Modifier.cl
clip
shape = RoundedCornerShape(4.dp)
){
....
clickable
.... clipToBounds
}
}
@Composable
fun SimpleRowComponent(
titleText: String,
subtitleText: String,
imageUrl: String,
viewModel: SuperheroViewModel
){
Card(
modifier = Modifier.fillMaxWidth() +
Modifier.padding(8.dp) +
Modifier.clickable {
viewModel.updateSelectedSuperhero()
},
shape = RoundedCornerShape(4.dp)
){
....
....
}
}
@Composable
fun SimpleRowComponent(
titleText: String,
subtitleText: String,
imageUrl: String,
viewModel: SuperheroViewModel
){

👎
Card(
modifier = Modifier.fillMaxWidth() +
Modifier.padding(8.dp) +
Modifier.clickable {
viewModel.updateSelectedSuperhero()
},
shape = RoundedCornerShape(4.dp)
){
....
....
}
}
@Composable
fun SimpleRowComponent(
titleText: String,
subtitleText: String,
imageUrl: String,
onClick: () -> Unit
){
Card(
modifier = Modifier.fillMaxWidth() +
Modifier.padding(8.dp) +
Modifier.clickable {
onClick()
},
shape = RoundedCornerShape(4.dp)
){
....
....
}
}
@Composable
fun SimpleRowComponent(
titleText: String,
subtitleText: String,
imageUrl: String,
onClick: () -> Unit
){
Card(
modifier = Modifier.fillMaxWidth() +
Modifier.padding(8.dp) +
Modifier.clickable {
onClick()
},
shape = RoundedCornerShape(4.dp)
){
....
....
}
}
Example: Pinch-to-Zoom &
Drag
@Composable
fun ZoomableImageComponent(imageUrl: String) {

}
@Composable
fun ZoomableImageComponent(imageUrl: String) {
var scale by state { 1f }
var panOffset by state { Offset(0f, 0f) }
}
@Composable
fun ZoomableImageComponent(imageUrl: String) {
var scale by state { 1f }
var panOffset by state { Offset(0f, 0f) }

Box(gravity = Alignment.Center) {
NetworkImage(
imageUrl = imageUrl,
modifier = Modifier.fillMaxSize()
)
}
}
@Composable
fun ZoomableImageComponent(imageUrl: String) {
var scale by state { 1f }
var panOffset by state { Offset(0f, 0f) }

Box(
gravity = Alignment.Center,
modifier = Modifier.zoomable(onZoomDelta = { scale *= it })
){
NetworkImage(
imageUrl = imageUrl,
modifier = Modifier.fillMaxSize() + Modifier.drawLayer(
scaleX = scale,
scaleY = scale
)
)
}
}
@Composable
fun ZoomableImageComponent(imageUrl: String) {
var scale by state { 1f }
var panOffset by state { Offset(0f, 0f) }

Box(
gravity = Alignment.Center,
modifier = Modifier.zoomable(onZoomDelta = { scale *= it }) + Modifier.rawDragGestureFilter(
object : DragObserver {
override fun onDrag(dragDistance: Offset): Offset {
panOffset = panOffset.plus(dragDistance)
return super.onDrag(dragDistance)
}
})
){
NetworkImage(
imageUrl = imageUrl,
modifier = Modifier.fillMaxSize() + Modifier.drawLayer(
scaleX = scale,
scaleY = scale,
translationX = panOffset.x,
translationY = panOffset.y
)
)
}
}
@Composable
fun ZoomableImageComponent(imageUrl: String) {
var scale by state { 1f }
var panOffset by state { Offset(0f, 0f) }

Box(
gravity = Alignment.Center,
modifier = Modifier.zoomable(onZoomDelta = { scale *= it }) + Modifier.rawDragGestureFilter(
object : DragObserver {
override fun onDrag(dragDistance: Offset): Offset {
panOffset = panOffset.plus(dragDistance)
return super.onDrag(dragDistance)
}
})
){
NetworkImage(
imageUrl = imageUrl,
modifier = Modifier.fillMaxSize() + Modifier.drawLayer(
scaleX = scale,
scaleY = scale,
translationX = panOffset.x,
translationY = panOffset.y
)
)
}
}
Interoperability
Example: Compose in
Classic Android
class ComposeInClassicAndroidActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_compose_in_classic_android)
}
}
class ComposeInClassicAndroidActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_compose_in_classic_android)
val containerLayout = findViewById(R.id.frame_container)
containerLayout.setContent(Recomposer.current()) {
SimpleRowComponent()
}
}
}
class ComposeInClassicAndroidActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_compose_in_classic_android)
val containerLayout = findViewById(R.id.frame_container)
containerLayout.setContent(Recomposer.current()) {
SimpleRowComponent()
}
}
}
Example: Classic Android in
Compose
credit_card.xml

<?xml version="1.0" encoding="utf-8"?>


<com.vinaygaba.creditcardview.CreditCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id=“@+id/credit_card"
android:layout_width="fill_parent"
android:layout_height="225dp"
app:cardName="John Doe"
app:cardNumber="5500005555555559"
app:cardNumberFormat="masked_all_but_last_four"
app:expiryDate="02/22"
app:putChip="true"
app:type=“auto" />
@Composable
fun AndroidInCompose() {
AndroidView(R.layout.credit_card, modifier = Modifier.padding(16.dp))
}
Resources
https://bit.ly/ComposeByExample
https://www.JetpackCompose.app/

You might also like