استخدام AppBar

يوفّر شريط التطبيق العلوي مكانًا متسقًا على طول الجزء العلوي من نافذة التطبيق لعرض المعلومات والإجراءات من الشاشة الحالية.

مثال على شريط التطبيق العلوي
الشكل 1. مثال على شريط التطبيق العلوي.

تختلف ملكية شريط التطبيق حسب احتياجات تطبيقك. وعند استخدام الأجزاء، يمكن تنفيذ شريط التطبيق على شكل 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>

تحتوي القائمة على خيارين: أحدهما للانتقال إلى شاشة الملف الشخصي والآخر لحفظ أي تغييرات تم إجراؤها على الملف الشخصي.

شريط التطبيق الذي يملكه النشاط

غالبًا ما يكون شريط التطبيق مملوكًا لنشاط المضيف. عندما يكون شريط التطبيق مملوكًا لنشاط ما، يمكن أن تتفاعل الأجزاء مع شريط التطبيق عن طريق تجاوز أساليب إطار العمل التي يتم استدعاؤها أثناء إنشاء الأجزاء.

التسجيل باستخدام النشاط

يجب إبلاغ النظام بأن جزء شريط التطبيق يشارك في عدد الأشخاص في قائمة الخيارات. للقيام بذلك، استدعِ 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) النظام أنّ الجزء الخاص بك يريد تلقّي استدعاءات متعلّقة بالقائمة. عند وقوع حدث متعلّق بالقائمة، مثل نقرة، يتم استدعاء طريقة معالجة الأحداث أولاً إلى النشاط قبل استدعائه إلى الجزء.

ومع ذلك، لا تعتمد على هذا الترتيب في منطق التطبيق. إذا كان النشاط نفسه يستضيف أجزاءً متعددة، يمكن لكل جزء توفير خيارات القائمة، وفي هذه الحالة يعتمد ترتيب معاودة الاتصال على الترتيب الذي تتم إضافة الأجزاء به.

تضخيم القائمة

لدمج قائمتك في قائمة خيارات شريط التطبيق، يمكنك إلغاء 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()، لن تتلقى أي أجزاء مشارِكة أخرى معاودة الاتصال.

في تنفيذك لـ 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();
    }
}

شريط التطبيق المملوك للأجزاء

إذا كانت معظم الشاشات في تطبيقك لا تحتاج إلى شريط تطبيقات أو إذا كانت إحدى الشاشات تحتاج إلى شريط تطبيق مختلف عن الشاشات الأخرى، يمكنك إضافة Toolbar إلى تنسيق الأجزاء. يمكنك إضافة Toolbar في أيّ مكان ضمن التدرّج الهرمي لطريقة عرض الجزء، إلا أنّك تحتفظ به بشكل عام في أعلى الشاشة. لاستخدام Toolbar في الجزء الخاص بك، قدِّم معرّفًا واحصل على إشارة إليه في الجزء الخاص بك، كما هو الحال مع أي طريقة عرض أخرى. يمكنك أيضًا تجربة تحريك شريط الأدوات باستخدام سلوكيات CoordinatorLayout.

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

عند استخدام شريط تطبيق مملوك لأجزاء، تنصح Google باستخدام واجهات برمجة تطبيقات Toolbar مباشرةً. عدم استخدام setSupportActionBar() وواجهات برمجة التطبيقات للقائمة 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(). يتم استدعاء هذا المستمع عندما يختار المستخدم عنصر قائمة من أزرار الإجراءات المعروضة في نهاية شريط الأدوات أو القائمة الكاملة المرتبطة. يتم تمرير 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.
            }
        });
    }
}