Rabu, 01 Mei 2024

woofApp

Kali ini saya belajar untuk membuat aplikasi woof  yaitu aplikasi yang menampilkan daftar anjing dimana menerapkan desain material dengan jetpack compose. Desain Material adalah sistem desain yang dibuat dan didukung oleh desainer dan developer Google guna menciptakan pengalaman digital berkualitas tinggi untuk Android, serta platform seluler dan web lainnya. Panduan ini berisi langkah-langkah cara membangun UI aplikasi Anda dengan cara yang mudah dibaca, menarik, dan konsisten.



###Palet Warna
Berikut adalah palet warna untuk tema terang dan gelap yang akan di gunakan.

###Tipografi
Berikut adalah gaya jenis yang  akan di gunakan pada aplikasi.

###File Tema
File Theme.kt adalah file yang menyimpan semua informasi tentang tema aplikasi, yang ditentukan melalui warna, tipografi, dan bentuk. File ini penting untuk Anda ketahui. Di dalam file terdapat WoofTheme() composable, yang menetapkan warna, tipografi, dan bentuk aplikasi.

@Composable
fun
WoofTheme(
    darkTheme
: Boolean = isSystemInDarkTheme(),
   
// Dynamic color is available on Android 12+
    dynamicColor
: Boolean = false,
    content
: @Composable () -> Unit
) {
    val colorScheme
= when {
        dynamicColor
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context
= LocalContext.current
           
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
       
}

        darkTheme
-> DarkColors
       
else -> LightColors
   
}
    val view
= LocalView.current
   
if (!view.isInEditMode) {
       
SideEffect {
            setUpEdgeToEdge
(view, darkTheme)
       
}
   
}

   
MaterialTheme(
        colorScheme
= colorScheme,
        shapes
= Shapes,
        typography
= Typography,
        content
= content
   
)
}

/**
 * Sets up edge-to-edge for the window of this [view]. The system icon colors are set to either
 * light or dark depending on whether the [darkTheme] is enabled or not.
 */

private fun setUpEdgeToEdge(view: View, darkTheme: Boolean) {
    val window
= (view.context as Activity).window
   
WindowCompat.setDecorFitsSystemWindows(window, false)
    window
.statusBarColor = Color.Transparent.toArgb()
    val navigationBarColor
= when {
       
Build.VERSION.SDK_INT >= 29 -> Color.Transparent.toArgb()
       
Build.VERSION.SDK_INT >= 26 -> Color(0xFF, 0xFF, 0xFF, 0x63).toArgb()
       
// Min sdk version for this app is 24, this block is for SDK versions 24 and 25
       
else -> Color(0x00, 0x00, 0x00, 0x50).toArgb()
   
}
    window
.navigationBarColor = navigationBarColor
    val controller
= WindowCompat.getInsetsController(window, view)
    controller
.isAppearanceLightStatusBars = !darkTheme
    controller
.isAppearanceLightNavigationBars = !darkTheme
}

Di MainActivity.kt, WoofTheme() ditambahkan untuk menyediakan Penerapan Tema Material untuk seluruh aplikasi.


class MainActivity : ComponentActivity() {
   
override fun onCreate(savedInstanceState: Bundle?) {
       
super.onCreate(savedInstanceState)
       setContent
{
           
WoofTheme {
               
Surface(
                   modifier
= Modifier.fillMaxSize()
               
) {
                   
WoofApp()
               
}
           
}
       
}
   
}
}

Lihat WoofPreview(). WoofTheme() ditambahkan untuk menyediakan Penerapan Tema Material yang Anda lihat di WoofPreview().
@Preview
@Composable
fun
WoofPreview() {
   
WoofTheme(darkTheme = false) {
       
WoofApp()
   
}
}




Untuk mendapatkan kode awal, kita mengetikkan perintah pada terminal:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-woof.git
$ cd basic-android-kotlin-compose-training-woof
$ git checkout starter


Catatan: Kode awal berada di cabang starter dari repositori yang didownload.

Mempelajari kode awalBuka kode awal di Android Studio.
  1. Buka com.example.woof > data > Dog.kt. File ini berisi Dog data class yang akan digunakan untuk mewakili foto, nama, usia, dan hobi anjing. File ini juga berisi daftar anjing dan informasi yang akan Anda gunakan sebagai data di aplikasi Anda.
  2. Buka res > drawable. File ini berisi semua aset gambar yang Anda butuhkan untuk project ini, termasuk ikon aplikasi, gambar anjing, dan ikon.
  3. Buka res > values > strings.xml. File ini berisi string yang Anda gunakan dalam aplikasi ini, termasuk nama aplikasi, nama anjing, deskripsinya, dan lainnya.
  4. Buka MainActivity.kt. File ini berisi kode untuk membuat daftar sederhana yang menampilkan foto anjing, nama anjing, dan usia anjing tersebut.
  5. WoofApp() berisi LazyColumn yang menampilkan DogItem.
  6. DogItem() berisi Row yang menampilkan foto anjing dan informasi tentangnya.
  7. DogIcon() menampilkan foto anjing.
  8. DogInformation() menampilkan nama dan usia anjing.
  9. WoofPreview() memungkinkan Anda melihat pratinjau aplikasi di panel Design.

###Menambahkan Warna 

Hal pertama yang akan Anda ubah di aplikasi Woof adalah skema warna.

Skema warna adalah kombinasi warna yang digunakan aplikasi Anda. Kombinasi warna yang berbeda membangkitkan suasana hati yang berbeda, yang memengaruhi perasaan orang saat menggunakan aplikasi Anda.

Warna, dalam sistem Android, diwakili oleh nilai warna heksadesimal (hex). Kode warna heksadesimal dimulai dengan tanda pagar (#), dan diikuti dengan enam huruf dan/atau angka yang mewakili komponen merah, hijau, dan biru (RGB) dari warna tersebut. Dua huruf/angka pertama merujuk ke warna merah, dua huruf berikutnya berwarna hijau, dan dua huruf terakhir mengacu pada warna biru.



Warna juga dapat menyertakan nilai alfa—huruf dan/atau angka—yang mewakili transparansi warna (#00 adalah opasitas 0% (transparan sepenuhnya), #FF adalah opasitas 100% (solid sepenuhnya). Jika disertakan, nilai alfa adalah dua karakter pertama dari kode warna heksadesimal setelah tanda pagar (#). Jika nilai alfa tidak disertakan, nilai tersebut diasumsikan sebagai #FF, yaitu opasitas 100% (solid sepenuhnya).

Berikut adalah beberapa contoh warna dan nilai heksadesimalnya.


Menggunakan Material Theme Builder untuk membuat skema warna

Untuk membuat skema warna kustom bagi aplikasi, kita akan menggunakan Material Theme Builder.

1. Klik link ini untuk membuka Material Theme Builder.
2. Di panel kiri, Anda akan melihat Core Colors, klik Primary:


3. Pemilih warna HCT akan terbuka.


4. Untuk membuat skema warna yang ditampilkan di screenshot aplikasi, Anda akan mengubah warna primer di pemilih warna ini. Di kotak teks, ganti teks saat ini dengan #006C4C. Tindakan ini akan membuat warna primer aplikasi menjadi hijau.

Menambahkan palet warna ke tema

Di halaman Material Theme Builder, ada opsi untuk mengklik tombol Export guna mendownload file Color.kt dan file Theme.kt dengan tema kustom yang Anda buat di Theme Builder.

Tombol ini akan bekerja untuk menambahkan tema kustom yang telah kita buat ke aplikasi. Namun, karena file Theme.kt yang dihasilkan tidak menyertakan kode untuk warna dinamis yang akan kita bahas nanti di codelab, salin file tersebut.

1. Buka file Color.kt dan ganti konten dengan kode di bawah ini untuk menyalin dalam skema warna baru.

package com.example.woof.ui.theme

import androidx.compose.ui.graphics.Color

val md_theme_light_primary
= Color(0xFF006C4C)
val md_theme_light_onPrimary
= Color(0xFFFFFFFF)
val md_theme_light_primaryContainer
= Color(0xFF89F8C7)
val md_theme_light_onPrimaryContainer
= Color(0xFF002114)
val md_theme_light_secondary
= Color(0xFF4D6357)
val md_theme_light_onSecondary
= Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer
= Color(0xFFCFE9D9)
val md_theme_light_onSecondaryContainer
= Color(0xFF092016)
val md_theme_light_tertiary
= Color(0xFF3D6373)
val md_theme_light_onTertiary
= Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer
= Color(0xFFC1E8FB)
val md_theme_light_onTertiaryContainer
= Color(0xFF001F29)
val md_theme_light_error
= Color(0xFFBA1A1A)
val md_theme_light_errorContainer
= Color(0xFFFFDAD6)
val md_theme_light_onError
= Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer
= Color(0xFF410002)
val md_theme_light_background
= Color(0xFFFBFDF9)
val md_theme_light_onBackground
= Color(0xFF191C1A)
val md_theme_light_surface
= Color(0xFFFBFDF9)
val md_theme_light_onSurface
= Color(0xFF191C1A)
val md_theme_light_surfaceVariant
= Color(0xFFDBE5DD)
val md_theme_light_onSurfaceVariant
= Color(0xFF404943)
val md_theme_light_outline
= Color(0xFF707973)
val md_theme_light_inverseOnSurface
= Color(0xFFEFF1ED)
val md_theme_light_inverseSurface
= Color(0xFF2E312F)
val md_theme_light_inversePrimary
= Color(0xFF6CDBAC)
val md_theme_light_shadow
= Color(0xFF000000)
val md_theme_light_surfaceTint
= Color(0xFF006C4C)
val md_theme_light_outlineVariant
= Color(0xFFBFC9C2)
val md_theme_light_scrim
= Color(0xFF000000)

val md_theme_dark_primary
= Color(0xFF6CDBAC)
val md_theme_dark_onPrimary
= Color(0xFF003826)
val md_theme_dark_primaryContainer
= Color(0xFF005138)
val md_theme_dark_onPrimaryContainer
= Color(0xFF89F8C7)
val md_theme_dark_secondary
= Color(0xFFB3CCBE)
val md_theme_dark_onSecondary
= Color(0xFF1F352A)
val md_theme_dark_secondaryContainer
= Color(0xFF354B40)
val md_theme_dark_onSecondaryContainer
= Color(0xFFCFE9D9)
val md_theme_dark_tertiary
= Color(0xFFA5CCDF)
val md_theme_dark_onTertiary
= Color(0xFF073543)
val md_theme_dark_tertiaryContainer
= Color(0xFF244C5B)
val md_theme_dark_onTertiaryContainer
= Color(0xFFC1E8FB)
val md_theme_dark_error
= Color(0xFFFFB4AB)
val md_theme_dark_errorContainer
= Color(0xFF93000A)
val md_theme_dark_onError
= Color(0xFF690005)
val md_theme_dark_onErrorContainer
= Color(0xFFFFDAD6)
val md_theme_dark_background
= Color(0xFF191C1A)
val md_theme_dark_onBackground
= Color(0xFFE1E3DF)
val md_theme_dark_surface
= Color(0xFF191C1A)
val md_theme_dark_onSurface
= Color(0xFFE1E3DF)
val md_theme_dark_surfaceVariant
= Color(0xFF404943)
val md_theme_dark_onSurfaceVariant
= Color(0xFFBFC9C2)
val md_theme_dark_outline
= Color(0xFF8A938C)
val md_theme_dark_inverseOnSurface
= Color(0xFF191C1A)
val md_theme_dark_inverseSurface
= Color(0xFFE1E3DF)
val md_theme_dark_inversePrimary
= Color(0xFF006C4C)
val md_theme_dark_shadow
= Color(0xFF000000)
val md_theme_dark_surfaceTint
= Color(0xFF6CDBAC)
val md_theme_dark_outlineVariant
= Color(0xFF404943)
val md_theme_dark_scrim
= Color(0xFF000000)

2. Buka file Theme.kt dan ganti konten dengan kode di bawah ini untuk menambahkan warna baru ke tema.

package com.example.woof.ui.theme

import android.app.Activity
import android.os.Build
import android.view.View
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat

private val LightColors = lightColorScheme(
    primary
= md_theme_light_primary,
    onPrimary
= md_theme_light_onPrimary,
    primaryContainer
= md_theme_light_primaryContainer,
    onPrimaryContainer
= md_theme_light_onPrimaryContainer,
    secondary
= md_theme_light_secondary,
    onSecondary
= md_theme_light_onSecondary,
    secondaryContainer
= md_theme_light_secondaryContainer,
    onSecondaryContainer
= md_theme_light_onSecondaryContainer,
    tertiary
= md_theme_light_tertiary,
    onTertiary
= md_theme_light_onTertiary,
    tertiaryContainer
= md_theme_light_tertiaryContainer,
    onTertiaryContainer
= md_theme_light_onTertiaryContainer,
    error
= md_theme_light_error,
    errorContainer
= md_theme_light_errorContainer,
    onError
= md_theme_light_onError,
    onErrorContainer
= md_theme_light_onErrorContainer,
    background
= md_theme_light_background,
    onBackground
= md_theme_light_onBackground,
    surface
= md_theme_light_surface,
    onSurface
= md_theme_light_onSurface,
    surfaceVariant
= md_theme_light_surfaceVariant,
    onSurfaceVariant
= md_theme_light_onSurfaceVariant,
    outline
= md_theme_light_outline,
    inverseOnSurface
= md_theme_light_inverseOnSurface,
    inverseSurface
= md_theme_light_inverseSurface,
    inversePrimary
= md_theme_light_inversePrimary,
    surfaceTint
= md_theme_light_surfaceTint,
    outlineVariant
= md_theme_light_outlineVariant,
    scrim
= md_theme_light_scrim,
)

private val DarkColors = darkColorScheme(
    primary
= md_theme_dark_primary,
    onPrimary
= md_theme_dark_onPrimary,
    primaryContainer
= md_theme_dark_primaryContainer,
    onPrimaryContainer
= md_theme_dark_onPrimaryContainer,
    secondary
= md_theme_dark_secondary,
    onSecondary
= md_theme_dark_onSecondary,
    secondaryContainer
= md_theme_dark_secondaryContainer,
    onSecondaryContainer
= md_theme_dark_onSecondaryContainer,
    tertiary
= md_theme_dark_tertiary,
    onTertiary
= md_theme_dark_onTertiary,
    tertiaryContainer
= md_theme_dark_tertiaryContainer,
    onTertiaryContainer
= md_theme_dark_onTertiaryContainer,
    error
= md_theme_dark_error,
    errorContainer
= md_theme_dark_errorContainer,
    onError
= md_theme_dark_onError,
    onErrorContainer
= md_theme_dark_onErrorContainer,
    background
= md_theme_dark_background,
    onBackground
= md_theme_dark_onBackground,
    surface
= md_theme_dark_surface,
    onSurface
= md_theme_dark_onSurface,
    surfaceVariant
= md_theme_dark_surfaceVariant,
    onSurfaceVariant
= md_theme_dark_onSurfaceVariant,
    outline
= md_theme_dark_outline,
    inverseOnSurface
= md_theme_dark_inverseOnSurface,
    inverseSurface
= md_theme_dark_inverseSurface,
    inversePrimary
= md_theme_dark_inversePrimary,
    surfaceTint
= md_theme_dark_surfaceTint,
    outlineVariant
= md_theme_dark_outlineVariant,
    scrim
= md_theme_dark_scrim,
)

@Composable
fun
WoofTheme(
    darkTheme
: Boolean = isSystemInDarkTheme(),
   
// Dynamic color is available on Android 12+
    dynamicColor
: Boolean = false,
    content
: @Composable () -> Unit
) {
    val colorScheme
= when {
        dynamicColor
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context
= LocalContext.current
           
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
       
}

        darkTheme
-> DarkColors
       
else -> LightColors
   
}
    val view
= LocalView.current
   
if (!view.isInEditMode) {
       
SideEffect {
            setUpEdgeToEdge
(view, darkTheme)
       
}
   
}

   
MaterialTheme(
        colorScheme
= colorScheme,
        shapes
= Shapes,
        typography
= Typography,
        content
= content
   
)
}

/**
 * Sets up edge-to-edge for the window of this [view]. The system icon colors are set to either
 * light or dark depending on whether the [darkTheme] is enabled or not.
 */

private fun setUpEdgeToEdge(view: View, darkTheme: Boolean) {
    val window
= (view.context as Activity).window
   
WindowCompat.setDecorFitsSystemWindows(window, false)
    window
.statusBarColor = Color.Transparent.toArgb()
    val navigationBarColor
= when {
       
Build.VERSION.SDK_INT >= 29 -> Color.Transparent.toArgb()
       
Build.VERSION.SDK_INT >= 26 -> Color(0xFF, 0xFF, 0xFF, 0x63).toArgb()
       
// Min sdk version for this app is 24, this block is for SDK versions 24 and 25
       
else -> Color(0x00, 0x00, 0x00, 0x50).toArgb()
   
}
    window
.navigationBarColor = navigationBarColor
    val controller
= WindowCompat.getInsetsController(window, view)
    controller
.isAppearanceLightStatusBars = !darkTheme
    controller
.isAppearanceLightNavigationBars = !darkTheme
}


Di WoofTheme(), colorScheme val menggunakan pernyataan when

  • Jika dynamicColor bernilai benar dan versi build adalah S atau yang lebih tinggi, perangkat akan diperiksa apakah menggunakan darkTheme atau tidak.
  • Jika temanya gelap, colorScheme akan disetel ke dynamicDarkColorScheme.
  • Jika tidak dalam tema gelap, warna akan disetel ke dynamicLightColorScheme.
  • Jika aplikasi tidak menggunakan dynamicColorScheme, aplikasi akan diperiksa apakah menggunakan darkTheme. Jika demikian, colorScheme akan ditetapkan ke DarkColors.
  • Jika tidak ada yang benar, colorScheme akan ditetapkan ke LightColors.
File yang disalin di Theme.kt memiliki dynamicColor yang disetel ke salah dan perangkat yang kita gunakan dalam mode terang sehingga colorScheme akan disetel ke LightColors.

al colorScheme = when {
       dynamicColor
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
           val context
= LocalContext.current
           
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
       
}

       darkTheme
-> DarkColors
       
else -> LightColors
   
}


3. Jalankan kembali aplikasi Anda, perhatikan bahwa panel aplikasi telah otomatis berubah warna.



Pemetaan warna
Komponen material dipetakan ke slot warna secara otomatis. Komponen utama lainnya di seluruh UI, seperti Tombol Tindakan Mengambang (FAB), juga disetel ke warna Primer sebagai default. Ini berarti Anda tidak perlu menetapkan warna secara eksplisit ke komponen karena akan otomatis dipetakan ke slot warna saat Anda menetapkan tema warna di aplikasi. Anda dapat menggantinya dengan menetapkan warna secara eksplisit dalam kode. Baca selengkapnya tentang peran warna di sini.

Di bagian ini, kita akan menggabungkan Row yang berisi DogIcon() dan DogInformation() dengan Card untuk membedakan warna item daftar dengan latar belakang.

1. Dalam fungsi composable DogItem(), gabungkan Row() dengan Card().
Card() {
   
Row(
       modifier
= modifier
           
.fillMaxWidth()
           
.padding(dimensionResource(id = R.dimen.padding_small))
   
) {
       
DogIcon(dog.imageResourceId)
       
DogInformation(dog.name, dog.age)
   
}
}

2. Karena Card kini merupakan composable turunan pertama di DogItem(), teruskan pengubah dari DogItem() ke Card, dan update pengubah Row ke instance baru Modifier. 
Card(modifier = modifier) {
   
Row(
       modifier
= Modifier
           
.fillMaxWidth()
           
.padding(dimensionResource(id = R.dimen.padding_small))
   
) {
       
DogIcon(dog.imageResourceId)
       
DogInformation(dog.name, dog.age)
   
}
}

3. Lihat WoofPreview(). Item daftar sekarang telah otomatis berubah warna karena Composable Card. Warnanya terlihat bagus, tetapi tidak ada spasi di antara item daftar.

                                                      

File dimensi

Sama seperti menggunakan strings.xml untuk menyimpan string di aplikasi Anda, sebaiknya gunakan file bernama dimens.xml untuk menyimpan nilai dimensi. Dengan file ini, Anda tidak perlu melakukan hard code nilai dan jika perlu, Anda dapat mengubahnya di satu tempat.

Buka app > res > values > dimens.xml dan lihat file. Fungsi ini menyimpan nilai dimensi untuk padding_small, padding_medium, dan image_size. Dimensi ini akan digunakan di seluruh aplikasi.

<resources>
   
<dimen name="padding_small">8dp</dimen>
   
<dimen name="padding_medium">16dp</dimen>
   
<dimen name="image_size">64dp</dimen>
</resources>

Untuk menambahkan nilai dari file dimens.xml, ini adalah format yang benar:

Misalnya, untuk menambahkan padding_small, Anda akan meneruskan dimensionResource(id = R.dimen.padding_small).

1. Di WoofApp(), tambahkan modifier dengan padding_small dalam panggilan ke DogItem().
@Composable
fun
WoofApp() {
   
Scaffold { it ->
       
LazyColumn(contentPadding = it) {
            items
(dogs) {
               
DogItem(
                    dog
= it,
                    modifier
= Modifier.padding(dimensionResource(R.dimen.padding_small))
               
)
           
}
       
}
   
}
}

Di WoofPreview(), sekarang ada lebih banyak definisi di antara item daftar.


Tema gelap

Di sistem Android, ada opsi untuk mengalihkan perangkat Anda ke tema gelap. Tema gelap menggunakan warna yang lebih gelap, lebih tenang, dan:

Dapat mengurangi penggunaan daya secara signifikan (bergantung pada teknologi layar perangkat).
Meningkatkan visibilitas bagi pengguna dengan gangguan penglihatan dan mereka yang sensitif terhadap cahaya terang.
Memudahkan penggunaan perangkat di lingkungan yang minim cahaya.
Aplikasi Anda dapat ikut serta dalam Gelap Otomatis, yang berarti bahwa sistem akan menerapkan tema gelap untuk Anda. Namun, akan menjadi pengalaman yang lebih baik bagi pengguna jika Anda menerapkan tema gelap, sehingga Anda mempertahankan kontrol penuh atas tema aplikasi.

Saat memilih tema gelap sendiri, penting untuk diperhatikan bahwa warna untuk tema gelap harus memenuhi standar kontras aksesibilitas. Tema gelap menggunakan warna platform gelap, dengan aksen warna terbatas.

Melihat tema gelap dalam pratinjau

Anda telah menambahkan warna untuk tema gelap di langkah sebelumnya. Untuk melihat efek dari tema gelap, Anda dapat menambahkan Composable Pratinjau lainnya ke MainActivity.kt. Dengan demikian, saat mengubah tata letak UI dalam kode, Anda dapat melihat tampilan pratinjau tema terang dan tema gelap secara bersamaan.

1. Di bagian WoofPreview(), buat fungsi baru bernama WoofDarkThemePreview() dan anotasikan dengan @Preview dan @Composable.
@Preview
@Composable
fun
WoofDarkThemePreview() {

}
2. Di dalam DarkThemePreview(), tambahkan WoofTheme(). Tanpa menambahkan WoofTheme(), Anda tidak akan melihat gaya apa pun yang telah ditambahkan dalam aplikasi. Tetapkan parameter darkTheme ke true.
@Preview
@Composable
fun
WoofDarkThemePreview() {
   
WoofTheme(darkTheme = true) {

   
}
}

3. Panggil WoofApp() di dalam WoofTheme().

@Preview
@Composable
fun
WoofDarkThemePreview() {
   
WoofTheme(darkTheme = true) {
       
WoofApp()
   
}
}

Sekarang, scroll ke bawah di panel Design untuk melihat aplikasi dalam tema gelap, termasuk latar belakang item aplikasi/daftar yang lebih gelap dan teks yang lebih terang. Bandingkan perbedaan antara tema gelap dan terang.

Dark:




Light:


Melihat tema gelap di perangkat atau emulator

Untuk melihat aplikasi Anda dalam tema gelap di emulator atau perangkat fisik:
  1. Buka aplikasi Setelan di perangkat.
  2. Telusuri Tema Gelap dan klik di dalamnya.
  3. Aktifkan/Nonaktifkan Tema gelap.
  4. Buka kembali aplikasi Woof, dan aplikasi akan muncul dalam tema gelap
Warna Dinamis

Material 3 sangat berfokus pada personalisasi pengguna - fitur baru dalam Material 3 adalah Warna Dinamis yang membuat tema untuk aplikasi Anda berdasarkan wallpaper pengguna. Dengan demikian, jika pengguna menyukai warna hijau dan memiliki latar belakang ponsel berwarna biru, aplikasi Woof mereka juga akan berwarna biru untuk mencerminkan hal tersebut. Tema dinamis hanya tersedia di perangkat tertentu yang menjalankan Android 12 dan yang lebih baru.

Tema kustom dapat digunakan untuk aplikasi yang memiliki warna branding yang kuat dan juga perlu diterapkan untuk perangkat yang tidak mendukung tema dinamis sehingga aplikasi Anda masih bertema.

1. Untuk mengaktifkan warna dinamis, buka Theme.kt dan buka composable WoofTheme(), lalu setel parameter dynamicColor ke benar.
  @Composable
fun WoofTheme(
   darkTheme
: Boolean = isSystemInDarkTheme(),
   dynamicColor
: Boolean = true,
   content
: @Composable () -> Unit
)

2. Untuk mengubah latar belakang perangkat atau emulator, buka Setelan, lalu cari Wallpaper.
3. Ubah wallpaper ke warna atau sekumpulan warna.
4. Jalankan ulang aplikasi Anda untuk melihat tema dinamis (perhatikan bahwa perangkat atau emulator anda harus Android 12+ untuk melihat warna dinamis), jangan ragu untuk mencoba fitur ini dengan wallpaper yang berbeda.


5. Codelab ini berfokus pada tema kustom, jadi nonaktifkan dynamicColor sebelum Anda melanjutkan.
@Composable
fun
WoofTheme(
   darkTheme
: Boolean = isSystemInDarkTheme(),
   dynamicColor
: Boolean = false,
   content
: @Composable () -> Unit
)

###Menambahkan bentuk

Menerapkan bentuk akan sangat memengaruhi tampilan dan nuansa composable. Bentuk mampu menarik perhatian, mengidentifikasi komponen, mengomunikasikan status, dan mengekspresikan merek.

Banyak bentuk ditentukan menggunakan RoundedCornerShape, yang menggambarkan persegi panjang dengan sudut membulat. Angka yang diteruskan menentukan kebulatan sudut. Jika RoundedCornerShape(0.dp) digunakan, persegi panjang tidak memiliki sudut membulat; jika RoundedCornerShape(50.dp) digunakan, sudut akan membulat sepenuhnya.

File Shape.kt digunakan untuk menentukan bentuk komponen di Compose. Ada tiga jenis komponen: kecil, sedang, dan besar. Di bagian ini, Anda akan mengubah komponen Card, yang ditentukan sebagai ukuran medium. Komponen dikelompokkan ke dalam kategori bentuk berdasarkan ukurannya.

Pada bagian ini, Anda akan membentuk gambar anjing menjadi lingkaran, dan mengubah bentuk item daftar.

Membentuk gambar anjing menjadi lingkaran

1. Buka file Shape.kt dan perhatikan bahwa parameter kecil ditetapkan ke RoundedCornerShape(50.dp). Ini akan digunakan untuk membentuk gambar menjadi lingkaran.

val Shapes = Shapes(
   small
= RoundedCornerShape(50.dp),
)

2. Buka MainActivity.kt. Di DogIcon(), tambahkan atribut clip ke modifier dari Image; tindakan ini akan memotong gambar menjadi sebuah bentuk. Teruskan MaterialTheme.shapes.small.

import androidx.compose.ui.draw.clip

@Composable
fun
DogIcon(
   
@DrawableRes dogIcon: Int,
   modifier
: Modifier = Modifier
) {
   
Image(
       modifier
= modifier
           
.size(dimensionResource(id = R.dimen.image_size))
           
.padding(dimensionResource(id = R.dimen.padding_small))
           
.clip(MaterialTheme.shapes.small),

Saat melihat WoofPreview(), Anda akan melihat ikon anjing tersebut menjadi lingkaran. Namun, beberapa foto terpotong di bagian samping dan tidak muncul sebagai lingkaran sepenuhnya.

3. Untuk membuat semua foto menjadi lingkaran, tambahkan atribut ContentScale dan Crop; tindakan ini akan memangkas gambar agar sesuai. Perlu diketahui bahwa contentScale adalah atribut dari Image, dan bukan bagian dari modifier.
import androidx.compose.ui.layout.ContentScale

@Composable
fun
DogIcon(
   
@DrawableRes dogIcon: Int,
   modifier
: Modifier = Modifier
) {
   
Image(
       modifier
= modifier
           
.size(dimensionResource(id = R.dimen.image_size))
           
.padding(dimensionResource(id = R.dimen.padding_small))
           
.clip(MaterialTheme.shapes.small),
       contentScale
= ContentScale.Crop,

Ini adalah Composable DogIcon() lengkap.
@Composable
fun
DogIcon(
   
@DrawableRes dogIcon: Int,
    modifier
: Modifier = Modifier
) {
   
Image(
        modifier
= modifier
           
.size(dimensionResource(R.dimen.image_size))
           
.padding(dimensionResource(R.dimen.padding_small))
           
.clip(MaterialTheme.shapes.small),
        contentScale
= ContentScale.Crop,
        painter
= painterResource(dogIcon),

       
// Content Description is not needed here - image is decorative, and setting a null content
       
// description allows accessibility services to skip this element during navigation.

        contentDescription
= null
   
)
}
Sekarang di WoofPreview(), ikon berbentuk lingkaran.



Menambahkan bentuk ke item daftar

Di bagian ini, Anda akan menambahkan bentuk ke item daftar. Item daftar sudah ditampilkan melalui Card. Card adalah platform yang dapat berisi satu composable dan berisi opsi untuk dekorasi. Dekorasi dapat ditambahkan melalui batas, bentuk, dan lainnya. Di bagian ini, Anda akan menggunakan Card untuk menambahkan bentuk ke item daftar.


1. Buka file Shape.kt. Card adalah komponen media, sehingga Anda menambahkan parameter media objek Shapes. Untuk aplikasi ini, pojok kanan atas dan kiri bawah item daftar, tetapi tidak membentuk lingkaran penuh. Untuk mencapainya, teruskan 16.dp ke atribut medium.
medium = RoundedCornerShape(bottomStart = 16.dp, topEnd = 16.dp)
Karena Card secara default sudah menggunakan bentuk media, Anda tidak perlu menyetelnya secara eksplisit ke bentuk media. Lihat Pratinjau untuk melihat Card yang baru dibentuk.



Jika kembali ke file Theme.kt di WoofTheme() dan melihat MaterialTheme(), Anda akan melihat atribut shapes disetel ke Shapes val yang baru saja Anda update.
MaterialTheme(
   colors
= colors,
   typography
= Typography,
   shapes
= Shapes,
   content
= content
)
Berikut adalah tampilan item daftar secara berdampingan sebelum dan sesudah pembentukan. Perhatikan bahwa aplikasi ini menjadi jauh lebih menarik secara visual dengan pembentukan yang ditambahkan padanya.

###Menambahkan tipografi

Jenis huruf Desain Material
Jenis huruf adalah pilihan gaya font yang dapat digunakan di seluruh aplikasi dan memastikan gaya yang fleksibel namun konsisten. Jenis huruf Desain Material mencakup lima belas gaya font yang didukung oleh sistem jenis. Penamaan dan pengelompokannya telah disederhanakan untuk: tampilan, judul utama, judul, isi, dan label, dengan ukuran besar, sedang, dan kecil untuk masing-masing. Anda hanya perlu menggunakan pilihan ini jika ingin menyesuaikan aplikasi. Jika Anda tidak tahu apa yang harus ditetapkan untuk setiap kategori jenis huruf, ada skala tipografi default yang dapat Anda gunakan.

Jenis huruf ini berisi kategori teks yang dapat digunakan kembali, masing-masing dengan aplikasi yang dimaksudkan dan artinya.

Tampilan
Sebagai teks terbesar di layar, gaya tampilan dikhususkan untuk teks atau angka yang singkat dan penting. Gaya tampilan berfungsi paling baik di perangkat layar besar.

Judul Utama
Judul utama sangat cocok untuk teks singkat dengan penekanan tinggi pada layar yang lebih kecil. Gaya ini cocok untuk menandai bagian utama teks atau area penting konten.

Judul
Judul lebih kecil daripada gaya judul utama, dan harus digunakan untuk teks dengan penekanan sedang yang relatif singkat.

Isi
Gaya isi digunakan untuk bagian teks yang lebih panjang di aplikasi Anda.

Label
Gaya label adalah gaya yang lebih kecil dan fungsional, yang digunakan untuk hal-hal seperti teks di dalam komponen atau untuk teks yang sangat kecil di dalam isi konten, misalnya keterangan gambar.

Font
Platform Android menyediakan berbagai font, tetapi Anda mungkin ingin menyesuaikan aplikasi dengan font yang tidak disediakan secara default. Font kustom dapat menambah karakteristik dan digunakan untuk branding.

Di bagian ini, Anda akan menambahkan font khusus bernama Abril Fatface, Montserrat Bold, dan Montserrat Regular. Anda akan menggunakan judul utama displayLarge dan displayMedium, juga teks bodyLarge dari sistem Jenis Material, dan menambahkannya ke teks di aplikasi Anda

Membuat Direktori Resource Android font.
Sebelum menambahkan font ke aplikasi, Anda harus menambahkan direktori font.

1. Di tampilan project Android Studio, klik kanan folder res.
2. Pilih New > Android Resource Directory.


3. Beri nama Direktori font, setel jenis Resource sebagai font, dan klik OK.


4. Buka direktori resource font baru yang terletak di res > font

Mendownload font kustom

Karena Anda menggunakan font yang tidak disediakan oleh platform Android, Anda harus mendownload font kustom.
  1. Buka https://fonts.google.com/.
  2. Telusuri Montserrat, lalu klik Download family.
  3. Buka file zip.
  4. Buka folder Montserrat yang didownload. Di folder static, temukan Montserrat-Bold.ttf dan Montserrat-Regular.ttf (ttf adalah singkatan dari TrueType Font dan merupakan format untuk file font). Pilih kedua font dan tarik ke direktori resource font dalam project Anda di Android Studio
  5. Di folder font, ganti nama Montserrat-Bold.ttf menjadi montserrat_bold.ttf dan ganti nama Montserrat-Regular.ttf menjadi montserrat_regular.ttf.
  6. Telusuri Abril Fatface dan klik Download family.
  7. Buka folder Abril_Fatface yang telah didownload. Pilih AbrilFatface-Regular.ttf, lalu tarik ke direktori resource font.
  8. Di folder font, ganti nama Abril_Fatface_Regular.ttf menjadi abril_fatface_regular.ttf.
Seperti inilah tampilan direktori resource font dalam project Anda dengan tiga file font kustom:


Melakukan inisialisasi font

1. Di jendela project, buka ui.theme > Type.kt. Lakukan inisialisasi font yang didownload di bawah pernyataan impor dan di atas Typography val. Pertama, lakukan inisialisasi Abril Fatface dengan menyetelnya sama dengan FontFamily dan meneruskan Font dengan file font abril_fatface_regular.

import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import com.example.woof.R

val
AbrilFatface = FontFamily(
   
Font(R.font.abril_fatface_regular)
)

2. Lakukan inisialisasi Montserrat, di bawah Abril Fatface, dengan menyetelnya sama dengan FontFamily dan meneruskan Font dengan file font montserrat_regular. Untuk montserrat_bold, sertakan juga FontWeight.Bold. Meskipun Anda meneruskan file font versi cetak tebal, Compose tidak mengetahui bahwa file tersebut dicetak tebal, jadi Anda perlu menautkan file secara eksplisit ke FontWeight.Bold.

import androidx.compose.ui.text.font.FontWeight

val
AbrilFatface = FontFamily(
   
Font(R.font.abril_fatface_regular)
)

val
Montserrat = FontFamily(
   
Font(R.font.montserrat_regular),
   
Font(R.font.montserrat_bold, FontWeight.Bold)
)

Selanjutnya, Anda menetapkan berbagai jenis judul ke font yang baru saja Anda tambahkan. Objek Typography memiliki parameter untuk 13 jenis huruf berbeda yang dibahas di atas. Anda dapat menentukan sebanyak yang Anda butuhkan. Dalam aplikasi ini, kita akan menetapkan displayLarge, displayMedium, dan bodyLarge. Di bagian berikutnya dari aplikasi ini, Anda akan menggunakan labelSmall, sehingga Anda akan menambahkannya di sini.

Di bawah ini adalah tabel yang menampilkan jenis font, ketebalan, dan ukuran dari setiap judul utama yang Anda tambahkan.


3. Untuk atribut displayLarge, tetapkan sama dengan TextStyle, lalu isi fontFamily, fontWeight, dan fontSize dengan informasi dari tabel di atas. Artinya, semua teks yang ditetapkan ke displayLarge akan memiliki Abril Fatface sebagai font, dengan ketebalan font normal, dan fontSize 36.sp.

Ulangi proses ini untuk displayMedium, labelSmall, dan bodyLarge.

import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.sp

val
Typography = Typography(
   displayLarge
= TextStyle(
       fontFamily
= AbrilFatface,
       fontWeight
= FontWeight.Normal,
       fontSize
= 36.sp
   
),
   displayMedium
= TextStyle(
       fontFamily
= Montserrat,
       fontWeight
= FontWeight.Bold,
       fontSize
= 20.sp
   
),
   labelSmall
= TextStyle(
       fontFamily
= Montserrat,
       fontWeight
= FontWeight.Bold,
       fontSize
= 14.sp
   
),
   bodyLarge
= TextStyle(
       fontFamily
= Montserrat,
       fontWeight
= FontWeight.Normal,
       fontSize
= 14.sp
   
)
)

Jika Anda membuka file Theme.kt di WoofTheme() dan melihat MaterialTheme(), parameter typography sama dengan Typography val yang baru saja Anda update.

MaterialTheme(
   colors
= colors,
   typography
= Typography,
   shapes
= Shapes,
   content
= content
)

Menambahkan tipografi ke teks aplikasi
Sekarang Anda akan menambahkan jenis judul utama ke setiap instance teks di aplikasi.

1. Tambahkan displayMedium sebagai gaya untuk dogName karena merupakan informasi singkat yang penting. Tambahkan bodyLarge sebagai gaya untuk dogAge karena berfungsi cukup baik dengan ukuran teks yang lebih kecil.

@Composable
fun
DogInformation(
   
@StringRes dogName: Int,
   dogAge
: Int,
   modifier
: Modifier = Modifier
) {
   
Column(modifier = modifier) {
       
Text(
           text
= stringResource(dogName),
           style
= MaterialTheme.typography.displayMedium,
           modifier
= Modifier.padding(top = dimensionResource(id = R.dimen.padding_small))
       
)
       
Text(
           text
= stringResource(R.string.years_old, dogAge),
           style
= MaterialTheme.typography.bodyLarge
       
)
   
}
}

2. Sekarang di WoofPreview(), nama anjing akan menampilkan font Montserrat tebal dalam 20.sp, dan usia anjing menampilkan font Montserrat normal dalam 14.sp.
                                                    
Berikut ini tampilan item daftar secara berdampingan sebelum dan sesudah menambahkan tipografi. Perhatikan perbedaan font antara nama anjing dan usia anjing.


###Menambahkan Panel Atas

Scaffold adalah tata letak yang menyediakan slot untuk berbagai komponen dan elemen layar, seperti Image, Row, atau Column. Scaffold juga menyediakan slot untuk TopAppBar, yang akan Anda gunakan di bagian ini.

TopAppBar dapat digunakan untuk berbagai tujuan, tetapi dalam hal ini, Anda akan menggunakannya untuk branding dan memberikan karakteristik pada aplikasi. Ada empat jenis TopAppBar: tengah, kecil, sedang, dan besar. Dalam codelab ini, Anda akan menerapkan panel aplikasi atas di tengah. Anda akan membuat composable yang terlihat seperti screenshot di bawah, dan memasukkannya ke bagian topBar dari Scaffold.


Untuk aplikasi ini, panel atas terdiri dari Row dengan gambar logo dan teks judul aplikasi. Logo menampilkan tapak kaki bergradasi yang lucu dan judul aplikasi!


Menambahkan gambar dan teks ke panel atas
1. Di MainActivity.kt, buat composable bernama WoofTopAppBar() dengan modifier opsional.

@Composable
fun
WoofTopAppBar(modifier: Modifier = Modifier) {

}

2. Scaffold mendukung parameter contentWindowInsets yang dapat membantu menentukan inset untuk konten scaffold. WindowInsets adalah bagian layar tempat aplikasi Anda dapat bersinggungan dengan UI sistem, yang akan diteruskan ke slot konten melalui parameter PaddingValues. Baca selengkapnya di sini.

@Composable
fun
WoofApp() {
   
Scaffold { it ->
       
LazyColumn(contentPadding = it) {
            items
(dogs) {
               
DogItem(
                    dog
= it,
                    modifier
= Modifier.padding(dimensionResource(R.dimen.padding_small))
               
)
           
}
       
}
   
}
}

Nilai contentWindowInsets diteruskan ke LazyColumn sebagai contentPadding.

3. Dalam Scaffold, tambahkan atribut topBar dan tetapkan ke WoofTopAppBar().

Scaffold(
   topBar
= {
       
WoofTopAppBar()
   
}
)

Berikut adalah tampilan composable WoofApp():

@Composable
fun
WoofApp() {
   
Scaffold(
        topBar
= {
           
WoofTopAppBar()
       
}
   
) { it ->
       
LazyColumn(contentPadding = it) {
            items
(dogs) {
               
DogItem(
                    dog
= it,
                    modifier
= Modifier.padding(dimensionResource(R.dimen.padding_small))
               
)
           
}
       
}
   
}
}

Tidak ada yang berubah di WoofPreview() karena tidak ada apa pun di WoofTopAppBar(). Mari kita ubah.



4. Dalam WoofTopAppBar() Composable, tambahkan CenterAlignedTopAppBar() dan tetapkan parameter pengubah ke pengubah yang diteruskan ke WoofTopAppBar().

import androidx.compose.material3.CenterAlignedTopAppBar

@Composable
fun
WoofTopAppBar(modifier: Modifier = Modifier) {
   
CenterAlignedTopAppBar(
       modifier
= modifier
   
)
}

5. Untuk parameter judul, teruskan Row yang akan menyimpan Image dan Text dari CenterAlignedTopAppBar.

@Composable
fun
WoofTopAppBar(modifier: Modifier = Modifier){
   
CenterAlignedTopAppBar(
       title
= {
           
Row() {

           
}
       
},
       modifier
= modifier
   
)
}

6. Tambahkan logo Image ke Row.
  • Setel ukuran gambar di modifier sebagai image_size dalam file dimens.xml dan padding sebagai padding_small dari file dimens.xml.
  • Gunakan painter untuk menetapkan Image sebagai ic_woof_logo dari folder drawable.
  • Tetapkan contentDescription sebagai null. Dalam situasi ini, logo aplikasi tidak menambahkan informasi semantik apa pun bagi pengguna dengan gangguan penglihatan, sehingga kita tidak perlu menambahkan deskripsi konten.
Row() {
   
Image(
       modifier
= Modifier
           
.size(dimensionResource(id = R.dimen.image_size))
           
.padding(dimensionResource(id = R.dimen.padding_small)),
       painter
= painterResource(R.drawable.ic_woof_logo),
       contentDescription
= null
   
)
}

7. Selanjutnya, tambahkan Composable Text di dalam Row setelah Image.
  • Gunakan stringResource() untuk menetapkannya ke nilai app_name. Tindakan ini akan menetapkan teks ke nama aplikasi, yang disimpan di strings.xml.
  • Setel gaya teks ke displayLarge karena nama aplikasi singkat dan penting.
Text(
   text
= stringResource(R.string.app_name),
   style
= MaterialTheme.typography.displayLarge
)


Inilah yang muncul di WoofPreview(), dan terlihat sedikit tidak rapi karena ikon dan teks tidak sejajar secara vertikal.

8. Untuk memperbaikinya, tambahkan parameter nilai verticalAlignment ke Row dan tetapkan sama dengan Alignment.CenterVertically.

import androidx.compose.ui.Alignment

Row(
   verticalAlignment
= Alignment.CenterVertically
)




Itu terlihat jauh lebih baik.
Ini adalah Composable WoofTopAppBar() lengkap:

@Composable
fun
WoofTopAppBar(modifier: Modifier = Modifier) {
   
CenterAlignedTopAppBar(
       title
= {
           
Row(
               verticalAlignment
= Alignment.CenterVertically
           
) {
               
Image(
                   modifier
= Modifier
                       
.size(dimensionResource(id = R.dimen.image_size))
                       
.padding(dimensionResource(id = R.dimen.padding_small)),
                   painter
= painterResource(R.drawable.ic_woof_logo),

                   contentDescription
= null
               
)
               
Text(
                   text
= stringResource(R.string.app_name),
                   style
= MaterialTheme.typography.displayLarge
               
)
           
}
       
},
       modifier
= modifier
   
)
}

Jalankan aplikasi dan lihat betapa indahnya TopAppBar memadukan aplikasi.

Tampilan tanpa panel aplikasi atas:

Tampilan dengan panel aplikasi atas:

Tampilan final dengan tema gelapa:














































Tidak ada komentar:

Posting Komentar

EAS-PPB I