کار کردن با AppBar

نوار برنامه بالا مکان ثابتی را در بالای پنجره برنامه برای نمایش اطلاعات و کنش‌های صفحه فعلی فراهم می‌کند.

نمونه نوار برنامه بالا
شکل ۱. نمونه‌ای از نوار برنامه بالا.

مالکیت نوار برنامه بسته به نیازهای برنامه‌تان متفاوت است. هنگام استفاده از قطعه‌ها، نوار برنامه می‌تواند به‌عنوان یک 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) قطعه‌تان فراخوانی کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

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

‫setHasOptionsMenu(true) به سیستم می‌گوید که قطعه شما می‌خواهد تماس‌های برگشتی مربوط به منو را دریافت کند. وقتی رویداد مرتبط با منو، مثل کلیک، اتفاق می‌افتد، روش مدیریت رویداد ابتدا در فعالیت فراخوانی می‌شود و سپس در قطعه فراخوانی می‌شود.

بااین‌حال، در منطق برنامه‌تان به این ترتیب تکیه نکنید. اگر یک فعالیت میزبان چند قطعه باشد، هر قطعه می‌تواند گزینه‌های منو را ارائه دهد، که در این صورت ترتیب فراخوانی به ترتیبی که قطعات اضافه می‌شوند بستگی دارد.

منو را باز کنید

برای ادغام منو در منوِ گزینه‌های نوار برنامه، onCreateOptionsMenu() را در قطعه‌تان لغو کنید. این روش منو نوار برنامه فعلی و یک MenuInflater را به‌عنوان پارامتر دریافت می‌کند. از منو inflater برای ایجاد نمونه‌ای از منو قطعه‌تان استفاده کنید، و سپس آن را در منو فعلی ادغام کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

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

شکل ۲ منو به‌روزشده را نشان می‌دهد.

منو گزینه‌ها اکنون حاوی قطعه منو شما است
شکل ۲. اکنون منوِ گزینه‌ها حاوی قطعه منو شما است.

مدیریت رویدادهای کلیک

هر فعالیت و قطعه‌ای که در منوِ گزینه‌ها شرکت می‌کند می‌تواند به لمس‌ها پاسخ دهد. onOptionsItemSelected() قطعه، گزینه منو انتخاب‌شده را به‌عنوان پارامتر دریافت می‌کند و یک بولی برمی‌گرداند تا نشان دهد آیا لمس مصرف شده است یا نه. وقتی فعالیت یا قطعه‌ای true را از onOptionsItemSelected() برمی‌گرداند، هیچ قطعه شرکت‌کننده دیگری فراخوان را دریافت نمی‌کند.

در پیاده‌سازی onOptionsItemSelected()، از عبارت switch در itemId گزینه منو استفاده کنید. اگر مورد انتخاب‌شده متعلق به شما است، لمس را به‌درستی مدیریت کنید و true را برگردانید تا نشان دهید که رویداد کلیک مدیریت شده است. اگر مورد انتخاب‌شده متعلق به شما نیست، پیاده‌سازی super را فراخوانی کنید. به‌طور پیش‌فرض، پیاده‌سازی super false را برمی‌گرداند تا پردازش منو ادامه یابد.

کاتلین

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)
        }
    }
}

جاوا

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() باعث می‌شود منو به‌درستی ارائه شود:

کاتلین

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

جاوا

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() را فراخوانی می‌کند و منو را به‌روز می‌کند تا وضعیت فعلی قطعه را منعکس کند.

کاتلین

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

جاوا

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 API استفاده کنید. از setSupportActionBar() و میاناهای برنامه‌سازی کاربردی منو Fragment که فقط برای نوارهای برنامه متعلق به فعالیت مناسب هستند استفاده نکنید.

منو را باز کنید

Toolbar روش راحتی inflateMenu(int) شناسه منبع منو را به‌عنوان پارامتر می‌گیرد. برای گسترش منبع منو XML در نوارابزار، resId را به این روش ارسال کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

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) با شناسه منو جدید، منو را پاک کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

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

        viewBinding.myToolbar.getMenu().clear()

    }

}

مدیریت رویدادهای کلیک

می‌توانید OnMenuItemClickListener را مستقیماً بااستفاده از روش setOnMenuItemClickListener() به نوارابزار ارسال کنید. وقتی کاربر گزینه منویی را از دکمه‌های کنش ارائه‌شده در انتهای نوارابزار یا سرریز مرتبط انتخاب می‌کند، این شنونده فراخوانده می‌شود. MenuItem انتخاب‌شده به روش onMenuItemClick() شنونده ارسال می‌شود و می‌توان از آن برای مصرف کنش استفاده کرد، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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
            }
        }
    }
}

جاوا

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 را در زمان اجرا دقیقاً مانند هر نمای دیگری تغییر دهید.

با ادامه مثال قبلی، گزینه منو ذخیره باید تا زمانی که کاربر شروع به ویرایش نکرده است نامرئی باشد و وقتی روی آن تک‌ضرب زده می‌شود دوباره ناپدید شود:

کاتلین

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

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

    }
}

جاوا

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

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

}

اگر وجود داشته باشد، دکمه پیمایش در ابتدای نوارابزار نشان داده می‌شود. تنظیم نماد پیمایش در نوارابزار باعث می‌شود قابل‌مشاهده شود. همچنین می‌توانید onClickListener() مختص پیمایش تنظیم کنید که هروقت کاربر روی دکمه پیمایش کلیک می‌کند فراخوانده شود، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

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

جاوا

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.
            }
        });
    }
}