Intro to Android Development
  • Welcome
  • Syllabus
  • Hack Challenge
  • Resources
    • Lecture Videos
    • Ed Discussion
    • Git & GitHub Help/How-To
    • Setting up Android Studio
    • Starting an Android Studio Project & Making an Emulator
    • Importing, Exporting, & Submitting Your Projects to CMS
  • SP25 Course Material
    • Week 1 | Course Logistics, Kotlin, & Basic UI
      • Relevant Links
      • Demo/Lecture: Eatery Card
      • A0: Eatery Card (Follow-Along)
    • Week 2 | States, Components, LazyColumn
      • Relevant Links
      • Demo: Todo List
      • A2: Shopping List
    • Week 3 | Navigation & Animations
      • Relevant Links
      • Demo: Onboarding
      • A3: Stock Trading (RobbingGood)
    • Week 4 | MVVM and Flows
      • Relevant Links
      • Demo: Eatery Card 2
      • A4: Chat of a Lifetime
    • Week 5 | Dumb Components & UIEvents
      • Relevant Links
      • Demo: Music Player
      • A5: Rate My Vibe
    • Week 6 | Coroutines, Networking, JSON
      • Relevant Links
      • Demo: Retrofit
      • A6: You Should Even Lift, Bro.
  • Bonus Week | Android Job Search
    • Relevant Links
    • Android Technical Interview Question!
  • Textbook
    • 1. Introduction to the Editor and Views
      • 1.1 Introduction to the Editor
      • 1.2 SDK Management
      • 1.3 Kotlin Overview
      • 1.4 Views
      • 1.5 Android Studio Project Demo + Understanding The Editor
    • 2. Jetpack Compose
      • 2.1 Introduction
      • 2.2 Layouts
      • 2.3 Modifiers
      • 2.4 Animations
      • 2.5 Lazy Lists
      • 2.6 Reactive UI
    • 3. Intents and Manifest
      • 3.1 Activities
      • 3.2 Implicit Intents
      • 3.3 Explicit Intents
      • 3.4 Manifest
      • 3.5 Permissions
      • 3.6 Summary
    • 4. Navigation
      • 4.1 Types of Navigation
      • 4.2 Implementation of the Bottom Navigation Bar
    • 5. Data and Persistent Storage
      • 5.1 Singleton Classes
      • 5.2 Shared Preferences
      • 5.3 Rooms
      • 5.4 Entities
      • 5.5 Data Access Objects
      • 5.6 Databases
    • 5.5 Concurrency
      • 5.5.1 Coroutines
      • 5.5.2 Implementation of Coroutines
      • 5.5.3 Coroutines with Networking Calls
    • 6. Networking and 3rd Party libraries
      • 6.1 HTTP Overview
      • 6.2 3rd Party Libraries
      • 6.3 JSON and Moshi
      • 6.4 Retrofit
      • 6.5 Summary
    • 7. MVVM Design Pattern
      • 7.1 Key Idea
      • 7.2 Implementation Ideas
    • 8. Flows
    • 9. The Art and Ontology of Software
    • 10. 🔥 Firebase
      • 10.1 Setting up Firebase
      • 10.2 Authentication
      • 10.3 Analytics
      • 10.4 Messaging
      • 10.5 Firestore
  • Additional Topics
    • Git and GitHub
    • Exporting to APK
  • Archive
    • Archived Native Android Textbook Pages
      • 1. Layouts and More Views
        • 1.1 File Structure and File Types
        • 1.2 Resource Files
        • 1.3 Button and Input Control
        • 1.4 ViewGroups
        • 1.5 Summary + A Note On Chapter 2 Topics
      • 2. RecyclerViews
        • 2.1 RecyclerViews
        • 2.2 RecyclerView Performance
        • 2.3 Implementation of a Recycler View
        • 2.4 Implementation with Input Controls
        • 2.5 Filtering RecyclerViews
        • 2.6 Recyclerview Demo
      • 3. ListViews and Searching
        • 3.1 ListView vs. RecyclerView
        • 3.2 ListView Performance
        • 3.3 Implementation of a ListView
        • 3.4 Searching in a List View
      • 4. Fragments
        • 4.1 What are Fragments?
        • 4.2 Lifecycle of a Fragment
        • 4.3 Integrating a Fragment into an Activity
        • 4.4 Sharing Data Between Fragments
        • 4.5 Fragment Slide Shows
      • 5. OkHttp
      • 6. Activity Lifecycle
      • 7. Implementation of Tab Layout
    • Fall 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 1.5: Beauty of Kotlin
      • Lecture 2 & HW 2: Modifiers, Lazylists and Reactive UI
      • Lecture 3 & HW 3: Animations, Intents and Manifest
      • Lecture 4 & HW 4: Coroutines & Navigation
      • Lecture 5 & HW 5: Persistent Storage, Networking, and JSON Parsing
      • Lecture 6 & HW 6: MVVM, Flows
      • Bonus Lectures & Bonus HW
      • Bonus Lecture: Industry Practice
    • Spring 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 4 & HW 4: LazyLists
      • Lecture 6 & HW 6: Networking, Data, and Persistent Storage
    • Spring 2020 Course Material
      • Week 1: Intro to the Editor
      • Week 2: Views and Layouts
      • Week 3: Intent and Manifest
      • Week 4: ListView and RecyclerView
      • Week 5: Fragments
      • Week 6: Networking
    • Spring 2021 Lecture & HW 8: Networking & 3rd Party APIs
    • HackOurCampus Workshop
Powered by GitBook
On this page

Was this helpful?

  1. Textbook
  2. 2. Jetpack Compose

2.2 Layouts

Organization slay

Previous2.1 IntroductionNext2.3 Modifiers

Last updated 9 months ago

Was this helpful?

As you may recall from Native Android, UI elements live in a hierarchy, where each element has a parent element by which it is contained. Jetpack Compose allows us to create this hierarchy by calling other composable functions inside the one we are creating. However, if you try just putting two Text composables right after one another, you will notice that they will overlap and make the text unreadable. Therefore, we need some ways to organize the composables to our liking.

Jetpack Compose provides multiple methods to arrange multiple composable functions depending on the format the user wants. The most common ones are Rows, Columns, and Boxes. As the names suggest, Rows allow us to put composables in a row with one another, while Columns allow us to put composables in a column with one another. Boxes may seem a bit more unintuitive, but they allow us to arrange the composables inside of it however we like, including overlapping composables, which Rows and Columns do not allow.

Another thing to note is that while in Native Android, we want to avoid nested layouts because it slows down runtime, Jetpack Compose has optimized for layouts and therefore the performance will not be impeded by nested layouts.

Alignment and Arrangement

When we want to manage the layout of items within a Row or Column, there are some arguments that we can specify in order to do so. For example, as you can see below, we can use the verticalAlignment and horizontalArrangement arguments in order to specify that we want the composables inside the Row to be centered vertically and right-aligned (using Arrangement.End). Similarly, Columns have horizontalAlignment and verticalArrangement arguments to specify how the composables inside should be arranged.

@Composable
fun ArtistCard(artist: Artist) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.End
    ) {
        Image(/*...*/)
        Text { /*...*/ }
    }
}
  • Arrangement.Start: places items in the main axis start.

  • Arrangement.End: places items in the main axis end.

  • Arrangement.Center: places items in the main axis center.

  • Arrangement.SpaceBetween: places first item in the main axis start and the last item in the main axis end, then distributes the remaining items evenly in the space left.

  • Arrangement.SpaceAround: puts the same amount of space on the left and the right of each item (in a Row, or top and bottom in a Column). Notice that spaces in the middle will be twice as large as spaces in the ends.

  • Arrangement.SpaceEvenly: puts the same amount of space between items, the start and the end. It differentiates from space around because the spacing at the start and end is the same as the spacing in the middle.

When using a Box, the composables inside of it will have padding from the boundaries of it. Therefore, we can allow multiple composables to overlap simply by adjusting their paddings to make them in similar places. Here's an example from the Scooped profile screen:

Box(
    modifier = Modifier.fillMaxSize(),
) {
    Image(/*...*/)
    Column {
        Spacer(
            modifier = Modifier
                .height(133.dp)
                .fillMaxWidth()
        )
        /*...*/
    }
    Image(
        painter = /*...*/,
        contentDescription = null,
        modifier = Modifier
            .padding(top = 68.dp)
            .size(128.dp)
            .clip(CircleShape)
            .align(Alignment.TopCenter)
            .border(width = 3.dp, color = Green, shape = CircleShape)
    )
}

Also, you may notice that we have a modifier inside the Image referencing Alignment.TopCenter. The reason that we're able to do this is that we are able to use either the contentAlignment argument for the Box itself or we can use the modifier.align() method on the children of the Box.

Here's a list of Arrangements and Alignments from a discussing the intricacies of Jetpack Compose Layouts that may come in handy:

website
A visual representation of layouts provided by the official Android Developers website