Android Codelabs Together ตอน Jetpack Compose Basics

android Apr 27, 2021

กลับมาใน season 2 ของงาน Android Codelabs Together และในที่สุด! ก็ได้ถึงเวลา! ได้ลองทำ! Jetpack Compose ซะที

โดยใน season นี้จะฉายเวลา 19:00 - 21:00 มีทั้งหมด 3 ตอนด้วยกันคือ

  • Jetpack Compose Basic (25 เมษายน 2564) บล็อกนี้
  • Layout in Jetpack Compose (2 พฤษภาคม 2564)
  • Using State in Jetpack Compose (9 พฤษภาคม 2564)

ก่อนเริ่มงาน

ก่อนอื่นเลย ไปดูคลิปนี้กันก่อน การเตรียมตัวสำหรับงานนี้ในเบื้องต้น

https://www.youtube.com/watch?v=uFd859RfGCQ

ทางเราเลย list และสรุปให้เนอะว่าต้องเตรียมอะไรบ้าง อ่ะปายยยยยยยย~~

ทำความรู้จักกันก่อนว่า Jetpack Compose คืออะไร?

Jetpack Compose คือ toolkit สำหรับสร้าง Android UI ด้วย code แบบ DSL Style (domain-specific language) ทำให้เราสามารถเห็นโค้ด UI ที่เราเขียนได้ ในตอนนี้ก็เป็น Beta แล้วเนอะ

มันจะคล้ายๆกับ Swift UI ฝั่ง iOS แล้วก็การเขียน UI ใน Flutter นั่นแหละ

สำหรับคราวที่แล้ว ในปีที่แล้วก็มีกิจกรรม Android Codelab Together เหมือนกัน พูดในส่วนของการทำ Unit Testing ใน Android Architecture Components เราก็จะคุ้นเคยกับเจ้า Codelab เป็นอย่างดี

มาเขียนเทสกัน กับงาน Android Codelabs Together ตอน Testing Basics
ฝั่ง Firebase เขาก็มีกันไปแล้ว เป็น Codelab เขียนเว็บ แล้วฝั่ง Android จะยอมน้อยหน้ากันได้อย่างไรจริงม่ะ
https://www.mikkipastel.com/android-codelabs-together-testing-basics/

Codelab คือ tutorial set ในการเรียนรู้ในเรื่องต่างๆ เช่น การเขียน Unit Testing หรือในหลายๆบทความของเราก็ทำจาก codelab แล้วมาสรุปให้ฟัง ไม่ว่าจะเป็นเรื่องของ Repository, Room, Object Animator, Motion Layout และอื่นๆ

ทาง Google มี pathways สำหรับ Jetpack Compose โดยเฉพาะ ซึ่งเราจะทำ code lab ในหน้านี้กัน โดยเข้าไปอ่าน article กันก่อนได้ที่

Jetpack Compose | Android Developers
Learn about Compose, a modern toolkit for building native Android UI.
https://developer.android.com/courses/pathways/compose

และอย่าลืม Sign-in เข้าไปด้วยนะ เพราะมันจะเก็บ progress ของเรา และถ้าเราทำครบ เราก็จะได้ badge ประดับ profile ของเรา

สิ่งที่ต้องเตรียมให้พร้อม คือ Android Studio ที่เราใช้ทำงานจะเป็นแบบปกติเนอะ แต่ในที่นี้ให้Android Studio Arctic Fox (2020.3.1.10) เพราะเป็น version ที่สามารถเขียน Jetpack Compose ได้นั่นเอง ติดตั้งต่างๆให้เรียบร้อย และทดสอบดูว่าทำงานได้ไหมเนอะ

Android Studio Preview | Android Developers
<!-- hide description -->
https://developer.android.com/studio/preview

และอย่าลืม sign-in เพื่อรับ badge ของตัว Android Studio Canary มาประดับ profile เราด้วยนะ

จริงๆมี Badge Android Studio ด้วยนะ เผื่อใครอยากไปตำ วิธีเดิมคือ ไปหน้า Android Studio นั่นแหละ

feature ใน version นี้

New features in Android Studio Preview | Android Developers
Discover new features and changes in Android Studio preview.
https://developer.android.com/studio/preview/features#2020.3.1

จากนั้นเปิดโปรแกรม Android Studio Preview แน่นอนว่ามี UI ใหม่ที่เขา redesign จากเดิม สวยขึ้นเป็นกอง

ไปสร้างโปรเจกใหม่ เลือก Empty Compose Activity

จากนั้นกินหนมรอจนมันบิ้วเสร็จโหลดเสร็จ กดบิ้วอีกรอบ จะได้หน้าตาแบบนี้


ถึงเวลาแล้วมาเริ่มเรียนกันเล้ยย~~!

ก่อนอื่นเข้าไปเตรียมของต่างๆให้เรียบร้อย และเข้าไปเรียนไปพร้อมๆกันที่นี่เลยจ้า

https://www.youtube.com/watch?v=HrZf0hTDAcg

แต่ตอนถ่ายทอดคือแอบติดขัดนิดนึง คือ ดันได้ยินเสียงออกข้างขวาข้างเดียวจ้า ไม่แน่ใจว่าเกิดจากอะไรอะเนอะ เพราะก็งงกันไปหมดทุกคนเลย แล้วช่วงท้ายๆคือคอมน้องเบนขิตไปเลยอ่ะ คนดูส่งแรงใจแล้วแต่คอมน้องก็ยังขิต มุแง

ช่วงแรกจะเป็นการพูดคุยกันก่อนเนอะ

มีหลากหลายประเด็นตั้งแต่เปิดรายการมา ยันระหว่างทำ codelab เลยมาแปะทั้งหมดไว้ที่นี่ที่เดียวเลยหล่ะกัน

  • การปล่อยของออกมาให้เราใช้นั้น จะเริ่มที่ developer version แล้วขยับไปเป็น preview แล้วไป alpha และ beta ซึ่ง API มัน stable แล้ว ไม่ปรับบ่อยเหมือนก่อนหน้านี้หล่ะ เน้นเพิ่ม feature และ bug fix กัน
  • "The first stable release of AndroidX 1.0.0 suitable for use in production was released on September 21, 2018." << อันนี้ลอกเม้นมาว่าเจ้า Jetpack Compose เกิดมาตอนไหน
  • สำหรับ pathways ของ Jetpack Compose นั้น ถ้าจบงานนี้ไปแล้วให้อ่าน Tutorial: Compose Basics และไปฟัง Compose Beta Overview เพื่อเพิ่มความเข้าใจของเราให้มากขึ้นเนอะ
  • Jetpack Compose นั้นคือการสร้าง UI บน Android แบบใหม่ เขียนด้วย Kotlin เป็นคนละ style กับ xml ดังนั้นจะต้องไปอ่าน Compose Mental Model ใน pathways เพิ่มจ้า จะเป็นการอธิบายการใช้งาน และ behavior การทำงาน เป็นการเปลี่ยน mindset วิธีคิดในการทำ UI เพื่อทำให้เรา implement ได้ถูกต้องขึ้น
  • Compose เป็น framework แยกวิธีการ render ของต่างๆจากโค้ดที่เราเขียน เป็น DSL Style (domain-specific language) เปลี่ยนเป็นอะไรก็ได้ เช่น บน desktop จะเป็น Java Swing ส่วนบน Mobile จะเป็น Android
  • ฝั่ง view มีหน้าที่แค่แสดง data ออกมา ซึ่งเหมือนกับบน web เช่นใน React (ที่เราดองไว้ว่าจะเรียน), SwiftUI บน iOS หรือบน Flutter เองก็ตาม
  • การทำ UI ที่เราทำอยู่ปัจจุบันคือใช้ XML เป็น Imperative UI เป็นการสร้าง XML และมี getter/setter ให้เราสามารถ set data เข้า view นั้นๆได้
  • ส่วนแบบ Compose เป็น Declarative UI เขียนสิ่งที่เราต้องการอยากให้เห็น เหมือนเป็นแม่พิมพ์
  • จริงๆใน pathways นั้นไม่ได้มี codelab แค่ 3 อัน แต่คนสอนมองว่าถ้าเราผ่านสามอันแรกมาได้ อันที่เหลือเราก็ทำเองได้แบบชิวๆหล่ะ
  • "แล้วแบบนี้ทำไมถึงมีทำออกมากันซ้ำรอครับ ทั้งที่มี flutter อยู่แล้ว? หรือมีปัจจัยอื่น" >> คนละทีมกัน ทำ parallel กัน และแยกงานกันชัดเจน และมี goal ต่างกัน
  • "kotlin multiplatform สามารถใช้ร่วมกันได้ไหมครับ" >> ใช้ได้ที่ android และ desktop เนื่องจากมี compile ได้ แต่ไม่ค่อยมีคนใช้ท่านี้กันเท่าไหร่
  • "นอกเรืองนิดครับ ui test จะเหมือนเดิมไหมครับ" >> golden test, snapshot test ออกมาเป็นรูปเก็บไว้ ดู hirency, id ของ view จะหายไป, compose testing
  • "อันนี้สงสัยขึ้นมาคับ เวลาทำ ui test มันชอบนานเพราะต้องรันทั้งแอป ถ้ามีตัว preview แบบนี้ เราสามารถ test ui แบบ แยกได้ไหมครับ โดยที่ไม่ต้องรันทั้งแอป" >> build app with module
ปล. ส่วนอันอื่นๆใน pathways เดี๋ยวจะทยอยสรุปให้อีกทีจ้า เรียนรู้ไปพร้อมๆกัน

เริ่มทำ codelab แรกของ Jetpack Compose กันเถอะ

– Jetpack Compose basics

Before you begin

ในส่วนนี้เป็นการ introduction ว่าเราต้องเตรียมอะไรบ้างนะ ตอนพูดคุยกันก่อนเริ่มก็ได้กล่าวไปพอสมควรเลยแหละ

  • syntax ของ Kotlin เราจะต้องรู้กันอยู่แล้วเนอะ และไม่แนะนำให้ใช้เป็น Java ซึ่งมันจะเป็น byte code ผ่าน Kotlin compiler โค้ดที่ออกมานั้นเขาบอกกันว่าน่าสยดสยองเลยทีเดียว
  • ติดตั้ง Android Studio ที่เป็น Canary ซึ่งจะมีคลิปก่อนหน้านี้ และด้านบนๆของบทความ

Starting a new Compose project

  • สร้างโปรเจกใหม่ ซึ่งใน codelab จะเป็น UI เก่า ไม่ตรงกับ video ชื่อโปรเจกจะตั้งว่า BasicCodelabs กันงง (แต่ของเราดันตั้งชื่อโปรเจกว่า Compose ไปแล้ว ถ้ามีอันนี้หลุดมาก็คือสาเหตุนี้แหละ)
  • Jetpack Compose ลองรับ API level 21 ขึ้นไป
  • ความแตกต่างระหว่างโปรเจกปกติ กับแบบที่มี Compose ก็คือใน gradle นั่นเอง มี buildFeatures ที่ต้องใส่ compose true เพิ่ม, kotlinCompilerVersion, และ dependency ของตัว Compose โดยใน codelab นี้จะใช้ 1.0.0-beta05 นะ
build.gradle ของ module app
build.gradle ของโปรเจก
  • พวก release note ต่างๆสามารถไปส่องได้ที่นี่จ้า
Recent Release Notes | Android Developers
https://developer.android.com/jetpack/androidx/versions/all-channel
Compose | Android Developers
https://developer.android.com/jetpack/androidx/releases/compose
  • จากนั้นเราจะส่องกันที่ MainActivity.kt เป็นหลัก โดยเราจะเปิดแบบ split เพื่อให้เห็น design ที่เราทำการ coding ไว้เนอะ และเมื่อเราทำการ update view แล้ว ไปกดเพื่อให้มัน build ให้ preview หรือจะกด key ลัด command + option + shift + r สำหรับ MacOs นะ
  • การกดดูหน้า UI ของเรานั้น มันจะ zoom in/zoom out เร็วกว่าปกติ แบบเผลอเลื่อนไวไปหน่อย หน้า UI ใหญ่เว่อร์ไปเลย แนะนำให้กด +/- แทนเน้อ
  • เราสามารถให้มัน preview เฉพาะส่วนที่เราต้องการได้ โดยการใส่ annotation ไปแบบนี้ @Preview ไว้บน function และเมื่อเราเพิ่ม function ของ compose view ขึ้นมา ให้ทำการใส่ @Composable ไว้ด้านบน function เพื่อให้ตัว Kotlin compiler จับ annotation มาให้ และทำการ build และ gen code มาให้เรา
  • ดังนั้นในเรื่อง naming จะต่างจากปกติคือ นำหน้าด้วยตัวพิมพ์ใหญ่ เนื่องจากมองเป็น component นึงนั่นเอง

Getting started with Compose

  • เริ่มต้นโดยการสร้าง Composable function และใส่ @Composable เข้าไป เช่น เราจะสร้าง TextView ตัวนึง ชื่อว่า Greeting รับค่า string ของชื่อ แล้วนำไปแสดงใน TextView นั่นเอง
@Composable
fun Greeting(name: String) {
   Text(text = "Hello $name!")
}
  • การ set layout ปกติที่เป็น xml เราจะใช้ setContentView(R.layout.activity_main) กันเนาะ (ถ้าใช้ View Binding จะประกาศอีกแบบนึง) แต่ใน Jetpack Compose เราจะใช้ setContent {} แทน ข้างในมีการกำหนด theme โดยอิงชื่อตามโปรเจกที่เราสร้าง
setContent {
    BasicsCodelabTheme {
        Surface(color = MaterialTheme.colors.background) {
            Greeting("Android")
        }
    }
}
  • @Preview จะแสดง view ที่เราสร้างขึ้นมาไม่ต้องไปหาแปะที่ไหน และสามารถ preview ได้หลายๆตัวพร้อมๆกันได้ โดยใช้เฉพาะตอนที่เราจะ preview เพื่อดู UI ที่เราทำเท่านั้นนะ
@Preview(showBackground = true, name = "Text preview")
@Composable
fun DefaultPreview() {
    BasicsCodelabTheme {
        Greeting(name = "Android")
    }
}
  • ในที่นี้คุณเอกได้ลองทำปุ่มให้ดูอันนึง และเราไม่ต้องทำตามเขานะ เขาแค่แสดงให้ดูว่าใส่กี่ view เพื่อ preview ก็ได้
  • มี Interactive Mode สามารถกดปุ่มหรือทำอะไรต่างๆได้จริง เทสที่นี่ได้เลย ไม่ต้องไปบิ้วแอพเพื่อเทส
  • มี Deploy Preview สามารถเอา view แต่ละตัวไปแสดงในเครื่องจริงได้ โดยไม่ต้องสร้างแอพขึ้นมา
  • และใน Canary นั้น สามารถแสดง view ให้เราแบบ realtime ได้เลย

Declarative UI

  • เมื่อเราทำการ build preview เราจะต้องรอสักพักเนอะ ถ้ามันบิ้วเสร็จ จะมีติ๊กถูกตรงมุมบนขวา
  • Surface เป็น view เปล่า ที่เราจะเอาไปแปะที่ไหนก็ได้
  • ตอน import เข้ามาต้องระวัง ให้ import สิ่งที่เป็น androidx.compose เข้ามา
  • เราสามารถเข้าไปดูว่าแต่ละตัวมีอะไรให้เราใช้บ้าง โดยทำการกด command แล้วคลิกสิ่งที่เราสนใจ เช่น อยากรู้ว่า Text ใส่อะไรได้บ้างก็เข้าไปดูได้เลยจ้า
  • modifier เราสามารถใส่พวก padding ต่างๆเข้าไปได้ เช่น ใส่ที่ Surface มันจะระบายสีตรงที่จะ render จริง ทำให้ได้พื้นหลังไม่เต็มจอ จะมีความคล้ายๆ margin แต่ให้เราใส่ padding ตามที่ที่เราต้องการไปอย่างเดียว เพื่อลดความสับสน ถ้าใส่ใน Text มันก็จะระบายเต็มให้เราหมด
  • ตัว modifier สามารถพิมพ์ dot ต่อได้เลย เป็น fully interface
  • เราไม่ต้องทำการสร้าง shape drawable ต่างๆอีกต่อไป เราสามารถใช้ผ่าน code ได้เลย สามารถทำ background ครอบ view ได้ และสามารถใช้ padding 2 ชั้นได้ ไม่ต้องใช้ margin
  • Jetpack Compose สามารถ reuse ได้หลายๆที่ แต่ตัวอย่างเขายกมาทั้งหมดเลย แหะๆ คือเล่นยกมาทั้ง theme เลยวุ้ย ชื่อว่า MyApp ยกทุกสิ่งที่อยู่ภายใต้ setContent ออกมาเลยจ้า
  • สร้าง container function เป็นการเปลี่ยนของที่อยู่ข้างใน ที่สามารถรับ content แล้ว render ตัว view ข้างใน
  • เวลาจริงเราอาจจะสร้างไฟล์แยกแต่ละ component มาใช้งานก็ได้นะ
  • ลองทำ Greeting หลายๆอันซ้อนกัน มี Column, Row, Divider โดยค่าของ names นั้น ก็จะมี default ให้หล่ะ จะได้แบบนี้

State in Compose

  • recomposing คือการ render เฉพาะส่วนที่เปลี่ยน ทำให้ performance ดีขึ้น
  • ในส่วนนี้จะทำการโยน data เข้าไป แล้วให้มัน render เอง เช่น ในที่นี้ทำปุ่มให้เรากด แล้วนับจำนวนครั้งที่เรากดปุ่มนี้
  • ข้างใน Counter() สร้างตัวแปร count เป็น generic type ใส่ value type ไหนก็ดึง type นั้นออกมา
  • ส่วน remember คืออะไรเป็นสิ่งที่มันต้องจำ ถ้าค่าเปลี่ยน UI ก็จะถูก render ใหม่ หรือถูก recompose นั่นเอง เป็นการจัดการ state ให้เรา โดยที่เราไม่ต้องไปสนใจ lifecycler ของแอพเพื่อไป handle เอง
@Composable
fun Counter() {

    val count = remember { mutableStateOf(0) }

    Button(onClick = { count.value++ }) {
        Text("I've been clicked ${count.value} times")
    }
}
  • ทำเสร็จก็เอาไปเรียกใช้ที่อื่นได้เลย
@Composable
fun MyScreenContent(names: List<String> = listOf("Android", "there")) {
    Column {
        for (name in names) {
            Greeting(name = name)
            Divider(color = Color.Black)
        }
        Divider(color = Color.Transparent, thickness = 32.dp)
        Counter()
    }
}
  • ตัว container นั้นสามารถรับ function ที่โยนเข้ามา เพื่อมา render ได้เอง
  • อยากให้ state อันนี้ใครเป็นคนจัดการ? ขึ้นอยู่กับการวาง logic ของเรา และอาจจะให้คนถือเป็นคนจัดการ state
  • เราจะให้ data ถูก control โดยใคร? เราจะให้ MyScreenContent() ใข้ได้ในหลายๆที่ ทำให้ counter รับเป็น function เพื่อให้นำมา control ใน compitable ตัวมันเอง เป็นstate pointing เพื่อไม่ให้มันถือและนำไปบวกเอง จนมันมั่วแล้วทำให้เรางง เพราะบางที่อาจจะใช้ logic ในการแสดงผลที่ไม่เหมือนกัน
@Composable
fun MyScreenContent(names: List<String> = listOf("Android", "there")) {
    val counterState = remember { mutableStateOf(0) }

    Column {
        for (name in names) {
            Greeting(name = name)
            Divider(color = Color.Black)
        }
        Divider(color = Color.Transparent, thickness = 32.dp)
        Counter(
            count = counterState.value,
            updateCount = { newCount ->
                counterState.value = newCount
            }
        )
    }
}

@Composable
fun Counter(count: Int, updateCount: (Int) -> Unit) {
    Button(onClick = { updateCount(count+1) }) {
        Text("I've been clicked $count times")
    }
}

Feature ที่ช่วยเราทำงานสร้าง UI สำหรับ Jetpack Compose เวลาเราทำงานเราจะ split หน้าจอออกมาแบบนี้เนอะ สีเขียวด้านขวาบนที่หน้า design เป็นตัวบอกว่า เอ้ออเราบิ้ว preview เสร็จแล้วนะ

อ่ะเข้ามาซูมใกล้ๆกันหน่อย จะมี 2 ส่วนที่เราสนใจ นั่นคือ

Interactive Mode เป็นโหมดเสมือนเรารันแอพนี้จริงๆ โดยนำส่วน @Preview มาแสดง แต่ไม่ต้องรันแอพบนเครื่องจริงนะ เราสามารถกดโน้นนี่นั่น เลื่อนขึ้นลงไปมาเหมือนเล่นกับเครื่องตัวเองได้เลย

Deploy Preview เป็นการนำส่วน @Preview มาแสดงบนเครื่องจริง โดยไม่ต้องบิ้วทั้งแอพ แค่เอาหน้านี้มาบิ้วในเครื่องเราก็พอล้าวว

Flexible layouts

  • หลักการคล้าย XML เดิม แต่ค่ามันจะเปลี่ยนไปนิดหน่อย
  • ขยายให้มันเต็มหน้าจอ โดยใช้ fillMaxHeight
  • ตรง preview เราสามารถกำหนด size, background หรือโน้นนี่เองได้ ว่าเราอยากเทสในการแสดง UI ยังไง
  • weight เหมือนใน LinearLayout คำนวณจาก weightSum เหมือนกัน
@Composable
fun MyScreenContent(names: List<String> = listOf("Android", "there")) {
    val counterState = remember { mutableStateOf(0) }

    Column(modifier = Modifier.fillMaxHeight()) {
        Column(modifier = Modifier.weight(1f)) {
            for (name in names) {
                Greeting(name = name)
                Divider(color = Color.Black)
            }
        }
        Counter(
            count = counterState.value,
            updateCount = { newCount ->
                counterState.value = newCount
            }
        )
    }
}
  • colors เปลี่ยนสีพื้นหลัง มี issue บางอย่าง คือพอให้มัน auto complete มามันจะแปลกๆ เราต้องพิมพ์เอง เช่น
  • ในที่นี้เราสามารถสร้าง function มารับค่า และเปลี่ยนแปลงการแสดงผลได้ เช่น เมื่อค่า count > 5 จะเปลี่ยนการแสดงพื้นหลังของปุ่ม
@Composable
fun Counter(count: Int, updateCount: (Int) -> Unit) {
    Button(
        onClick = { updateCount(count+1) },
        colors = ButtonDefaults.buttonColors(
            backgroundColor = if (count > 5) Color.Green else Color.White
        )
    ) {
        Text("I've been clicked $count times")
    }
}
  • LazyColumn() จะคล้ายๆ lazyload, item กำหนด list ให้กับมัน และต้อง import เข้ามาเนื่องจากเป็น inline function และทำการ return item สิ่งที่อยู่ใน list นี้มาให้เรา เมื่อเราไปเปิดใน Interactive Mode พบว่ามันลื่นมากๆเลยในตอน scroll ลงมา
  • ซึ่ง LazyColumn() มี performance ไม่เท่ากับ RecyclerView ตรงเรื่องของ reuse resourse เมื่อหลุดจากจอแล้วกลับมาใหม่ พบว่าที่เรากดไปนั้นมันหายไป เพราะว่ามันสร้างอันใหม่ ลบอันเก่าทิ้งตลอดเวลา
@Composable
fun NameList(names: List<String>, modifier: Modifier = Modifier) {
   LazyColumn(modifier = modifier) {
       items(items = names) { name ->
           Greeting(name = name)
           Divider(color = Color.Black)
       }
   }
}

Animating your list

  • การทำ animation กับตัว compose อย่างง่าย (ถ้าอย่างเต็มที่จะอยู่ใน codelab ท้ายๆของชุดนี้) โดยเล่นกับตัว state

อันนี้ codelab วางบัค อ่ะพอพิมพ์สิ่งนี้ตามใน codelab จะเกิดปัญหา

อาจจะแก้โดยการเปลี่ยน by เป็น = โค้ดจะเป็นแบบนี้ เราจะต้อง .value เพื่อเข้าถึงค่าที่อยู่ข้างใน

@Composable
fun Greeting(name: String) {
   var isSelected = remember {
        mutableStateOf(false)
    }
   val backgroundColor = animateColorAsState(if (isSelected.value) Color.Red else Color.Transparent)

   Text(
       text = "Hello $name!",
       modifier = Modifier
           .padding(24.dp)
           .background(color = backgroundColor)
           .clickable(onClick = { isSelected = !isSelected })
   )
}

หรือ import getValue มาจะได้เหมือนใน codelab หล่ะ

  • isSelected เราเคยกดหรือยัง
  • animateColorAsState ใช้กับที่ที่เราจะเปลี่ยนเป็น animation โดยมันจะ animate ค่าสีโดยการ fade ให้เราตอนกด
  • อื่นๆที่น่าสนใจ นอกจากสียังเป็นอื่นๆได้ด้วย เช่น animateFullAsState, animateFloatAsState

Theming your app

  • design system คือสิ่งที่เป็น style guide ของแอพของเรานั่นแหละ ว่าแต่ละ component ในแอพจะมีหน้าตาเป็นอย่างไรบ้าง designer เป็นคน define component ในส่วน UI ไปให้ developer เนอะ ทำให้ง่ายต่อการคุยกันในทีม เช่น สีแดง นี่สีแดงไหน แดงเข้ม เข้มแบบไหนนะ ถ้ามี hex color และชื่อมาเราก็จะเข้าใจได้ทันที ก็เหมือนหนุ่มๆเลือกสีลิปสติกให้สาวๆ ซึ่งสาวๆควรบอกชื่อสีไปเลยจะได้ไม่ต้องงงกัน อะไรงี้
  • เรากำหนดได้เลยโดยใช้ผ่าน theme ซึ่งเป็นไฟล์ที่อยู่ใน ui.theme ชื่อไฟล์ Theme.kt เป็นภาษา Kotlin ที่เรารัก เป็น composible ที่กำหนด theme
  • ส่วน darkTheme ในที่นี้จะกำหนดจากเครื่องเราว่าตอนนี้เครื่องเราใช้ dark theme อยู่ไหมนะ
  • เจอสีหลายๆ primary ก็จะงงๆเนอะ colorPrimary จะเป็นสีพื้นหลัง ส่วน colorOnPrimary จะเป็นสีของ content เช่นสีของตัวหนังสือใน TextView สามารถไปดูเพิ่มเติมได้ที่ codelab theming ที่อยู่ใน pathways เดียวกันเนอะ ส่วนเรื่องสีไปอ่าน document ใน Material Design ได้
Material Design
Build beautiful, usable products faster. Material Design is an adaptable system—backed by open-source code—that helps teams build high quality digital experiences.
https://material.io/design/color/the-color-system.html#color-theme-creation
  • ส่วน default style ของเจ้า Text จะเป็น MaterialTheme.typography.body1 นะ
  • อันนี้ลองเปลี่ยนเป็น H2
@Composable
fun Greeting(name: String) {
    val isSelected = remember {
        mutableStateOf(false)
    }
    val backgroundColor = animateColorAsState(if (isSelected.value) Color.Red else Color.Transparent)
    
    Text(
        text = "Hello $name!",
        modifier = Modifier
            .padding(24.dp)
            .background(color = backgroundColor.value)
            .clickable(onClick = { isSelected.value = !isSelected.value }),
        style = MaterialTheme.typography.h2
    )
}

จะได้แบบนี้

  • copy data เพื่อ modified ค่าด้านในได้ และสร้าง theme ข้างในได้

คำถามนี้ดี แต่ขอแอบใส่ไว้ด้านหลังสุด เพื่อเป็นการ summary แหะๆ

ระหว่าง xml กับ Composable แบบนี้มี ผลต่อขนาด app ไหมครับ

คำตอบคือ น้อยกว่า เพราะมันโตตามจำนวน code ไม่ใช่โตตามจำนวนไฟล์ ทำให้ size ลดลง ขนาดเล็กลง ทั้ง app size and data count

โดย reference ของคำตอบมาจาก blog ของคุณ Chris Banes ในบล็อกจะพูดถึง TiVi เป็นแอพ track ว่าเราดู tv content อะไรบ้าง

Jetpack Compose — Before and after
Since the start of this year, I’ve been slowly migrating the UI in Tivi to be written in Jetpack Compose, and this week, the first stage of that migration is now complete! 🎉 In this blog post, we’ll…
https://medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f

อันนี้ repo เผื่ออยากส่อง

chrisbanes/tivi
Tivi is a work-in-progress TV show tracking Android app, which connects to Trakt.tv. It is still in its early stages of development and currently only contains two pieces of UI. It is under heavy d...
https://github.com/chrisbanes/tivi

เมื่อทำ codelab เรียบร้อยแล้วก็เข้าสู่ Q & A ซึ่งทั้งหมดน้องเบนบอกว่าเราเลทไปทั้งหมด 1 ชั่วโมง 4 นาที นั่นเองจ้า ไม่เป็นไรเนอะเพราะในไลฟ์เกิดเหตุไม่คาดฝันหลายอย่างอยู่เนอะ คราวหน้าหวังว่าเสียงจะออกสองข้างล้าวนะ และคอมน้องเบนจงแข็งแรง :D

เจอกันครั้งต่อไป วันอาทิตย์ที่ 2 พฤษภาคม นี้น้าา~~

ปล. สรุปอาจจะมึนๆหน่อย เพราะทางเรารีบแหละ อาทิตย์นี้มีอีกสองงาน ซึ่งเทสรุปไปหนึ่งเพราะงง ส่วนอีกอันเดี๋ยวได้อ่านเร็วๆนี้เนอะ


download แอพอ่านบล็อกใหม่ของเราได้ที่นี่

MikkiPastel - Apps on Google Play
First application from “MikkiPastel” on play store beta feature- read blog from https://www.mikkipastel.com by this application- read blog content by chrome custom tab- update or refresh new content by pull to refresh- share content to social network
https://play.google.com/store/apps/details?id=com.mikkipastel.blog

ติดตามข่าวสารและบทความใหม่ๆได้ที่

อย่าลืมกด like กด share บทความกันด้วยนะคะ :)

Posted by MikkiPastel on Sunday, 10 December 2017

ช่องทางใหม่ใน Twiter จ้า

และ YouTube ช่องใหม่จ้า

mikkicoding
Android Developer & Content Creator
https://www.youtube.com/channel/UCtGbMSe4i7NJiKQ271Fezcg

Tags

Minseo Chayabanjonglerd

Android Developer ผู้เป็นเจ้าของบล็อก MikkiPastel ที่ชอบทำหลายๆอย่างนอกจากเขียนแอพแอนดรอยด์ เช่น เขียนบล็อก เขียนแชทบอท เรียนออนไลน์ อ่านหนังสือ วาดรูปเล่น ดู netfilx สั่งอาหารอร่อยๆกัน เป็นต้น

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.