Book Cover

Learn Jetpack Compose without spending hundreds of hours

110 copies sold
4.7/5 ⭐️⭐️⭐️⭐️
Black Friday deal 🚀
Save 50% if you purchase today
Use code BLACK_FRIDAY on checkout
Buy Now
Already purchased?

Use Jetpack Compose straight away

Jetpack Compose is the future of Android UI. Wouldn't it be great if you did not have to spend hundreds of hours figuring out how to do things you already know the old-fashioned way using Views?

This book includes code examples and to-the-point explanations so that you do not have to.

Available in PDF/ePUB/HTML

What people are saying about this book

Jorge Castillo
May 2nd 2022

I had the chance to meet Alex the other day and we talked about his plans regarding his book. I think his practical mindset on the way to approach to it will make it an instant recommendation for anybody learning Compose.

u/vikarti_anatra
July 28th 2022

Just what you need to get started on Compose when you migrate. Instead of a lot of articles.


I could only compare it to:


- some Mark Murphy books like Elements of Android Jetpack


- (non-android-dev example) Raywenderlich's series of books 'iOS N by Tutorials' in which they describe new things in new iOS version.




p.s.


Bought in-process book about 2 month ago.

Martin Kiperszmid | Programador
Aug 24th 2022

Brooo Your book has everything are you kidding me

Love it

⚡ Catalin Ghita
May 4th 2022

This looks really dope 👀 I'm sure this ebook will move mountains!

Daniele Bonaldo
August 19th 2022

Jetpack Compose learning curve is not simple. This book is helpful in understanding the differences with the traditional View system and how to implement stuff.

Ivan Morgillo 🐕💻⚔️☮️❄️🧘🏻‍♂️
May 5th 2022

Take what you already know about Views, mix it up with the new Jetpack Compose declarative approach, and you are good to go! I love it! 🥰 Great stuff Alex!

🤌 sebastiano 🤌
May 5th 2022

Alex has a great talent in explaining the basics of Compose, and his material on the topic so far has been excellent (follow him for tips & videos!).


I'm looking forward to seeing this book coming out and helping out folks migrating their apps to Jetpack Compose 🤓

Pre-ordered today, waiting for the book.

Georgios Metaxakis
May 3rd 2022

Just pre-ordered. Go on take yours too 😁

Preface

Thank you for reading my book! I am Alex Styl and I have been developing for Android for 10+ years.

You do not have to relearn everything you know from Android Views to use Jetpack Compose!

This is a no fluff, concise book that answers any specific question you might have while developing with Compose. Say for example that you are working with text and you need to style it. Jump straight to the Text chapter and find the answer to your styling questions there. Or you might not know how to structure your Jetpack Compose application or how Navigation works. Everything is here!

There are parts that might not give much information about a specific aspect of Compose and that is intentional. In the Text chapter, there is little emphasis to how you would use theming to style your entire app's Text in a single way, as the focus there in on how to use the Text composable. Instead you can read all about it in the Theming chapter.

If you are new in Compose or you struggle with understanding reading Compose code, I strongly encourage you to read the first chapter.

Special thanks to our proof-readers for their incredible work reviewing chapters of this book. More specifically I would like to thank: Colton Idle, Daniele Bonaldo, Davide Agostini, Ian Lake, Maia Grotepass, Manuel Vicente Vivo, Michael Sim, Rafael R. Tonholo and Jose Alcérreca.

Enjoy and happy coding,

– Alex Styl

PS: The text will slowly change to scrambled text unless you purchase the book. Buy the full book to keep reading the full book via the browser or offline (PDF/ePUB/HTML available).

Understanding Compose code

In Jetpack Compose, each component that needs to be rendered on the screen can be defined as a Kotlin Unit function marked with the @Composable annotation like this:

@Composable fun Article(title: String, description: String) { Card { Column { Text(title) Spacer(Modifier.height(10.dp)) Text(description) } } }

We call those functions composables. The above composable will render a Card with a title and a subtitle, with a spacing of 10 dp in between.

Every time the title and description change, the UI will be updated to reflect the updated values. This is what we call recomposition.

You may only call composable functions from other composable functions. Because of this, activities that use Composable to render their layouts will look like this:

class MyActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // use your composables here } } }

setContent {} is an extension function of the ComponentActivity. ComponentActivity is part of the androidx.activity:activity-compose dependency. Using composables in a Fragment needs a ComposeView like so:

class MyFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed) setContent { // use your composables here } } } }

In the View world, there are some common attributes and features found in most Views out there. Things like setting click and touch listeners, applying elevation, alpha, to name a few. For anyone creating their own custom views, there was a lot of boilerplate code to implement for your view to support such operations.

Compose introduces the concept of Modifiers. Modifiers provide functionality and features to composables without being tied to specific composables. Some Modifiers can be used for styling the composable (see background(), border() , clip() , shadow(), alpha(), animateContentSize()), others help with the placement and sizing of the composable (see fillMaxWidth() , size(), heightIn(), padding()) and others can bring functionality to the composable such as enabling click behavior or dragging (see clickable() , draggable(), toggleable(), swipeable()).

It is considered a good practice to always provide a Modifier when creating your own composable. This will allow callers of your composable to provide custom styling and specify any layout requirements they might have independently of the composable's code.

That was the basic knowledge you need, in order to understand Compose code you see in the wild. There are a few concepts that are new to Compose. Those new concepts will be explained in later parts of this book.

TextView to Text

Text is the direct replacement of TextView. It includes all standard TextView customizations and many more. Customizations can be passed directly as parameters to the composable. You can extract all customizations into a TextStyle that you can use through your app. You can provide a TextStyle directly into a Text as a parameter or via theming.

Example of usage:

Text("hello from Compose")

How to customize your text (text color, size, max lines, etc)

The Text composable supports functionality you would expect such as changing its textSize, setting its maxLines or its color.

In addition to standard TextView functionality, you get the option to modify the text's letterSpacing, lineHeight and more. All customization options can be found by inspecting the parameters of the Text composable.

Text( "Hello from Compose", fontSize = 18.sp, maxLines = 1, color = Color.Blue, )

How to reuse your text styles

One of the most important parameters of Text composable is the style parameter. It allows you to pass a TextStyle. This works in a very similar way to Views's TextAppearance.

A TextStyle contains all customizations you can apply as parameters to a Text composable. The benefit is that you can reuse the created style in multiple Text composables in your app. This makes styling consistent across the app and makes your composables easier to read and maintain.

A typical TextStyle looks like this:

val h1 = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.SemiBold, fontSize = 42.sp )

which you can use in your Text like this:

Text("My big header", style = h1)

Alternatively, you can define the style in your application's theme like this:

val Typography = Typography( h1 = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.SemiBold, fontSize = 42.sp ) ) @Composable fun MyTheme(content: @Composable () -> Unit) { MaterialTheme( typography = Typography, content = content ) }

and use it in your composable:

MyTheme { Text("My big header", style = MaterialTheme.Typography.h1) }

How to use custom Fonts

One of the parameters of Text is fontFamily. Compose provides some built-in fonts you can use that are device dependant, using the FontFamily object.

If the passed font family is not available on the device, a default font will be used instead. Alternatively, you can also define your own custom fonts in order to personalize your app further.

Example:

Text("This text is written in cursive", fontFamily = FontFamily.Cursive)

The font family can be used directly as a parameter to your Text composable or via a TextStyle. The TextStyle can be used in your application's theme.

There is a big chance that you will need to change the font of the entire app. For this purpose, you can use the defaultFontFamily parameter of the Typography class, which is part of the MaterialTheme.

How to create custom Fonts

First, store your .tff font files into your project under your res/font folder.

You can find a plethora of free to use fonts at Google Fonts.

Each font family might come with multiple files. Each file represents a different weight of the font, such as bold, semi-bold or thin. You will have to copy all those files in your resource folder.

Then, create a new FontFamily object and link each file to a respective styling:

val Urbanist = FontFamily( Font(R.font.urbanist_thin, weight = FontWeight.Thin), Font(R.font.urbanist_light, weight = FontWeight.Light), Font(R.font.urbanist_regular, weight = FontWeight.Normal), Font(R.font.urbanist_medium, weight = FontWeight.Medium), Font(R.font.urbanist_bold, weight = FontWeight.Bold), Font(R.font.urbanist_italic, style = FontStyle.Italic), )

How to use strings from xml resources

You can continue using all your translated XML string resources in your composables. Instead of having to rely to a Resource or Context object, you can use the stringResource() function:

Text(stringResource(R.string.my_translated_string)) // stringResource accepts args too Text(stringResource(R.string.hello_to), "Alex")

How to use string plurals from xml resources

There is currently no built-in way to use plurals. You would have to create your own function for the job.

You can use a mechanism called Composition Locals to get the current Context from a current composable function. This is what stringResource() and other similar resource functions use internally to get a hold of Context when needed.

A function for string plurals might look like this:

@Composable fun quantityStringResource( @PluralsRes pluralResId: Int, quantity: Int, vararg formatArgs: Any? = emptyArray() ): String { return LocalContext.current.resources .getQuantityString(pluralResId, quantity, *formatArgs) }

which you can use in your app like this:

// "Contact" or "Contacts" depending on the numberOfContacts Text(quantityStringResource(R.plurals.contact), numberOfContacts) // "No contact", "1 contact", or "$number contacts" Text( quantityStringResource(R.plurals.x_number_of_contacts), numberOfContacts, numberOfContacts )

How to make Text clickable

Instead of using a Modifier.clickable {} to make your text clickable, it is recommended to wrap your Text into an TextButton composable instead. The TextButton will style your Text according to your theme, and will include the right minimum touch target size required.

TextButton(onClick = { /*TODO start search*/ }) { Text("Search") }

How to make part of Text clickable (UrlSpans)

Create an AnnotatedString with the styling and URL information you need:

val tag = "info" val annotatedString = buildAnnotatedString { val text = "For more info click here" append(text) val start = text.indexOf("here") val end = start + 4 addStyle( style = SpanStyle( color = MaterialTheme.colors.primary, textDecoration = TextDecoration.Underline ), start = start, end = end ) addStringAnnotation( tag = tag, annotation = "https://viewtocomposable.com", start = start, end = end ) }

then pass the annotated String into a ClickableText and use the LocalUriHandler to launch the respective URL:

val uriHandler = LocalUriHandler.current ClickableText( text = annotatedString, onClick = { offset -> annotatedString .getStringAnnotations(tag, offset, offset) .firstOrNull() ?.let { string -> uriHandler.openUri(string.item) } } )

How to align my Text according to its baseline

Use Modifier.paddingFromBaseline() to place paddings to your composable according to your Text's first or last line's baseline.

Text( "Choose an account", modifier = Modifier.paddingFromBaseline(top = 40.dp), style = MaterialTheme.typography.h6 )