Mengenal Row & Column pada Jetpack Compose

Android 15 Jul 2021

Pada kesempatan kali ini kita akan mengenal dua layout dari Jetpack Compose yaitu Row dan Column. Bagi kamu baru ingin mencoba Jetpack Compose bisa baca artikel ini dulu https://teknorial.com/blog/mengenal-jetpack-compose-di-android/.

Saat kita mengembangkan aplikasi Android menggunakan layout XML, kita mengenal seperti LinearLayout, RelativeLayout dan ConstraintLayout. Sama halnya dengan Jetpack Compose kita membutuhkan seperti container atau ViewGroup yang dapat mengantur child composable di dalamnya.

Column digunakan untuk menyusun setiap child composable dalam satu arah secara vertikal. Ini mirip LinearLayout dengan orientasi vertikal. Berikut gambaran dari penggunaan Column berserta child composable di dalamnya.

column jetpack compose

Sedangkan Row digunakan untuk menyusun setiap child composable dalam satu arah secara horizontal. Ini mirip dengan LinearLayout dengan orientasi horizontal. Berikut gambaran Row beserta child composable di dalamnya.

row jetpack compose

Kita telah mengenal dasar dari fungsi Column dan Row. Sekarang kita akan mencoba membangun layout halaman detail produk seperti pada marketplace. Kita akan menggabungkan layout column dan row seperti pada gambar berikut.

detail layout jetpack compose

Pada saat tutorial ini ditulis Jetpack Compose berada di versi 1.0.0-beta09. Untuk membuat projectnya perlu menggunakan Android Studio Preview Beta Build. Kamu dapat mendownload pada link berikut https://developer.android.com/studio/preview dan cara menginstall sama seperti Android Studio biasanya.

Buka Android Studio dan buat project baru → pilih Empty Compose Activity dan masukkan konfigurasi seperti berikut :

  • Name : LayoutJetpackCompose
  • Package Name : com.teknorial.layoutjetpackcompose
  • Biarkan opsi lain sebagaimana adanya

konfigurasi project layout jetpack compose

Setelah project berhasil build. Kita masih perlu mengubah versi Jetpack Compose yang di generate oleh Android Studio karena terjadi render problem yang menyebabkan preview tidak berjalan semestinya. Kita akan menggunakan Jetpack Composer versi 1.0.0-beta09 dan kotlin-gradle-plugin 1.5.10.  Buka build.gradle (Project: LayoutJetpackCompose) dan modifikasi seperti kode di bawah.


// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext {
        compose_version = '1.0.0-beta09'
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0-beta05"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Tekan Sync now dan tunggu proses Gradle build.

Buka build.gradle (Module: LayoutJetpackCompose.app), hapus atau komen kotlinCompilerVersion di composeOptions{}.

build gradle kotlinCompilerVersion

Tekan Sync now dan tunggu proses Gradle build selesai.  Buka kembali MainActivity.kt, sekarang preview layout dapat terlihat di sisi kanan.

mainactivity preview

Kita akan mulai memodifikasi tampilan dari MainActivity. Hapus beberapa function composable seperti kode berikut.

package com.teknorial.layoutjetpackcompose

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.teknorial.layoutjetpackcompose.ui.theme.LayoutJetpackComposeTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LayoutJetpackComposeTheme {

            }
        }
    }
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    LayoutJetpackComposeTheme {

    }
}

Kita akan membuat function composable bernama MainScreen(). Dalam MainScreen kita akan membuat background layar dengan Surface.

package com.teknorial.layoutjetpackcompose

import ...

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LayoutJetpackComposeTheme {
                MainScreen()
            }
        }
    }
}

@Composable
fun MainScreen() {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {

    }
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    LayoutJetpackComposeTheme {
        MainScreen()
    }
}

Build Refresh (Ctrl+Shift+5), tunggu sampai proses selesai dan tampilan preview akan muncul dengan layar background putih. Di sini kita akan memulai menggunakan column dan row untuk membangun tampilan sesuai yang kita rencanakan sebelumnya. Kita juga akan memasukkan image ke dalam layout, silahkan download terlebih dahulu di sini dan masukkan ke dalam folder drawable.

Pertama kita akan menambahkan column dengan Modifier.fillMaxSize() agar column dapat mengisi penuh pada layar. Dalam column kita juga akan memasukkan image di posisi paling atas di dalamnya. Modifikasi function MainScreen seperti kode di bawah.

@Composable
fun MainScreen() {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {
        Column(modifier = Modifier.fillMaxSize()) {
            Image(
                modifier = Modifier.fillMaxWidth(),
                painter = painterResource(id = R.drawable.lenovo),
                contentDescription = "Photo ThinkPad T480",
            )
        }
    }
}

Build Refresh (Ctrl+Shift+5) dan kita akan melihat tampilan preview seperti pada gambar di bawah.

preview layout column dengan image

Kita dapat melihat gambar di atas bahwa Column telah mengisi seluruh bagian layar. Untuk melihat dari detail dari function tersebut, Ctrl + b atau Ctrl + Click pada tulisan Column.

column function jetpack compose

Dari gambar di atas kita bisa melihat bawah Column merupakan Composable function. Kita juga melihat beberapa parameter yang memiliki default value seperti modifier, verticalArrangement, dan horizontalAligment. Terakhir Column memiliki parameter content yang merupakan function lamda dan memiliki receiver ColumnScope. Dalam parameter content nantinya kita akan mengisi beberapa function composable lainnya seperti Image dan Column lainnya.

Kembali ke MainActivity.kt. Dalam function Column, kita telah menambahkan function Image sebagai content dan menggunakan argument modifier.fillMaxWidth() yang berarti lebar gambar akan mengikuti parentnya yaitu Column. Untuk memanggil gambar dari drawable kita menggunakan argument painter = painterResource kemudian kita isikan alamat id dari drawable tersebut. Terakhir  kita wajib menggunakan contentDescription untuk menulis deskripsi dari gambar kita. Untuk menggali lebih dalam apa saja isi dari function Image, Ctrl + b pada tulisan Image.

image function jetpack compose

Terdapat banyak parameter dalam function Image dan hanya 3 parameter yang kita gunakan. Kamu bisa baca beberapa tulisan berwarna hijau di atasnya untuk mengatahui lebih lengkap tentang kegunaan dari parameter tersebut.

Kembali ke MainActivity.kt. Sekarang kita akan tambahkan Column lagi untuk content informasi dari produk tersebut. Modifikasi function MainScreen seperti kode di bawah.

@Composable
fun MainScreen() {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {
        Column(modifier = Modifier.fillMaxSize()) {
            Image(
                modifier = Modifier.fillMaxWidth(),
                painter = painterResource(id = R.drawable.lenovo),
                contentDescription = "Photo ThinkPad T480",
            )
            Column(
                modifier = Modifier.padding(
                    start = 16.dp,
                    top = 4.dp,
                    end = 16.dp
                )
            ) {

            }
        }
    }
}

Pada kode di atas, kita telah menambahkan Column dengan modifier padding. Kemudian tambahkan content di dalamnya berupa Text.

@Composable
fun MainScreen() {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {
        Column(modifier = Modifier.fillMaxSize()) {
            Image(
                modifier = Modifier.fillMaxWidth(),
                painter = painterResource(id = R.drawable.lenovo),
                contentDescription = "Photo ThinkPad T480",
            )
            Column(
                modifier = Modifier.padding(
                    start = 16.dp,
                    top = 4.dp,
                    end = 16.dp
                )
            ) {
                Text(
                    text = "Rp 10.725.000",
                    style = MaterialTheme.typography.body1,
                    fontWeight = FontWeight.Bold
                )

                Text(
                    text = "Laptop ThinkPad T480 RAM 8 GB",
                    style = MaterialTheme.typography.body1
                )

                Text(
                    modifier = Modifier.padding(top = 8.dp),
                    text = "Detail Produk",
                    style = MaterialTheme.typography.body1,
                    fontWeight = FontWeight.Bold,
                )
                Text(
                    text = "Tingkatkan standar dengan ThinkPad T480. " +
                            "Memamerkan prosesor penuh tenaga terbaru " +
                            "dan baterai sepanjang hari, laptop 14 inch " +
                            "ini tangguh namun cukup ringan untuk menemani " +
                            "Anda ke mana pun. Sentuhan praktis termasuk keyboard " +
                            "dengan cahaya latar serta rangkaian port, " +
                            "sementara fitur keamanan yang ditingkatkan " +
                            "membantu mengamankan pekerjaan Anda ke mana " +
                            "pun pekerjaan membawa Anda.\n\n" +
                            "Spesifikasi :\n" +
                            "- Processor Intel® Core i5-8350U Processor (6M Cache, up to 3.60 GHz) VPro\n" +
                            "- Operating System Windows 10 Pro\n" +
                            "- Graphics Integrated\n" +
                            "- Webcam with ThinkShutter and microphone\n" +
                            "- Memory 8 + 16GB DDR4 2400, Total RAM 24GB\n" +
                            "- Storage 512Gb SSD M.2 PCIe NVMe\n" +
                            "- Audio Dolby\n" +
                            "- Dual-array microphones\n" +
                            "- Battery 3 cell 57Wh"
                )

                //TODO add Row here
            }
        }
    }
}

Build Refresh( Ctrl+Shift+5) dan tampilan preview akan muncul seperti pada gambar di bawah ini.

preview layout text composable

Kita telah masukkan 4 function Text dalam Column dan semuanya mengikuti ukuran padding kiri(start) dan kanan (end) yang telah didefinisikan oleh Column. Kita juga menggunakan argumen style pada Text, kamu bisa mengubah valuenya seperti gambar di bawah untuk melihat apa saja perubahan dari style tersebut.

style text composable

Untuk membuat tulisan bold kita bisa menggunakan argumen fontWeight = FontWeight.Bold. Masih banyak yang dapat kita modifikasi pada Text, Ctrl + b pada tulisan Text dan kita akan melihat detail dari function tersebut.

function text composable

Kita bisa melihat Text merupakan function Composable dan memiliki banyak parameter yang bisa kita gunakan untuk menampilkan dan memodifikasi pada Text tersebut.

Kembali ke MainActivity.kt. Kita akan menggunakan Row untuk menampilkan dua button secara horizontal. Letakan Row tepat pada tulisan //TODO add Row here dan function MainScreen akan seperti pada kode berikut.

@Composable
fun MainScreen() {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {
        Column(modifier = Modifier.fillMaxSize()) {
            Image(
                modifier = Modifier.fillMaxWidth(),
                painter = painterResource(id = R.drawable.lenovo),
                contentDescription = "Photo ThinkPad T480",
            )
            Column(
                modifier = Modifier.padding(
                    start = 16.dp,
                    top = 4.dp,
                    end = 16.dp
                )
            ) {
                Text(
                    text = "Rp 10.725.000",
                    style = MaterialTheme.typography.body1,
                    fontWeight = FontWeight.Bold
                )

                Text(
                    text = "Laptop ThinkPad T480 RAM 8 GB",
                    style = MaterialTheme.typography.body1
                )

                Text(
                    modifier = Modifier.padding(top = 8.dp),
                    text = "Detail Produk",
                    style = MaterialTheme.typography.body1,
                    fontWeight = FontWeight.Bold,
                )
                Text(
                    text = "Tingkatkan standar dengan ThinkPad T480. " +
                            "Memamerkan prosesor penuh tenaga terbaru " +
                            "dan baterai sepanjang hari, laptop 14 inch " +
                            "ini tangguh namun cukup ringan untuk menemani " +
                            "Anda ke mana pun. Sentuhan praktis termasuk keyboard " +
                            "dengan cahaya latar serta rangkaian port, " +
                            "sementara fitur keamanan yang ditingkatkan " +
                            "membantu mengamankan pekerjaan Anda ke mana " +
                            "pun pekerjaan membawa Anda.\n\n" +
                            "Spesifikasi :\n" +
                            "- Processor Intel® Core i5-8350U Processor (6M Cache, up to 3.60 GHz) VPro\n" +
                            "- Operating System Windows 10 Pro\n" +
                            "- Graphics Integrated\n" +
                            "- Webcam with ThinkShutter and microphone\n" +
                            "- Memory 8 + 16GB DDR4 2400, Total RAM 24GB\n" +
                            "- Storage 512Gb SSD M.2 PCIe NVMe\n" +
                            "- Audio Dolby\n" +
                            "- Dual-array microphones\n" +
                            "- Battery 3 cell 57Wh"
                )

                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 16.dp, bottom = 8.dp)

                ) {
                    //TODO add button here
                }
            }
        }
    }
}

Kita telah menambah Row dan sama seperti sebelumnya untuk melihat detail function tersebut bisa Ctrl + b pada tulisan Row.

row function composable

Sekarang kita akan menambahkan content ke dalam Row yaitu dua Button. Tambahkan kedua button tepat pada tulisan //TODO add button here seperti pada kode di bawah.

@Composable
fun MainScreen() {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {
        Column(modifier = Modifier.fillMaxSize()) {
            Image(
                modifier = Modifier.fillMaxWidth(),
                painter = painterResource(id = R.drawable.lenovo),
                contentDescription = "Photo ThinkPad T480",
            )
            Column(
                modifier = Modifier.padding(
                    start = 16.dp,
                    top = 4.dp,
                    end = 16.dp
                )
            ) {
                Text(
                    text = "Rp 10.725.000",
                    style = MaterialTheme.typography.body1,
                    fontWeight = FontWeight.Bold
                )

                Text(
                    text = "Laptop ThinkPad T480 RAM 8 GB",
                    style = MaterialTheme.typography.body1
                )

                Text(
                    modifier = Modifier.padding(top = 8.dp),
                    text = "Detail Produk",
                    style = MaterialTheme.typography.body1,
                    fontWeight = FontWeight.Bold,
                )
                Text(
                    text = "Tingkatkan standar dengan ThinkPad T480. " +
                            "Memamerkan prosesor penuh tenaga terbaru " +
                            "dan baterai sepanjang hari, laptop 14 inch " +
                            "ini tangguh namun cukup ringan untuk menemani " +
                            "Anda ke mana pun. Sentuhan praktis termasuk keyboard " +
                            "dengan cahaya latar serta rangkaian port, " +
                            "sementara fitur keamanan yang ditingkatkan " +
                            "membantu mengamankan pekerjaan Anda ke mana " +
                            "pun pekerjaan membawa Anda.\n\n" +
                            "Spesifikasi :\n" +
                            "- Processor Intel® Core i5-8350U Processor (6M Cache, up to 3.60 GHz) VPro\n" +
                            "- Operating System Windows 10 Pro\n" +
                            "- Graphics Integrated\n" +
                            "- Webcam with ThinkShutter and microphone\n" +
                            "- Memory 8 + 16GB DDR4 2400, Total RAM 24GB\n" +
                            "- Storage 512Gb SSD M.2 PCIe NVMe\n" +
                            "- Audio Dolby\n" +
                            "- Dual-array microphones\n" +
                            "- Battery 3 cell 57Wh"
                )

                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 16.dp, bottom = 8.dp)
                ) {
                    Button(
                        modifier = Modifier
                            .weight(1f)
                            .padding(end = 4.dp),
                        onClick = { /*TODO*/ },
                        border = BorderStroke(
                            1.dp,
                            MaterialTheme.colors.primary
                        ),
                        colors = ButtonDefaults.buttonColors(
                            backgroundColor = MaterialTheme.colors.background
                        )
                    ) {
                        Text(text = "Beli Langsung")
                    }

                    Button(
                        modifier = Modifier
                            .weight(1f)
                            .padding(start = 4.dp),
                        onClick = { /*TODO*/ },
                    ) {
                        Text(text = "+ Keranjang")
                    }
                }
            }
        }
    }
}

Build Refresh (Ctrl + Shift + 5) dan tampilan preview akan muncul seperti gambar di bawah ini.

row button jetpack compose

Mari kita bahas apa saja yang kita lakukan pada button.

button compose

Kita menggunakan modifier weight dan padding. Parent kedua button tersebut adalah Row yang berarti button tersebut akan tersusun secara vertikal. Untuk membagi 50:50 dari kedua button kita bisa menggunakan Modifier.weight(1f). Untuk mempelajari pengaruh weight, kamu bisa mencoba mengubah weight salah satu button menjadi 2f maka button tersebut akan lebih besar.

ubah weight button

Kita juga membuat salah satu button berwarna berbeda.Pada dasarnya warna button akan mengikuti warna primary. Pada Button "Beli Langsung" kita membuat warna button putih seperti warna background dan border berwarna ungu seperti warna primary. Untuk menampilkan tulisan button kita perlu menggunakan function composable yaitu Text. Kenapa harus seperti itu? Untuk menjawabnya kita perlu membuka isi function Button. Ctrl + b pada tulisan Button.

button function composable

Pada gambar di atas kita bisa melihat banyak parameter yang dimiliki oleh Button. Kita fokus ke parameter content. Disini kita bisa melihat bawah content merupakan function lamda yang memiliki receiver RowScope persis yang dimiliki juga oleh layout Row. Dengan ini kita dapat memasukkan function Composable lainnya seperti Text dan bahkan menambah Image sebagai icon dengan aturan posisi seperti Row.

Kembali ke MainActivity.kt. Sekarang coba jalankan aplikasi telah kita buat. Klik Run 'App' (Shift + F10) dan tampilan aplikasi pada emulator atau smartphone akan seperti pada gambar di bawah.

app run jetpack compose

Aplikasi dapat berjalan dengan baik tanpa error, namun kita tidak dapat scroll ke bawah untuk melihat konten lebih lengkap. Sekarang menambahkan fitur scroll secara vertical pada Column paling atas. Pertama kita akan membuat scrollState dan tambahkan Modifier.verticalScroll pada Column seperti pada gambar di bawah.

vertical scroll column

Klik Run 'app' (Shift + F10) dan sekarang kita dapat melakukan scroll untuk melihat konten lebih lengkap seperti pada gambar di bawah.

scroll column jetpack compose

Demikian tutorial Mengenal Row & Column pada Jetpack Compose. Kita telah belajar mengenai penggunaan Row dan Column serta cara menggunakan function composable lainnya seperti Image, Text dan Button. Jika kamu masih kesulitan dalam mengikuti tutorial ini, silahkan bertanya di kolom komentar di bawah. Semoga artikel ini bermanfaat. Terima kasih.

Tag