การติดตามการมองเห็นใน Compose

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

  • onVisibilityChanged - ตัวแก้ไขนี้จะแจ้งให้คุณทราบเมื่อระดับการมองเห็นของ Composable มีการเปลี่ยนแปลง ซึ่งเหมาะสำหรับการทริกเกอร์การดำเนินการหรือผลข้างเคียงทุกครั้งที่ฟังก์ชันที่ประกอบกันได้ปรากฏขึ้น
  • onLayoutRectChanged - ตัวแก้ไขนี้ให้ข้อมูลเกี่ยวกับขอบเขตของ Composable ที่สัมพันธ์กับรูท หน้าต่าง และหน้าจอ โดยจะให้การควบคุมระดับต่ำและเป็น API พื้นฐานสำหรับ onVisibilityChanged ตัวแก้ไขนี้คล้ายกับ onGloballyPositioned แต่มีประสิทธิภาพดีกว่าและมีความยืดหยุ่นมากขึ้น

คุณใช้ API เหล่านี้กับ Composable ใดก็ได้โดยเป็นส่วนหนึ่งของเชนตัวแก้ไข

ติดตามการเปลี่ยนแปลงระดับการเข้าถึงด้วย onVisibilityChanged

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

หากต้องการรับการแจ้งเตือนเมื่อระดับการมองเห็นของรายการมีการเปลี่ยนแปลง ให้ใช้ตัวแก้ไข onVisibilityChanged ดังที่แสดงในตัวอย่างต่อไปนี้

Text(
    text = "Some text",
    modifier = Modifier
        .onVisibilityChanged { visible ->
            if (visible) {
                // Do something if visible.
            } else {
                // Do something if not visible.
            }
        }
        .padding(vertical = 8.dp)
)

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

ลำดับมีความสำคัญต่อตัวแก้ไข onVisibilityChanged เช่นเดียวกับตัวแก้ไขอื่นๆ ตัวอย่างก่อนหน้านี้แสดงฟังก์ชันที่ประกอบกันได้ซึ่งแสดงผลข้อความที่มีระยะห่างจากขอบ หากต้องการตรวจสอบว่าตัวแก้ไขส่งผลต่อ Composable ทั้งหมดพร้อมกับระยะห่างจากขอบ ให้เพิ่มตัวแก้ไข onVisibilityChanged ก่อนตัวแก้ไข padding

กำหนดขีดจำกัดเวลาใน Composable ก่อนเรียกใช้ Callback ระดับการเข้าถึง

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

หากต้องการทริกเกอร์การดำเนินการหลังจากที่รายการปรากฏเป็นระยะเวลาที่กำหนด ให้ใช้พารามิเตอร์ minDurationMs ในตัวแก้ไข onVisibilityChanged พารามิเตอร์นี้ระบุระยะเวลาขั้นต่ำที่ Composable ต้องแสดงอย่างต่อเนื่องเพื่อให้ทริกเกอร์ Callback หาก Composable ไม่ปรากฏก่อนถึงระยะเวลาที่กำหนด ระบบจะรีเซ็ตตัวจับเวลา ค่าเริ่มต้นคือ 0 มิลลิวินาที

ข้อมูลโค้ดต่อไปนี้จะเปลี่ยนพื้นหลังเป็นสีม่วงหลังจากที่ผู้ใช้มองเห็น Composable เป็นเวลา 3 วินาที

var background by remember { mutableStateOf(PalePink) }
Card(
    modifier = modifier
        // ...
        .onVisibilityChanged(minDurationMs = 3000) {
            if (it) {
                background = MutedPlum
            }
        }
) {

    Box(
        modifier = Modifier
            // ...
            .background(background),
        contentAlignment = Alignment.Center,
    ) {
        // ...
    }
}

รูปที่ 1 พื้นหลังจะเปลี่ยนจากสีชมพูเป็นสีม่วงพลัมหลังจากที่ Composable อยู่บนหน้าจอเป็นเวลา 3 วินาทีติดต่อกัน

กำหนดเศษส่วนที่มองเห็นได้ขั้นต่ำ

การตั้งค่าเศษส่วนที่มองเห็นได้ขั้นต่ำสำหรับ Callback ระดับการเข้าถึงของ Composable จะมีประโยชน์เมื่อทำงานกับเนื้อหาที่เลื่อนได้ (เช่น LazyColumn) เพื่อเพิ่มประสิทธิภาพการดึงข้อมูลสำหรับรายการที่เกินขนาดหน้าจอ

ในกรณีดังกล่าว ให้ใช้พารามิเตอร์ minFractionVisible ในตัวปรับแต่ง onVisibilityChanged เพื่อกำหนดเศษส่วนที่ต้องอยู่บนหน้าจอเพื่อให้ Composable ได้รับการทำเครื่องหมายว่ามองเห็นได้ โดยรองรับค่าแบบ Float ตั้งแต่ 0.0f ถึง 1.0f และตั้งค่าเป็น 1.0f โดยค่าเริ่มต้น 1.0f หมายความว่า Composable ต้องปรากฏบนหน้าจออย่างสมบูรณ์ หรือเติมเต็มวิวพอร์ตทั้งหมดหากมีขนาดใหญ่กว่าวิวพอร์ต

Callback จะได้รับ true เมื่อเศษส่วนที่มองเห็นได้มากกว่า minFractionVisible หรือเมื่อ Composable มองเห็นได้ทั้งหมดหรือเต็มวิวพอร์ต ไม่เช่นนั้นจะได้รับ false

LazyColumn(
    modifier = modifier.fillMaxSize()
) {
    item {
        Box(
            modifier = Modifier
                // ...
                // Here `visible` is `true` when more than 20% of the composable is visible.
                .onVisibilityChanged(
                    minFractionVisible = 0.2f,
                ) { visible ->
                    if (visible) {
                        // Call specific logic here.
                        // viewModel.fetchDataFromNetwork()
                    }
                }
                .padding(vertical = 16.dp)
        ) {
            Text(
                text = "Sample Text",
                modifier = Modifier.padding(horizontal = 16.dp)
            )
        }
    }
}

รูปที่ 2 โดยไม่ได้ตั้งค่า minFractionVisible รูปที่ 3 โดยตั้งค่า minFractionVisible เป็น 0.2f

ตัวอย่างที่ใช้ก่อนหน้านี้จะโหลด Androidify Bot ล่วงหน้าจากเครือข่ายก่อนที่ Composable จะแสดงอย่างสมบูรณ์ ในรูปที่ 2 บ็อตที่ 3 ไม่โหลดเนื่องจาก Composable ไม่ปรากฏอย่างสมบูรณ์ ในรูปที่ 3 มีการตั้งค่า minFractionVisible และบ็อตที่ 3 จะโหลดก่อนที่จะปรากฏบนหน้าจออย่างสมบูรณ์

ซ่อน Composable และเก็บพื้นที่ไว้

หากต้องการซ่อน Composable โดยไม่เปลี่ยนเลย์เอาต์รอบๆ ให้ใช้ตัวแก้ไข visible เมื่อคุณส่ง false ระบบจะยังคงวัดค่า Composable แต่จะไม่วางหรือวาด visible(false) แตกต่างจากการตั้งค่า alpha เป็น 0f ตรงที่ยังนำองค์ประกอบออกจากแผนผังการช่วยเหลือพิเศษและปิดใช้การโต้ตอบด้วยการสัมผัสด้วย ขณะเดียวกันก็ยังคงรักษาพื้นที่เลย์เอาต์ไว้

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

Row(modifier, verticalAlignment = Alignment.CenterVertically) {
    Icon(
        painter = painterResource(R.drawable.check),
        contentDescription = "Saved",
        modifier = Modifier
            // The icon keeps its space while it's hidden, so the text doesn't move.
            .visible(isSaved)
    )
    Text("Draft", Modifier.padding(start = 8.dp))
}

ใช้ visible เมื่อเลย์เอาต์รอบๆ Composable ต้องไม่เคลื่อนที่เมื่อ Composable ปรากฏขึ้นและหายไป หากต้องการนำ Composable และพื้นที่ของ Composable ออก อย่าเรียกใช้หรือใช้ AnimatedVisibility เพื่อทำให้ Composable เคลื่อนไหวเข้าและออก