การใช้งาน AppBar

แถบแอปด้านบน ให้ตำแหน่งที่สอดคล้องกันที่ด้านบนของหน้าต่างแอปสำหรับแสดง ข้อมูลและการดำเนินการต่างๆ จากหน้าจอปัจจุบัน

วันที่ ตัวอย่างแถบแอปด้านบน
รูปที่ 1 ตัวอย่างแถบแอปด้านบน

การเป็นเจ้าของแถบแอปจะแตกต่างกันไปตามความต้องการของแอป วันและเวลา โดยใช้ Fragment แถบแอปสามารถใช้เป็น ActionBar ที่เป็นเจ้าของ ข้างกิจกรรมของโฮสต์หรือแถบเครื่องมือภายในเลย์เอาต์ของแฟรกเมนต์

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

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

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

ตัวอย่างในหัวข้อนี้อ้างอิง ExampleFragment ที่มี โปรไฟล์ที่แก้ไขได้ ส่วนย่อยขยายความต่อไปนี้ เมนูที่กำหนด XML ในแถบแอป

<!-- sample_menu.xml -->
<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_settings"
        android:icon="@drawable/ic_settings"
        android:title="@string/settings"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/action_done"
        android:icon="@drawable/ic_done"
        android:title="@string/done"
        app:showAsAction="ifRoom|withText"/>

</menu>

เมนูประกอบด้วย 2 ตัวเลือก โดยตัวเลือกหนึ่งไปยังหน้าจอโปรไฟล์ และอีก 1 โปรไฟล์เพื่อบันทึกการเปลี่ยนแปลงโปรไฟล์ที่ทำ

แถบแอปที่เป็นเจ้าของกิจกรรม

กิจกรรมโฮสต์มักเป็นเจ้าของแถบแอปมากที่สุด เมื่อแอป แถบมีเจ้าของของกิจกรรม ส่วนย่อยสามารถโต้ตอบกับแถบแอปได้ โดยลบล้างเมธอดของเฟรมเวิร์กที่ถูกเรียกใช้ในระหว่างการสร้างส่วนย่อย

ลงทะเบียนพร้อมกิจกรรม

คุณต้องแจ้งให้ระบบทราบว่าส่วนย่อยของแถบแอปเข้าร่วมอยู่ ในการป้อนข้อมูลเมนูตัวเลือก โดยโทร setHasOptionsMenu(true) ในเมธอด onCreate(Bundle) ของส่วนย่อย ดังที่แสดงใน ตัวอย่าง:

Kotlin

class ExampleFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }
}

Java

public class ExampleFragment extends Fragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }
}

setHasOptionsMenu(true) จะบอกระบบว่าแฟรกเมนต์ของคุณ ต้องการรับ Callback ที่เกี่ยวข้องกับเมนู เมื่อรายการเกี่ยวกับเมนู เกิดขึ้น เช่น การคลิก วิธีการจัดการเหตุการณ์คือ เรียกกิจกรรมครั้งแรกก่อนที่จะถูกเรียกในส่วนย่อย

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

ขยายเมนูให้สูงเกินจริง

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

Kotlin

class ExampleFragment : Fragment() {
    ...
    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.sample_menu, menu)
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
       inflater.inflate(R.menu.sample_menu, menu);
    }
}

รูปที่ 2 แสดงเมนูที่อัปเดตแล้ว

วันที่ ตอนนี้เมนูตัวเลือกมีส่วนย่อยเมนูแล้ว
รูปที่ 2 ตอนนี้เมนูตัวเลือกมีเมนูของคุณ ส่วนย่อย

จัดการกิจกรรมการคลิก

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

ในการใช้งาน onOptionsItemSelected() ให้ใช้ switch ใน itemId ของรายการในเมนู หากรายการที่เลือก เป็นของคุณ โปรดจัดการการแตะให้เหมาะสม แล้วแสดงผล true เพื่อระบุว่า ที่มีการจัดการกิจกรรมการคลิก หากรายการที่เลือก โทรหาการติดตั้งใช้งาน super โดยค่าเริ่มต้น super การติดตั้งใช้งานจะส่งคืน false เพื่อให้ประมวลผลเมนูต่อไปได้

Kotlin

class ExampleFragment : Fragment() {
    ...
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.action_settings -> {
                // Navigate to settings screen.
                true
            }
            R.id.action_done -> {
                // Save profile changes.
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_settings:  {
                // Navigate to settings screen.
                return true;
            }
            case R.id.action_done: {
                // Save profile changes.
                return true;
            }
            default:
                return super.onOptionsItemSelected(item);
        }

    }

}

แก้ไขเมนูแบบไดนามิก

วางตรรกะเพื่อซ่อนหรือแสดงปุ่มหรือเปลี่ยนไอคอน onPrepareOptionsMenu() ระบบจะเรียกใช้เมธอดนี้ก่อนที่เมนูจะแสดง

และจากตัวอย่างก่อนหน้านี้ ปุ่มบันทึกควรจะ ไม่ปรากฏจนกว่าผู้ใช้จะเริ่มแก้ไข และควรหายไปหลังจาก ที่ผู้ใช้บันทึก การเพิ่มตรรกะนี้ลงใน onPrepareOptionsMenu() จะทำให้ เมนูปรากฏอย่างถูกต้อง:

Kotlin

class ExampleFragment : Fragment() {
    ...
    override fun onPrepareOptionsMenu(menu: Menu){
        super.onPrepareOptionsMenu(menu)
        val item = menu.findItem(R.id.action_done)
        item.isVisible = isEditing
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    @Override
    public void onPrepareOptionsMenu(@NonNull Menu menu) {
        super.onPrepareOptionsMenu(menu);
        MenuItem item = menu.findItem(R.id.action_done);
        item.setVisible(isEditing);
    }
}

เมื่อคุณจำเป็นต้องอัปเดตเมนู เช่น เมื่อผู้ใช้กด ปุ่มแก้ไขเพื่อแก้ไขข้อมูลโปรไฟล์ โทร invalidateOptionsMenu() ในกิจกรรมโฮสต์เพื่อขอให้ระบบเรียกใช้ onCreateOptionsMenu() หลังจากการทำให้เป็นโมฆะแล้ว คุณสามารถดำเนินการอัปเดตได้ใน onCreateOptionsMenu() ครั้งเดียว เมนูขยายออก ระบบจะเรียก onPrepareOptionsMenu() และอัปเดต เมนูเพื่อแสดงสถานะปัจจุบันของส่วนย่อย

Kotlin

class ExampleFragment : Fragment() {
    ...
    fun updateOptionsMenu() {
        isEditing = !isEditing
        requireActivity().invalidateOptionsMenu()
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    public void updateOptionsMenu() {
        isEditing = !isEditing;
        requireActivity().invalidateOptionsMenu();
    }
}

แถบแอปที่เป็นของ Fragment

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

<androidx.appcompat.widget.Toolbar
    android:id="@+id/myToolbar"
    ... />

เมื่อใช้แถบแอปที่เป็นส่วนย่อย Google แนะนำให้ใช้ Toolbar API โดยตรง อย่าใช้ setSupportActionBar() และ API เมนู Fragment ซึ่งเหมาะสำหรับแถบแอปที่เป็นเจ้าของกิจกรรมเท่านั้น

ขยายเมนูให้สูงเกินจริง

วิธีการสะดวกของ Toolbar inflateMenu(int) ใช้รหัสของ แหล่งข้อมูลเมนูเป็นพารามิเตอร์ วิธีเพิ่มทรัพยากรเมนู XML ลงใน ในแถบเครื่องมือ แล้วส่ง resId ไปยังเมธอดนี้ ดังที่แสดงดังต่อไปนี้ ตัวอย่าง:

Kotlin

class ExampleFragment : Fragment() {
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...
        viewBinding.myToolbar.inflateMenu(R.menu.sample_menu)
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ...
        viewBinding.myToolbar.inflateMenu(R.menu.sample_menu);
    }

}

หากต้องการเพิ่มทรัพยากรเมนู XML อื่นให้สูงเกินจริง ให้เรียกใช้เมธอดอีกครั้งด้วยเมธอด resId ของเมนูใหม่ ระบบจะเพิ่มรายการเมนูใหม่ลงในเมนู และ ระบบจะไม่แก้ไขหรือนำรายการในเมนูที่มีอยู่ออก

ถ้าคุณต้องการแทนที่ชุดเมนูที่มีอยู่ ให้ล้างเมนูก่อน กำลังเรียก inflateMenu(int) ด้วยรหัสเมนูใหม่ ดังที่ปรากฏใน ตัวอย่าง:

Kotlin

class ExampleFragment : Fragment() {
    ...
    fun clearToolbarMenu() {
        viewBinding.myToolbar.menu.clear()
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    public void clearToolbarMenu() {

        viewBinding.myToolbar.getMenu().clear()

    }

}

จัดการกิจกรรมการคลิก

คุณสามารถส่งผ่าน OnMenuItemClickListener แถบเครื่องมือได้โดยตรงโดยใช้ setOnMenuItemClickListener() ระบบจะเรียกใช้ Listener นี้เมื่อผู้ใช้เลือกรายการเมนู จากปุ่มดำเนินการที่แสดงอยู่ท้ายแถบเครื่องมือหรือ รายการเพิ่มเติมที่เกี่ยวข้อง รายการที่เลือก MenuItem จะส่งไปยังไฟล์ของผู้ฟัง onMenuItemClick() และสามารถใช้เพื่อดำเนินการ ดังที่ปรากฏใน ตัวอย่าง:

Kotlin

class ExampleFragment : Fragment() {
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...
        viewBinding.myToolbar.setOnMenuItemClickListener {
            when (it.itemId) {
                R.id.action_settings -> {
                    // Navigate to settings screen.
                    true
                }
                R.id.action_done -> {
                    // Save profile changes.
                    true
                }
                else -> false
            }
        }
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ...
        viewBinding.myToolbar.setOnMenuItemClickListener(item -> {
            switch (item.getItemId()) {
                case R.id.action_settings:
                    // Navigate to settings screen.
                    return true;
                case R.id.action_done:
                    // Save profile changes.
                    return true;
                default:
                    return false;
            }
        });
    }
}

แก้ไขเมนูแบบไดนามิก

เมื่อส่วนย่อยของคุณเป็นเจ้าของแถบแอป คุณจะแก้ไข Toolbar ได้ที่ เหมือนมุมมองอื่นๆ ทุกประการ

และจากตัวอย่างก่อนหน้านี้ ตัวเลือกเมนูบันทึกควรมีลักษณะดังนี้ ไม่ปรากฏจนกว่าผู้ใช้จะเริ่มแก้ไข และหน้าควรหายไป อีกครั้งเมื่อแตะ:

Kotlin

class ExampleFragment : Fragment() {
    ...
    fun updateToolbar() {
        isEditing = !isEditing

        val saveItem = viewBinding.myToolbar.menu.findItem(R.id.action_done)
        saveItem.isVisible = isEditing

    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    public void updateToolbar() {
        isEditing = !isEditing;

        MenuItem saveItem = viewBinding.myToolbar.getMenu().findItem(R.id.action_done);
        saveItem.setVisible(isEditing);
    }

}

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

Kotlin

class ExampleFragment : Fragment() {
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...
        myToolbar.setNavigationIcon(R.drawable.ic_back)

        myToolbar.setNavigationOnClickListener { view ->
            // Navigate somewhere.
        }
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ...
        viewBinding.myToolbar.setNavigationIcon(R.drawable.ic_back);
        viewBinding.myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Navigate somewhere.
            }
        });
    }
}