หน้าจอล่าสุด

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

หน้าจอ "ล่าสุด" ใช้โมเดลที่เน้นเอกสาร เป็นหลัก ซึ่งเปิดตัวใน Android 5.0 (API ระดับ 21) ซึ่งอินสแตนซ์หลายรายการของ กิจกรรมเดียวกันที่มีเอกสารต่างกันจะปรากฏเป็นงานในหน้าจอ "ล่าสุด" ตัวอย่างเช่น Google ไดรฟ์อาจมีงานสำหรับเอกสาร Google หลายรายการ เอกสารแต่ละรายการจะปรากฏเป็นงานในหน้าจอ "ล่าสุด" ดังนี้

หน้าจอ "ล่าสุด" แสดงเอกสาร Google ไดรฟ์ 2 รายการ โดยแต่ละรายการจะแสดงเป็นงานแยกกัน

อีกตัวอย่างที่พบบ่อยคือเมื่อผู้ใช้ใช้เบราว์เซอร์และแตะแชร์ > Gmail หน้าจอเขียนของแอป Gmail จะปรากฏขึ้น การแตะปุ่ม ล่าสุดในเวลานั้นจะแสดง Chrome และ Gmail ที่ทำงานเป็น งานแยกกัน

หน้าจอ "ล่าสุด" แสดง Chrome และ Gmail ที่ทำงานเป็นงานแยกกัน

โดยปกติแล้ว คุณจะปล่อยให้ระบบกำหนดวิธีแสดงงานและกิจกรรมในหน้าจอ "ล่าสุด" คุณไม่จำเป็นต้องแก้ไขลักษณะการทำงานนี้ อย่างไรก็ตาม แอปของคุณสามารถกำหนดวิธีและเวลาที่กิจกรรมปรากฏใน หน้าจอ "ล่าสุด" ได้

คลาส ActivityManager.AppTask ช่วยให้คุณจัดการงานได้ และค่าสถานะกิจกรรมของคลาส Intentช่วยให้คุณระบุได้ว่าเมื่อใดที่มีการเพิ่มหรือนำกิจกรรมออกจากหน้าจอ "ล่าสุด" นอกจากนี้ แอตทริบิวต์ <activity> ยังช่วยให้คุณกำหนดลักษณะการทำงานในไฟล์ Manifest ได้ด้วย

เพิ่มงานลงในหน้าจอ "ล่าสุด"

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

ใช้ Flag ของ Intent เพื่อเพิ่มงาน

เมื่อสร้างเอกสารใหม่สำหรับกิจกรรม คุณจะเรียกใช้เมธอด startActivity() โดยส่ง Intent ที่เปิดใช้กิจกรรมไปยังเมธอดนั้น หากต้องการแทรกตัวแบ่งตรรกะเพื่อให้ระบบถือว่ากิจกรรมของคุณเป็นงานใหม่ในหน้าจอ "ล่าสุด" ให้ส่งแฟล็ก FLAG_ACTIVITY_NEW_DOCUMENT ในเมธอด addFlags() ของ Intent ที่เปิดใช้กิจกรรม

หากคุณตั้งค่าแฟล็ก FLAG_ACTIVITY_MULTIPLE_TASK เมื่อสร้างเอกสารใหม่ ระบบจะสร้างงานใหม่โดยมี กิจกรรมเป้าหมายเป็นรูทเสมอ การตั้งค่านี้ช่วยให้เปิดเอกสารเดียวกัน ในงานมากกว่า 1 งานได้ โค้ดต่อไปนี้แสดงวิธีที่กิจกรรมหลัก ทำเช่นนี้และเริ่มกิจกรรมใหม่จาก Composable

private fun newDocumentIntent(context: Context): Intent =
    Intent(context, NewDocumentActivity::class.java).apply {
        addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
        putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, documentCounter++)
    }

@Composable
fun CreateDocumentButton() {
    val context = LocalContext.current
    Button(
        onClick = {
            val intent = newDocumentIntent(context)
            // Add FLAG_ACTIVITY_MULTIPLE_TASK if needed based on state
            context.startActivity(intent)
        }
    ) {
        Text("Create New Document")
    }
}

เมื่อกิจกรรมหลักเปิดใช้กิจกรรมใหม่ ระบบจะค้นหาใน งานที่มีอยู่เพื่อหากิจกรรมที่มี Intent ตรงกับชื่อคอมโพเนนต์ Intent และ ข้อมูล Intent ของกิจกรรม หากไม่พบงานหรือ Intent มีแฟล็ก FLAG_ACTIVITY_MULTIPLE_TASK ระบบจะสร้างงานใหม่โดยมีกิจกรรมเป็นรูท

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

class DocumentCentricActivity : ComponentActivity() {
    private var documentState by mutableStateOf(
        DocumentState(
            count = 0,
            textResId = R.string.hello_new_document_counter
        )
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val initialCount = intent.getIntExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0)

        documentState = documentState.copy(count = initialCount)

        setContent {
            MaterialTheme {
                DocumentScreen(
                    count = documentState.count,
                    textResId = documentState.textResId
                )
            }
        }
    }

    override fun onNewIntent(newIntent: Intent) {
        super.onNewIntent(newIntent)
        // If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this Activity is reused.
        documentState = documentState.copy(
            textResId = R.string.reusing_document_counter
        )
    }

    data class DocumentState(val count: Int, @StringRes val textResId: Int)

    companion object {
        const val KEY_EXTRA_NEW_DOCUMENT_COUNTER = "KEY_EXTRA_NEW_DOCUMENT_COUNTER"
    }
}

@Composable
fun DocumentScreen(count: Int, @StringRes textResId: Int) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center
    ) {
        // UI reacts to whichever string resource ID was passed down
        Text(text = stringResource(id = textResId))
        Spacer(modifier = Modifier.height(8.dp))
        Text(text = "Counter: $count")
    }
}

ในโค้ดก่อนหน้า กิจกรรมจะจัดการการกำหนดเส้นทางระดับระบบปฏิบัติการ (onCreate และ onNewIntent) ขณะที่ฟังก์ชัน @Composable มีหน้าที่รับผิดชอบเฉพาะ การแสดงผล UI ตามสถานะที่ระบุ

ใช้แอตทริบิวต์กิจกรรมเพื่อเพิ่มงาน

กิจกรรมยังระบุในไฟล์ Manifest ได้ว่าจะเปิดใช้ในงานใหม่เสมอโดยใช้แอตทริบิวต์ <activity> android:documentLaunchMode แอตทริบิวต์นี้มี 4 ค่า ซึ่งจะทำให้เกิดผลต่อไปนี้เมื่อผู้ใช้ เปิดเอกสารด้วยแอปพลิเคชัน

intoExisting
กิจกรรมจะนำงานที่มีอยู่สำหรับเอกสารมาใช้ซ้ำ ซึ่งเหมือนกับการตั้งค่าแฟล็ก FLAG_ACTIVITY_NEW_DOCUMENT โดยไม่ตั้งค่าแฟล็ก FLAG_ACTIVITY_MULTIPLE_TASK ตามที่อธิบายไว้ในส่วน การใช้แฟล็ก Intent เพื่อเพิ่มงาน
always
กิจกรรมจะสร้างงานใหม่สำหรับเอกสาร แม้ว่าจะเปิดเอกสารอยู่แล้วก็ตาม การใช้ค่านี้จะเหมือนกับการตั้งค่าทั้งแฟล็ก FLAG_ACTIVITY_NEW_DOCUMENT และ FLAG_ACTIVITY_MULTIPLE_TASK
none
กิจกรรมนี้จะไม่สร้างงานใหม่สำหรับเอกสาร หน้าจอ "ล่าสุด" จะถือว่ากิจกรรมเป็นค่าเริ่มต้น โดยจะแสดงงานเดียว สำหรับแอป ซึ่งจะกลับมาทำงานต่อจากกิจกรรมที่ผู้ใช้เรียกใช้ล่าสุด
never
กิจกรรมนี้จะไม่สร้างงานใหม่สำหรับเอกสาร การตั้งค่านี้จะลบล้างลักษณะการทำงานของ FLAG_ACTIVITY_NEW_DOCUMENT และ FLAG_ACTIVITY_MULTIPLE_TASK หากตั้งค่าใดค่าหนึ่งใน Intent และหน้าจอ "ล่าสุด" แสดงงานเดียวสำหรับแอป แอปจะกลับมาทำงานต่อจากกิจกรรมใดก็ตามที่ผู้ใช้เรียกใช้ล่าสุด

นำสิ่งที่ต้องทำออก

โดยค่าเริ่มต้น งานเอกสารจะออกจากหน้าจอ "ล่าสุด" โดยอัตโนมัติ เมื่อกิจกรรมเสร็จสิ้น คุณลบล้างลักษณะการทำงานนี้ได้ด้วยคลาส ActivityManager.AppTask โดยใช้แฟล็ก Intent หรือใช้แอตทริบิวต์ <activity>

คุณยกเว้นงานจากหน้าจอ "ล่าสุด" ได้ทุกเมื่อโดยตั้งค่าแอตทริบิวต์ <activity> android:excludeFromRecents เป็น true

คุณตั้งค่าจำนวนงานสูงสุดที่แอปจะรวมไว้ใน หน้าจอ "ล่าสุด" ได้โดยตั้งค่า แอตทริบิวต์ <activity> android:maxRecents เป็น ค่าจำนวนเต็ม เมื่อมีงานครบตามจำนวนสูงสุด งานที่ใช้งานล่าสุดจะหายไปจากหน้าจอ "ล่าสุด" ค่าเริ่มต้นคือ 16 และค่าสูงสุดคือ 50 (25 ในอุปกรณ์ที่มีหน่วยความจำต่ำ) ค่าที่น้อยกว่า 1 ไม่ถูกต้อง

ใช้คลาส AppTask เพื่อนำงานออก

ในกิจกรรมที่สร้างงานใหม่ในหน้าจอ "ล่าสุด" คุณสามารถ ระบุเวลาที่จะนำงานออกและสิ้นสุดกิจกรรมทั้งหมดที่เชื่อมโยงกับงานนั้นได้โดย เรียกใช้เมธอด finishAndRemoveTask()

@Composable
fun RemoveTaskButton() {
    val context = LocalContext.current
    Button(
        onClick = {
            // It is good practice to remove a document from the overview stack if not needed anymore.
            (context as? Activity)?.finishAndRemoveTask()
        }
    ) {
        Text("Remove from Recents")
    }
}

เก็บงานที่เสร็จแล้วไว้

หากต้องการเก็บงานไว้ในหน้าจอ "ล่าสุด" แม้ว่ากิจกรรมของงานจะเสร็จสิ้นแล้ว ให้ส่งแฟล็ก FLAG_ACTIVITY_RETAIN_IN_RECENTS ในเมธอด addFlags() ของ Intent ที่เปิดกิจกรรม

private fun newDocumentIntent() =
        Intent(this, NewDocumentActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
                    android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)
            putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, getAndIncrement())
        }

หากต้องการให้ได้เอฟเฟกต์เดียวกัน ให้ตั้งค่าแอตทริบิวต์ <activity> android:autoRemoveFromRecents เป็น false ค่าเริ่มต้นคือ true สำหรับกิจกรรมในเอกสาร และ false สำหรับ กิจกรรมปกติ การใช้แอตทริบิวต์นี้จะลบล้างแฟล็ก FLAG_ACTIVITY_RETAIN_IN_RECENTS

เปิดใช้การแชร์ URL ที่ดูล่าสุด (Pixel เท่านั้น)

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

หน้าจอ "ล่าสุด" พร้อมลิงก์สำหรับแชร์ เนื้อหาเว็บที่ดูเมื่อเร็วๆ นี้

แอปใดก็ได้เปิดใช้การลิงก์รายการล่าสุดสำหรับผู้ใช้ได้โดยการระบุ UI บนเว็บและ การลบล้าง onProvideAssistContent() ตามที่แสดงในตัวอย่างต่อไปนี้

class MainActivity : ComponentActivity() {

    // Track the current URL as state so the UI can update it during navigation
    private var currentWebUri by mutableStateOf("https://example.com/home")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            AppTheme {
                // Pass a lambda to your Compose UI so it can update the URL state
                // as the user navigates through your app.
                MainScreen(
                    onPageChanged = { newUrl -> currentWebUri = newUrl }
                )
            }
        }
    }

    override fun onProvideAssistContent(outContent: AssistContent) {
        super.onProvideAssistContent(outContent)

        // The system calls this when the user enters the Recents screen.
        // Provide the active URI tracked by the Compose state.
        outContent.webUri = Uri.parse(currentWebUri)
    }
}