ข่าวสารผลิตภัณฑ์

มีอะไรใหม่ใน Jetpack Compose เวอร์ชันเมษายน '26

ใช้เวลาอ่าน 6 นาที
ดูโปรไฟล์ของ Meghan Mehta
Meghan Mehta ผู้ประสานงานนักพัฒนาแอป Android

วันนี้ Jetpack Compose เวอร์ชันเมษายน '26 พร้อมใช้งานแล้ว เวอร์ชันนี้มีโมดูลหลักของ Compose เวอร์ชัน 1.11 (ดู การจับคู่ BOMแบบเต็ม) เครื่องมือแก้ไขข้อบกพร่องขององค์ประกอบที่แชร์ เหตุการณ์ของแทร็กแพด และอื่นๆ นอกจากนี้ เรายังมี API แบบทดลองที่คุณสามารถลองใช้และแสดงความคิดเห็นได้

หากต้องการใช้เวอร์ชันที่เผยแพร่ในวันนี้ ให้อัปเกรด Compose BOMเป็นเวอร์ชันต่อไปนี้

implementation(platform("androidx.compose:compose-bom:2026.04.01"))

การเปลี่ยนแปลงใน Compose 1.11.0

การดำเนินการโครูทีนในการทดสอบ

เรากำลังเปิดตัวการอัปเดตครั้งใหญ่เกี่ยวกับวิธีที่ Compose จัดการการกำหนดเวลาในการทดสอบ หลังจากช่วงที่ให้เลือกใช้ตามที่ประกาศไว้ใน Compose 1.10 ตอนนี้ API การทดสอบ v2 เป็นค่าเริ่มต้นแล้ว และเราได้เลิกใช้งาน API v1 การเปลี่ยนแปลงที่สำคัญคือการเปลี่ยนตัวจัดส่งการทดสอบเริ่มต้น ในขณะที่ API v1 อาศัย UnconfinedTestDispatcher ซึ่งดำเนินการโครูทีนทันที แต่ API v2 ใช้ StandardTestDispatcher ซึ่งหมายความว่าเมื่อมีการเปิดใช้โครูทีนในการทดสอบ ระบบจะจัดคิวโครูทีนและจะไม่ดำเนินการจนกว่าจะมีการเลื่อนนาฬิกาเสมือน

การดำเนินการนี้จะจำลองสภาพแวดล้อมการใช้งานจริงได้ดีขึ้น ซึ่งจะช่วยขจัดสภาวะการแข่งขันและทำให้ชุดการทดสอบมีความเสถียรมากขึ้นและมีข้อผิดพลาดน้อยลง

เราขอแนะนำอย่างยิ่งให้ย้ายข้อมูลชุดการทดสอบเพื่อให้การทดสอบสอดคล้องกับลักษณะการทำงานของโครูทีนมาตรฐานและหลีกเลี่ยงปัญหาความเข้ากันได้ในอนาคต ดู คู่มือการย้ายข้อมูลที่ครอบคลุมของเราสำหรับการจับคู่ API และการแก้ไขปัญหาที่พบบ่อย

การปรับปรุงองค์ประกอบที่แชร์และเครื่องมือภาพเคลื่อนไหว

นอกจากนี้ เรายังได้เพิ่มเครื่องมือแก้ไขข้อบกพร่องแบบภาพที่เป็นประโยชน์สำหรับองค์ประกอบที่แชร์และ Modifier.animatedBounds ตอนนี้คุณจะเห็นสิ่งที่เกิดขึ้นเบื้องหลังได้อย่างชัดเจน เช่น ขอบเขตเป้าหมาย เส้นทางการเคลื่อนไหว และจำนวนรายการที่พบ ซึ่งจะช่วยให้คุณระบุได้ง่ายขึ้นว่าเหตุใดการเปลี่ยนภาพจึงอาจทำงานไม่เป็นไปตามที่คาดไว้ หากต้องการใช้เครื่องมือใหม่ เพียงล้อมรอบ SharedTransitionLayout ด้วยคอมโพสได้ LookaheadAnimationVisualDebugging

LookaheadAnimationVisualDebugging(
    overlayColor = Color(0x4AE91E63),
    isEnabled = true,
    multipleMatchesColor = Color.Green,
    isShowKeylabelEnabled = false,
    unmatchedElementColor = Color.Red,
) {
    SharedTransitionLayout {
        CompositionLocalProvider(
            LocalSharedTransitionScope provides this,
        ) {
            // your content
        }
    }
}

เหตุการณ์ของแทร็กแพด

เราได้ปรับปรุงการรองรับแทร็กแพดของ Compose เช่น แทร็กแพดในตัวของแล็ปท็อป แทร็กแพดแบบติดได้สำหรับแท็บเล็ต หรือแทร็กแพดภายนอก/เสมือน ตอนนี้ระบบจะพิจารณาเหตุการณ์แทร็กแพดพื้นฐานเป็นเหตุการณ์ PointerType.Mouse โดยทั่วไป ซึ่งจะทำให้ลักษณะการทำงานของเมาส์และแทร็กแพดสอดคล้องกับความคาดหวังของผู้ใช้มากขึ้น ก่อนหน้านี้ ระบบจะตีความเหตุการณ์แทร็กแพดเหล่านี้เป็นนิ้วสัมผัสหน้าจอปลอมของ PointerType.Touch ซึ่งทำให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่สับสน เช่น การคลิกและลากด้วยแทร็กแพดจะเลื่อนแทนที่จะเลือก การเปลี่ยนประเภทตัวชี้ที่เหตุการณ์เหล่านี้มีใน Compose เวอร์ชันล่าสุดจะทำให้การคลิกและลากด้วยแทร็กแพดไม่เลื่อนอีกต่อไป

นอกจากนี้ เรายังได้เพิ่มการรองรับท่าทางสัมผัสที่ซับซ้อนมากขึ้นของแทร็กแพดตามที่แพลตฟอร์มรู้จักตั้งแต่ API 34 เป็นต้นมา ซึ่งรวมถึง การปัดด้วย 2 นิ้วและ การบีบ คอมโพเนนต์ต่างๆ เช่น Modifier.scrollable และ Modifier.transformable จะรู้จักท่าทางสัมผัสเหล่านี้โดยอัตโนมัติเพื่อให้ทำงานกับแทร็กแพดได้ดีขึ้น

การเปลี่ยนแปลงเหล่านี้ช่วยปรับปรุงลักษณะการทำงานของแทร็กแพดในคอมโพเนนต์ในตัว โดยนำการเลื่อนสัมผัสที่ซ้ำซ้อนออก ท่าทางสัมผัสเริ่มต้นแบบลากและวางที่ใช้งานง่ายมากขึ้น การเลือกแบบดับเบิลคลิกและทริปเปิลคลิกในช่องข้อความ และเมนูบริบทสไตล์เดสก์ท็อปในช่องข้อความ

หากต้องการทดสอบลักษณะการทำงานของแทร็กแพด ให้ใช้ API การทดสอบใหม่ที่มี performTrackpadInput, ซึ่งช่วยให้คุณตรวจสอบลักษณะการทำงานของแอปเมื่อใช้กับแทร็กแพดได้ หากคุณมีเครื่องมือตรวจจับท่าทางสัมผัสที่กำหนดเอง ให้ตรวจสอบลักษณะการทำงานในประเภทอินพุตต่างๆ รวมถึงหน้าจอสัมผัส เมาส์ แทร็กแพด และสไตลัส และตรวจสอบว่ามีการรองรับล้อเลื่อนของเมาส์และท่าทางสัมผัสของแทร็กแพด

beforeAndAfter.webp

ค่าเริ่มต้นของโฮสต์การจัดองค์ประกอบ (รันไทม์ของ Compose)

เราได้เปิดตัว HostDefaultProviderLocalHostDefaultProviderHostDefaultKey, และ ViewTreeHostDefaultKey เพื่อให้บริการระดับโฮสต์โดยตรงผ่านรันไทม์ของ Compose ซึ่งจะช่วยให้ไลบรารีไม่ต้องขึ้นอยู่กับ compose-ui ในการค้นหา และรองรับ Kotlin Multiplatform ได้ดีขึ้น หากต้องการลิงก์ค่าเหล่านี้กับแผนผังการจัดองค์ประกอบ ผู้เขียนไลบรารีสามารถใช้ compositionLocalWithHostDefaultOf เพื่อสร้าง CompositionLocal ที่แก้ค่าเริ่มต้นจากโฮสต์

ตัวห่อหุ้มการแสดงตัวอย่าง

การแสดงตัวอย่างที่กำหนดเองของ Android Studio เป็นฟีเจอร์ใหม่ที่ช่วยให้คุณกำหนดวิธีแสดงเนื้อหาของการแสดงตัวอย่าง Compose ได้อย่างแม่นยำ

การใช้อินเทอร์เฟซ PreviewWrapperProvider และใช้คำอธิบายประกอบ @PreviewWrapper ใหม่จะช่วยให้คุณแทรกลอจิกที่กำหนดเองได้อย่างง่ายดาย เช่น การใช้ Theme ที่เฉพาะเจาะจง คุณสามารถใช้คำอธิบายประกอบกับฟังก์ชันที่มีคำอธิบายประกอบ @Composable และ @Preview หรือ @MultiPreview ซึ่งเป็นโซลูชันทั่วไปที่ใช้งานง่ายและใช้ได้กับฟีเจอร์การแสดงตัวอย่างต่างๆ และช่วยลดโค้ดที่ซ้ำซ้อนได้อย่างมาก

class ThemeWrapper: PreviewWrapperProvider {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}


@PreviewWrapper(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
    // JetsnackTheme in effect
    Button(onClick = {}) {
        Text(text = "Demo")
    }
}

การเลิกใช้งานและการนำออก

  • ตามที่ประกาศไว้ใน บล็อกโพสต์ Compose 1.10 เราจะเลิกใช้งาน Modifier.onFirstVisible() ชื่อของฟังก์ชันนี้มักทำให้เกิดความเข้าใจผิด โดยเฉพาะอย่างยิ่งในเลย์เอาต์แบบ Lazy ซึ่งฟังก์ชันนี้จะทริกเกอร์หลายครั้งระหว่างการเลื่อน เราขอแนะนำให้ย้ายข้อมูลไปใช้ Modifier.onVisibilityChanged() ซึ่งช่วยให้คุณติดตามสถานะการมองเห็นด้วยตนเองได้อย่างแม่นยำมากขึ้นตามข้อกำหนดของ Use Case ที่เฉพาะเจาะจง
  • เราได้นำแฟล็ก ComposeFoundationFlags.isTextFieldDpadNavigationEnabled ออกเนื่องจากตอนนี้ระบบจะเปิดใช้การนำทางด้วย D-pad สำหรับ TextFields โดยค่าเริ่มต้นเสมอ ลักษณะการทำงานใหม่นี้จะทำให้เหตุการณ์ D-pad จากเกมแพดหรือรีโมตทีวีเลื่อนเคอร์เซอร์ไปในทิศทางที่กำหนดก่อน โฟกัสจะย้ายไปยังองค์ประกอบอื่นได้ก็ต่อเมื่อเคอร์เซอร์ไปถึงจุดสิ้นสุดของข้อความ

API ที่กำลังจะมา

ใน Compose 1.12.0 เวอร์ชันที่จะเผยแพร่ในอนาคต เราจะอัปเกรด compileSdk เป็น compileSdk 37 โดยที่ AGP 9 รวมถึงแอปและไลบรารีทั้งหมดที่ขึ้นอยู่กับ Compose จะรับข้อกำหนดนี้ เราขอแนะนำให้คุณอัปเดตเป็นเวอร์ชันที่เผยแพร่ล่าสุดอยู่เสมอ เนื่องจาก Compose มีเป้าหมายที่จะนำ compileSdks ใหม่มาใช้โดยเร็วเพื่อมอบสิทธิ์เข้าถึงฟีเจอร์ล่าสุดของ Android อย่าลืมดู เอกสารประกอบที่นี่เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับ AGP เวอร์ชันที่รองรับสำหรับ API ระดับต่างๆ 

ใน Compose 1.11.0 เราได้เปิดตัว API ต่อไปนี้เป็น @Experimental และหวังว่าจะได้รับความคิดเห็นจากคุณเมื่อคุณลองใช้ API เหล่านี้ในแอป โปรดทราบว่าเราได้จัดเตรียม @Experimental APIs ไว้เพื่อให้คุณประเมินและแสดงความคิดเห็นเบื้องต้น และ API เหล่านี้อาจมีการเปลี่ยนแปลงหรือนำออกอย่างมากในเวอร์ชันที่จะเผยแพร่ในอนาคต

สไตล์ (ทดลอง)

เรากำลังเปิดตัว API พื้นฐานแบบทดลองใหม่สำหรับ การจัดสไตล์ Style API เป็นกระบวนทัศน์ใหม่สำหรับการปรับแต่งองค์ประกอบภาพของคอมโพเนนต์ ซึ่งโดยปกติแล้วจะทำด้วยตัวปรับแต่ง API นี้ออกแบบมาเพื่อปลดล็อกการปรับแต่งที่ลึกซึ้งและง่ายขึ้นโดยการเปิดเผยชุดพร็อพเพอร์ตี้ที่จัดสไตล์ได้มาตรฐานด้วยการจัดสไตล์ตามสถานะและการเปลี่ยนภาพเคลื่อนไหวที่เรียบง่าย เราเห็นประโยชน์ด้านประสิทธิภาพที่น่าพอใจจาก API ใหม่นี้แล้ว เราวางแผนที่จะนำสไตล์มาใช้ในคอมโพเนนต์ Material เมื่อ Style API มีความเสถียร

ตัวอย่างพื้นฐานของการลบล้างพื้นหลังสไตล์สถานะที่กด

@Composable
fun LoginButton(modifier: Modifier = Modifier) {
    Button(
        onClick = {
            // Login logic
        },
        modifier = modifier,
        style = {
            background(
                Brush.linearGradient(
                    listOf(lightPurple, lightBlue)
                )
            )
            width(75.dp)
            height(50.dp)
            textAlign(TextAlign.Center)
            externalPadding(16.dp)

            pressed {
                background(
                    Brush.linearGradient(
                        listOf(Color.Magenta, Color.Red)
                    )
                )
            }
        }
    ){
        Text(
            text = "Login",
        )
    }
}
styles.webp

ดู เอกสารประกอบและรายงานข้อบกพร่องต่างๆ ได้ ที่นี่

MediaQuery (ทดลอง)

API mediaQuery ใหม่เป็นวิธีประกาศและมีประสิทธิภาพในการปรับ UI ให้เข้ากับสภาพแวดล้อม API นี้จะดึงข้อมูลที่ซับซ้อนมาไว้ในเงื่อนไขที่เรียบง่ายภายใน UiMediaScope เพื่อให้มั่นใจว่าการจัดองค์ประกอบใหม่จะเกิดขึ้นเมื่อจำเป็นเท่านั้น

การรองรับสัญญาณสภาพแวดล้อมที่หลากหลาย ตั้งแต่ความสามารถของอุปกรณ์ เช่น ประเภทคีย์บอร์ดและความแม่นยำของตัวชี้ ไปจนถึงสถานะตามบริบท เช่น ขนาดและท่าทางของหน้าต่าง จะช่วยให้คุณสร้างประสบการณ์การใช้งานที่ตอบสนองได้ดี เราได้รวมประสิทธิภาพไว้ใน derivedMediaQuery เพื่อจัดการการอัปเดตที่มีความถี่สูง ในขณะที่ความสามารถในการลบล้างขอบเขตจะทำให้การทดสอบและการแสดงตัวอย่างราบรื่นในทุกการกำหนดค่าฮาร์ดแวร์ ก่อนหน้านี้ หากต้องการเข้าถึงพร็อพเพอร์ตี้บางอย่างของอุปกรณ์ เช่น หากอุปกรณ์อยู่ใน โหมดวางบนโต๊ะ คุณจะต้องเขียนโค้ดจำนวนมากเพื่อทำเช่นนั้น 

@Composable
fun isTabletopPosture(
    context: Context = LocalContext.current
): Boolean {
    val windowLayoutInfo by
        WindowInfoTracker
            .getOrCreate(context)
            .windowLayoutInfo(context)
            .collectAsStateWithLifecycle(null)

    return windowLayoutInfo.displayFeatures.any { displayFeature ->
        displayFeature is FoldingFeature &&
            displayFeature.state == FoldingFeature.State.HALF_OPENED &&
            displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
    }
}

@Composable
fun VideoPlayer() {
    if(isTabletopPosture()) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

ตอนนี้ UIMediaQuery ช่วยให้คุณเพิ่มไวยากรณ์ mediaQuery เพื่อค้นหาพร็อพเพอร์ตี้ของอุปกรณ์ได้ เช่น หากอุปกรณ์อยู่ในโหมดวางบนโต๊ะ

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun VideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

ดู เอกสารประกอบและรายงานข้อบกพร่องต่างๆ ได้ ที่นี่

กริด (ทดลอง)

Grid เป็น API ใหม่ที่มีประสิทธิภาพสำหรับการสร้างเลย์เอาต์ 2 มิติที่ซับซ้อนใน Jetpack Compose แม้ว่า Row และ Column จะเหมาะสำหรับการออกแบบเชิงเส้น แต่ Grid จะให้การควบคุมโครงสร้างที่จำเป็นสำหรับสถาปัตยกรรมระดับหน้าจอและคอมโพเนนต์ที่ซับซ้อนโดยไม่ต้องมีค่าใช้จ่ายเพิ่มเติมของรายการที่เลื่อนได้ Grid ช่วยให้คุณกำหนดเลย์เอาต์โดยใช้แทร็ก ช่องว่าง และเซลล์ โดยมีตัวเลือกการปรับขนาดที่คุ้นเคย เช่น Dp เปอร์เซ็นต์ ขนาดเนื้อหาโดยธรรมชาติ และหน่วย "Fr" ที่ยืดหยุ่น

@OptIn(ExperimentalGridApi::class)
@Composable
fun GridExample() {
    Grid(
        config = {
            repeat(4) { column(0.25f) }
            repeat(2) { row(0.5f) }
            gap(16.dp)
        }
    ) {
        Card1(modifier = Modifier.gridItem(rowSpan = 2)
        Card2(modifier = Modifier.gridItem(colmnSpan = 3)
        Card3(modifier = Modifier.gridItem(columnSpan = 2)
        Card4()
    }
}

คุณสามารถวางรายการโดยอัตโนมัติหรือขยายรายการอย่างชัดเจนในหลายแถวและคอลัมน์เพื่อให้ได้ความแม่นยำ และที่สำคัญที่สุดคือ API นี้ปรับเปลี่ยนได้สูง คุณสามารถกำหนดค่าแทร็กและช่วงของกริดใหม่แบบไดนามิกเพื่อตอบสนองต่อสถานะของอุปกรณ์ เช่น โหมดวางบนโต๊ะหรือการเปลี่ยนแปลงการวางแนว เพื่อให้มั่นใจว่า UI จะดูดีในทุกรูปแบบ

Grid.gif

ดู เอกสารประกอบและรายงานข้อบกพร่องต่างๆ ได้ ที่นี่

FlexBox (ทดลอง)

FlexBox เป็นคอนเทนเนอร์เลย์เอาต์ที่ออกแบบมาสำหรับ UI ที่ปรับเปลี่ยนได้และมีประสิทธิภาพสูง API นี้จะจัดการการปรับขนาดรายการและการกระจายพื้นที่ตามขนาดคอนเทนเนอร์ที่มีและจัดการงานที่ซับซ้อน เช่น การตัดข้อความ (wrap) และการจัดแนวรายการหลายแกน (justifyContent, alignItems, alignContent) รวมถึงอนุญาตให้รายการขยาย (grow) หรือย่อ (shrink) เพื่อเติมคอนเทนเนอร์

@OptIn(ExperimentalFlexBoxApi::class)
fun FlexBoxWrapping(){
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
        }
    ) {
        RedRoundedBox()
        BlueRoundedBox()
        GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) })
        OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) })
        PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) })
    }
}
AnimationGif.gif

ดู เอกสารประกอบและรายงานข้อบกพร่องต่างๆ ได้ ที่นี่

การติดตั้งใช้งาน SlotTable ใหม่ (ทดลอง)

เราได้เปิดตัวการติดตั้งใช้งาน SlotTable ใหม่ ซึ่งปิดใช้อยู่โดยค่าเริ่มต้นในเวอร์ชันนี้ SlotTable เป็นโครงสร้างข้อมูลภายในที่รันไทม์ของ Compose ใช้เพื่อติดตามสถานะของลำดับชั้นการจัดองค์ประกอบ ติดตามการทำให้เป็นโมฆะ/การจัดองค์ประกอบใหม่ จัดเก็บค่าที่จดจำไว้ และติดตามข้อมูลเมตาทั้งหมดของการจัดองค์ประกอบในรันไทม์ การติดตั้งใช้งานใหม่นี้ออกแบบมาเพื่อปรับปรุงประสิทธิภาพ โดยเฉพาะอย่างยิ่งเกี่ยวกับการแก้ไขแบบสุ่ม

หากต้องการลองใช้ SlotTable ใหม่ ให้เปิดใช้ ComposeRuntimeFlags.isLinkBufferComposerEnabled 

เริ่มเขียนโค้ดวันนี้เลย

Jetpack Compose มี API ใหม่ๆ ที่น่าตื่นเต้นมากมาย และจะมี API อื่นๆ อีกมากมายตามมา ดังนั้นตอนนี้จึงเป็นเวลาที่เหมาะที่สุดที่จะ ย้ายข้อมูลไปใช้ Jetpack Composeเราให้ความสำคัญกับความคิดเห็นและคำขอฟีเจอร์ของคุณเสมอ (โดยเฉพาะอย่างยิ่งสำหรับฟีเจอร์ @Experimental ที่ยังอยู่ในระหว่างการพัฒนา) โปรดส่งความคิดเห็นและคำขอต่างๆ ที่นี่ ขอให้สนุกกับการจัดองค์ประกอบ

เขียนโดย:
อ่านต่อ