ข่าวสารเกี่ยวกับผลิตภัณฑ์

มีอะไรใหม่ใน Jetpack Compose รุ่นเดือนสิงหาคม 2026

อ่าน 5 นาที
ดูโปรไฟล์ของ Nick Butcher
Nick Butcher ผู้จัดการผลิตภัณฑ์

วันนี้ Jetpack Compose รุ่นเดือนสิงหาคม 2026 พร้อมให้ใช้งานอย่างเสถียรแล้ว การเปิดตัวนี้จะนำเวอร์ชัน 1.12 มาสู่โมดูล Compose หลัก (ดูการจับคู่ BOM แบบเต็ม) ซึ่งจะเปิดตัว API แบบภาพที่สมบูรณ์ เช่น การรองรับ Mesh Gradients และ Wide Color Gamut (WCG), ฟีเจอร์เลย์เอาต์โครงสร้าง เช่น พื้นที่ที่มีชื่อใน Grid, การผสานรวมกับเครื่องมือจัดการข้อมูลเข้าสู่ระบบของ Android อย่างราบรื่น รวมถึงการทดสอบและการปรับปรุงประสิทธิภาพที่สำคัญ

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

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

การเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบ

  • AGP และ Compile SDK: Compose 1.12 อัปเดต compileSdk เป็น API 37 ซึ่งต้องใช้ AGP ขั้นต่ำ 9.1.2 โปรดทราบว่า Compose จะกำหนดเป้าหมายเป็น compileSdk ล่าสุดเสมอ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเปลี่ยนแปลงนี้ได้ที่นี่
  • Modifier.onFirstVisible() เลิกใช้งานแล้ว: ย้ายข้อมูลไปที่ Modifier.onVisibilityChanged() ซึ่งให้การติดตามเกณฑ์การแสดงผลที่แม่นยำยิ่งขึ้น

กราฟิก

การไล่ระดับสีแบบตาข่าย

Compose 1.12 เปิดตัว MeshGradientPainter เพื่อช่วยคุณสร้างการไล่ระดับสีแบบหลายจุดที่เป็นธรรมชาติ

meshGradient.gif
val rows = 1
val columns = 1

val gradientPainter = remember {
    MeshGradientPainter(rows, columns) {
        // Parameters: row, column, position, color
        setVertex(0, 0, Offset(0f, 0f), Color.Red)     // Top-Left
        setVertex(0, 1, Offset(1f, 0f), Color.Blue)    // Top-Right
        setVertex(1, 0, Offset(0f, 1f), Color.Green)   // Bottom-Left
        setVertex(1, 1, Offset(1f, 1f), Color.Yellow)  // Bottom-Right
    }
}

Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

ดูข้อมูลเพิ่มเติมและตัวอย่างได้ในเอกสารประกอบ

การรองรับช่วงสีแบบกว้างและ HDR

จอแสดงผลสมัยใหม่ให้ความเที่ยงตรงของสีที่มากขึ้นและช่วงไดนามิกที่สูงขึ้น ใน Compose 1.12 เราได้เปิดใช้การรองรับไปป์ไลน์แบบเต็มสำหรับ Wide Color Gamut (P3) และการแสดงผล HDR ในกราฟิก สี และ Shader ของ Compose ระบบจะคงสีที่กำหนดไว้ในพื้นที่สีที่ไม่ใช่ sRGB (เช่น Display P3) ไว้จนถึงการแสดงผลบนแพลตฟอร์มโดยไม่มีการหนีบสี สีจะกลับไปใช้ sRGB อย่างปลอดภัยหากใช้ Color Space ที่ไม่รองรับ (เช่น CieXyz, CieLab หรือ Oklab) ใช้ Color Space ใน Android เวอร์ชันที่ไม่รองรับ (เช่น Bt2020Hlg ใน Android 13 และต่ำกว่า) หรือหากแอปทำงานบน Android 9 (API 28) และต่ำกว่า

การเปลี่ยนแปลงอื่นๆ ที่สำคัญมีดังนี้

  • เราได้เพิ่ม LayerOutsets ลงใน GraphicsLayer และ Modifier.graphicsLayer ซึ่งคุณสามารถใช้เพื่อเพิ่มขอบเขตภาพของเลเยอร์ให้เกินขนาดที่วัดได้ ใช้ LayerOutsets เพื่อหลีกเลี่ยงลักษณะการทำงานของ clipToBounds โดยนัยเมื่อเลื่อนเลเยอร์ไปยังบัฟเฟอร์นอกหน้าจอ

รูปแบบ

ในงาน Google I/O เราได้แชร์วิสัยทัศน์เบื้องต้นเกี่ยวกับ Styles API ของ Compose ซึ่งเป็นวิธีที่มีประสิทธิภาพและเป็นหนึ่งเดียวในการจัดรูปแบบคอมโพเนนต์ นับตั้งแต่นั้นมา เราได้สร้างสถาปัตยกรรมพื้นฐานอย่างต่อเนื่องเพื่อรับประกันความปลอดภัยในการกำหนดประเภทที่เข้มงวดและความถูกต้องที่คาดการณ์ได้ รวมถึงเพื่อรองรับการสร้างระบบการออกแบบที่กำหนดเอง

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

การเพิ่มประสิทธิภาพรันไทม์

Keyed SideEffect Overload

SideEffect รองรับอาร์กิวเมนต์คีย์แล้ว ซึ่งช่วยให้คุณเรียกใช้ผลข้างเคียงแบบครั้งเดียวได้ทุกครั้งที่คีย์ที่เฉพาะเจาะจงมีการเปลี่ยนแปลง ซึ่งอาจทําให้มีประสิทธิภาพดีขึ้นเมื่อเทียบกับการใช้ LaunchedEffect หรือ DisposableEffect ในกรณีที่คุณไม่ต้องการบล็อกโครูทีนหรือบล็อกการทิ้ง SideEffect เร็วกว่า LaunchedEffect สูงสุด 90% และเร็วกว่า DisposableEffect ประมาณ 20% โปรดทราบว่า SideEffect จะทำงานก่อน DisposableEffect และ LaunchedEffect ดังนั้นโปรดระมัดระวังหากย้ายข้อมูลเอฟเฟกต์ที่มีอยู่ไปยัง API นี้ โดยเฉพาะอย่างยิ่งสำหรับ LaunchedEffects ที่ต้องอาศัยการเรียกใช้เพื่อเริ่มหลังจากเฟรมปัจจุบันเสร็จสมบูรณ์ 

@Composable
fun AnalyticsTracker(userId: String, screenName: String) {
    SideEffect(key1 = userId, key2 = screenName) {
        analytics.logScreenView(userId, screenName)
    }
}

ภาพเคลื่อนไหว

การเปลี่ยนฉากแบบ 2 ขั้นตอนแบบอินเทอร์แอกทีฟ

  • Composables ใหม่: DeferredAnimatedContent และ DeferredAnimatedVisibility ช่วยให้สร้างทรานซิชัน 2 ขั้นตอนที่น่าสนใจได้ เช่น สำหรับการติดตามท่าทางสัมผัสการย้อนกลับที่คาดการณ์ได้
  • การควบคุมภาพเคลื่อนไหวด้วยตนเอง: ในช่วงระยะเวลาที่เลื่อนออกไปของการเปลี่ยนฉาก ตอนนี้คุณสามารถจัดการพร็อพเพอร์ตี้ที่มีภาพเคลื่อนไหว (เช่น สเกลหรือออฟเซ็ต) ด้วยตนเองแบบเรียลไทม์ได้แล้ว (เช่น การติดตามท่าทางสัมผัสการปัด)
  • การส่งต่อที่ราบรื่น: เมื่อระยะที่เลื่อนออกไปสิ้นสุดลง เครื่องมือการเปลี่ยนจะเข้ามาควบคุมและทำการส่งต่อที่ราบรื่น ซึ่งรวมถึงการโอนความเร็วไปยังการเปลี่ยนอัตโนมัติ
  • การรองรับองค์ประกอบที่ใช้ร่วมกัน: แฟล็ก permitTransformDuringDeferredTransition ใหม่ใน SharedContentConfig จะควบคุมว่าองค์ประกอบที่ใช้ร่วมกันจะเปลี่ยนรูปแบบตามคอนเทนเนอร์ระดับบนสุดในระหว่างระยะการเปลี่ยนที่เลื่อนออกไปหรือไม่
val state = remember { DeferredTransitionState(initialScreen) }
val transition = rememberDeferredTransition(state)

if (predictiveBackInProgress) {
    state.defer(targetScreen)
} else {
    state.animateTo(targetScreen)
}

transition.DeferredAnimatedContent(
    targetState = targetScreen,
    mutableTransformSpec = {
       MutableContentTransform {
           // Manually manipulate properties during the deferred phase
           initialContentTransform { scale = swipeProgress }
       }
    }
) { screen ->
    ScreenContent(screen)
}

ด้านล่างนี้คือการสาธิต 2 รายการของกรณีการใช้งานที่ส่งต่อภาพเคลื่อนไหวที่ขับเคลื่อนด้วยท่าทางไปยังภาพเคลื่อนไหวที่ทริกเกอร์

colorCards.gif

การผสานรวมข้อความ ข้อมูล และแพลตฟอร์ม

การจัดรูปแบบข้อความที่แก้ไขได้

API ใหม่มีการจัดรูปแบบ Rich Text สำหรับข้อความที่แก้ไขได้ใน BasicTextField ตอนนี้คุณสามารถใช้ SpanStyle และ ParagraphStyle เพื่อใช้และจัดการการจัดรูปแบบอักขระและย่อหน้าแบบอินไลน์โดยใช้โปรแกรมผ่านเมธอด addStyle() ใหม่ภายในขอบเขต TextFieldBuffer (เช่น ภายใน textFieldState.edit { ... } หรือ InputTransformation) นอกจากนี้ TextFieldBuffer ยังมี API getSpanStyles() และ getParagraphStyles() ที่แสดงออบเจ็กต์ TrackedRange ซึ่งช่วยให้คุณอ่าน อัปเดต หรือนำสไตล์ที่ใช้แล้วออกได้ TextFieldState ตอนนี้ได้เปิดเผยพร็อพเพอร์ตี้ textStyles แบบอ่านอย่างเดียวสำหรับการค้นหาสไตล์ที่ใช้งานอยู่ทั่วทั้งช่วงแล้ว เพื่อเสริมการสร้างการจัดรูปแบบ ขณะที่ TextFieldBuffer มี originalTextStyles เพื่อตรวจสอบสถานะการจัดรูปแบบก่อนการแก้ไข ระบบจะเก็บการจัดรูปแบบข้อความและคำอธิบายประกอบที่กำหนดเองไว้เมื่อมีการเปลี่ยนแปลงการกำหนดค่า

val state = rememberTextFieldState("Formatted text in Compose 1.12")

// Apply bold and color styles to a range of text
state.edit {
    addStyle(
        SpanStyle(fontWeight = FontWeight.Bold, color = Color.Blue),
        start = 0,
        end = 9
    )
}

// Query active styles from TextFieldState
val currentStyles = state.textStyles

การเลือกข้อความ

API SelectionState ใหม่ช่วยให้ควบคุมและสังเกตการณ์การเลือกข้อความภายใน SelectionContainer ได้แบบเป็นโปรแกรม การยกออบเจ็กต์ SelectionState ผ่าน rememberSelectionState() และส่งไปยัง SelectionContainer จะแสดง selectedTexts เป็นรายการแบบรีแอ็กทีฟของ AnnotatedStrings และมีเมธอดต่างๆ เช่น selectAll(), clear(), select(TextRange) และ extendSelectionByWord()

นอกจากนี้ ให้ใช้ getSelectableTexts() เพื่อดึงข้อมูลรายการข้อความที่เลือกได้ทั้งหมดตามลำดับเลย์เอาต์ และเลือกข้อความใน Composable ใน SelectionContainer โดยใช้ช่วงส่วนกลาง 

@Composable
fun ProgrammaticSelectionExample() {
    val selectionState = rememberSelectionState()

    Column {
        Button(
            onClick = { selectionState.selectAll() },
            modifier = Modifier.disableSelectionClearOnTap()
        ) {
            Text("Select All")
        }

        SelectionContainer(state = selectionState) {
            Text("Text content to be selected programmatically.")
        }
    }
}

การผสานรวม Credential Manager

ตอนนี้ช่องข้อความ Compose ได้ผสานรวมกับ Credential Manager ของ Android (API 34 ขึ้นไป) โดยตรงผ่านเฟรมเวิร์กการป้อนข้อความอัตโนมัติ (API ต่ำกว่า 34 จะจัดการโดย androidx.credentials library) การแนบพร็อพเพอร์ตี้ความหมาย credentialRequest ใหม่กับ CredentialRequestData จะทำให้ข้อมูลข้อความแจ้งพาสคีย์ ข้อมูลเข้าสู่ระบบที่บันทึกไว้ หรือคำขอลงชื่อเข้าใช้ได้โดยตรงภายในขั้นตอนข้อมูลจากผู้ใช้

@Composable
fun LoginField(textFieldState: TextFieldState) {
    val credentialData = remember {
        CredentialRequestData(
            // Specify Credential Manager request options
        )
    }

    BasicTextField(
        state = textFieldState,
        modifier = Modifier.semantics {
            credentialRequest = credentialData
        }
    )
}

การเปลี่ยนแปลงอื่นๆ ที่สำคัญมีดังนี้

  • รองรับการตั้งค่ารูปแบบแบบอักษรในแบบอักษรที่ดาวน์โหลดได้
  • เปิดใช้การเลื่อนอัตโนมัติเมื่อลากข้อความที่เลือกเกินวิวพอร์ตใน SelectionContainer
  • เพิ่มการรองรับเสียงการโต้ตอบอัตโนมัติ (การคลิกและการไปยังส่วนต่างๆ โดยใช้โฟกัส) ให้กับคอมโพเนนต์ Compose พร้อมกับคอมโพสได้ใหม่ SoundEffectOnInteraction เพื่อให้เลือกไม่ใช้ได้ โปรดทราบว่าการเปลี่ยนแปลงนี้ส่งผลให้ตอนนี้ต้องเรียกใช้เครื่องมือฟังการคลิกเชิงความหมายจากเทรดหลัก ซึ่งอาจส่งผลต่อกรณีทดสอบจำนวนเล็กน้อย
  • ตอนนี้ KeyboardType มี Date, Time, DateTime และ SignedDecimal แล้ว
  • ตอนนี้ BasicSecureTextField ใช้ TextObfuscationMode.System เป็นค่าเริ่มต้น ส่วน RevealLastTyped จะใช้เป็นการลบล้างแบบสัมบูรณ์

การปรับปรุงเลย์เอาต์

พื้นที่ที่มีชื่อในเลย์เอาต์ตารางกริด

ตอนนี้การสร้างเลย์เอาต์ 2 มิติที่ซับซ้อนทำได้ง่ายขึ้นด้วยพื้นที่ที่มีชื่อในคอมโพเนนต์ @Experimental Grid คุณสามารถกำหนดภูมิภาคเชิงความหมายใน GridConfigurationScope และวาง Composable ตามชื่อพื้นที่แทนที่จะจัดการดัชนีคอลัมน์และแถวที่เป็นตัวเลขในรายการต่างๆ

@OptIn(ExperimentalGridApi::class)
@Composable
fun DashboardLayout() {
    Grid(
        config = {
            area("header", row = 0, column = 0, rowSpan = 1, columnSpan = 2)
            area("sidebar", row = 1, column = 0)
            area("content", row = 1, column = 1)
            gap(16.dp)
        }
    ) {
        HeaderSection(modifier = Modifier.gridItem(areaId = "header"))
        NavigationSidebar(modifier = Modifier.gridItem(areaId = "sidebar"))
        MainContentView(modifier = Modifier.gridItem(areaId = "content"))
    }
}

ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบ

ประสิทธิภาพ

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

timetoinitialdisplay@2x _v2.png

การอัปเกรดการทดสอบและเครื่องมือ

การซิงค์การทดสอบ

Compose 1.12 เปิดตัว API การทดสอบใหม่ที่ออกแบบมาเพื่อลดเวลาในการดำเนินการทดสอบและขจัดความไม่แน่นอนระหว่างการสุ่มตัวอย่างสถานะ

  • hasPendingWork: ตรวจสอบโดยอัตโนมัติว่า UI มีงานที่รอดำเนินการหรือไม่โดยไม่ต้องเลื่อนเวลา ซึ่งเหมาะสำหรับลูปภาพเคลื่อนไหวที่ทำด้วยตนเอง
  • runWithoutImplicitWait: ปิดใช้การซิงค์โดยนัยชั่วคราวเมื่อเลื่อนผ่านเฟรมนาฬิกาด้วยตนเอง (เช่น การทดสอบภาพเคลื่อนไหว)
@Test
fun testAnimationStateFast() {

composeTestRule.mainClock.autoAdvance = false
    
    while (composeTestRule.hasPendingWork()) {
        composeTestRule.mainClock.advanceTimeByFrame()
        composeTestRule.waitForIdle()
        
        composeTestRule.runOnUiThread {
            composeTestRule.runWithoutImplicitWait {
                // This is most effective when querying multiple nodes in a single frame. 
                // It prevents the redundant synchronization overhead that would 
                // otherwise occur on every individual query.
                val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode()
                val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode()
                
                assertThat(box1.boundsInRoot.right).isAtMost(box2.boundsInRoot.left)
            }
        }
    }
}

การเปลี่ยนแปลงอื่นๆ ที่สำคัญมีดังนี้

  • ตอนนี้ captureToImage API ช่วยให้คุณบันทึกป๊อปอัปหรือกล่องโต้ตอบพร้อมกับจุดยึดในบิตแมปเดียวได้แล้ว
  • เพิ่ม onRootWithViewInteraction เพื่อกำหนดขอบเขตการค้นหาเชิงความหมายของ Compose ไปยัง Android View ที่เฉพาะเจาะจง ซึ่งจะช่วยลดความซับซ้อนในการทดสอบ UI แบบไฮบริด เช่น RecyclerViews โดยไม่ต้องใช้แท็กทดสอบที่ไม่ซ้ำกันในโค้ดที่ใช้งานจริง
  • ตอนนี้คุณสามารถใช้คำอธิบายประกอบ @PreviewWrapper กับ@MultiPreviewคลาสที่กำหนดเองได้แล้ว ซึ่งจะช่วยให้ตั้งค่าตัวอย่างที่นำกลับมาใช้ใหม่ได้ (เช่น ธีมที่กำหนดเอง) ในคอมโพเนนต์หลายรายการ

ขอให้สนุกกับการแต่งเพลง

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

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