Повторное использование кода меню опций

#android #android-optionsmenu

#Android #android-optionsmenu

Вопрос:

Существует ли удобный способ отображения одних и тех же параметров меню опций в нескольких действиях?

Пример: В моем приложении я показываю телегид одним из трех способов.

  1. Семидневное руководство (TabActivity с 7 вкладками)
  2. Все каналы «Теперь отображаются» (ListActivity)
  3. Все отображается сегодня по времени начала (Activity — можно легко изменить на ListActivity)

Для меню опций в TabActivity код довольно прост…

 @Override
public boolean onPrepareOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    menu.clear();
    inflater.inflate(R.menu.gv_options_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.view:
        ...
    ...
    }
}
  

…но на данный момент кажется, что мне нужно скопировать / вставить его в два других действия, которые мне не нравятся. Если я изменю код меню опций для одного, мне нужно будет сделать это и для двух других.

Единственная альтернатива, о которой я могу подумать, — это у меня есть класс ‘helper’ (POJO), к которому я мог бы добавить метод и передать context в, чтобы разрешить использование getMenuInflator() метода, и другой метод, в который я мог бы передать результат item.getItemId() для обработки с помощью switch-case.

Каков обычный способ выполнения нескольких действий с одним и тем же меню опций?

Ответ №1:

Создайте простой отдельный класс с помощью этих двух методов:

 public class MyMenuHandler {

    private Activity mActivity;

    public MyMenuHandler(Activity activity) {
        mActivity = activity;
    }

    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuInflater inflater = mActivity.getMenuInflater();
        menu.clear();
        inflater.inflate(R.menu.gv_options_menu, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.view:
            ...
        }
    }
}
  

В ваших действиях переопределите эти методы обратного вызова и перенаправьте вызов на экземпляр вашего класса MyMenuHandler:

 public class MyActivity1 extends TabActivity {

    private MyMenuHandler mMenuHandler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mMenuHandler = new MyMenuHandler(this);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // you may also add here some items which are specific 
        // for one activity, not for the others
        ...
        return mMenuHandler.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // handle selection of your specific items here,
        // if none of them has been selected call mMenuHandler method
        ...
        return mMenuHandler.onOptionsItemSelected(item);
    }
}
  

Это позволит вам хранить в одном месте код, который отвечает за выбор ваших основных пунктов меню, поэтому вам не нужно будет беспокоиться о копировании-вставке его во все действия, которые должны иметь одно и то же меню.

Ответ №2:

Один из подходов заключается в использовании наследования в ваших действиях. Создайте базовое действие, которое реализует методы меню опций, и тогда каждое дочернее действие получит эту функциональность. Это рекомендуемый подход на сайте разработчика Android:

Совет: Если ваше приложение содержит несколько действий и некоторые из них предоставляют одно и то же меню опций, рассмотрите возможность создания действия, которое не реализует ничего, кроме методов onCreateOptionsMenu() и onOptionsItemSelected(). Затем расширьте этот класс для каждого действия, которое должно использовать одно и то же меню опций. Таким образом, вам придется управлять только одним набором кода для обработки действий меню, и каждый класс-потомок наследует поведение меню.

К сожалению, это не сработает для вас, поскольку вы наследуете не от самого Activity, а от разных его подклассов, но это «обычный» способ сделать это.

Комментарии:

1. Как оказалось, я забыл, что содержимое вкладки действия «Руководство по 7 дням» на самом деле является ListActivity — я изменил действие «все шоу сегодня …» (№ 3 в моем вопросе) на также ListActivity и определил базовый класс, который теперь расширяют все три. Один из тех моментов, когда невозможно увидеть лес за деревьями. Спасибо.

Ответ №3:

Вы можете инкапсулировать свое меню действий в фрагмент. Таким образом, вам нужно только добавить фрагмент в меню onCreate вашей активности.

Вам нужно вызвать setHasOptionsMenu после создания фрагмента. Для добавления фрагмента add используйте тег вместо идентификатора макета.

Комментарии:

1. Привет. у вас есть какой-нибудь хороший пример (учебное пособие или любой другой пример) для этого? фрагмент для меня совершенно новый.

2. начните с этого developer.android.com/guide/topics/fundamentals/fragments.html

3. Обратите внимание, что это применимо, если вы используете API уровня 11 или выше

4. Или пакета совместимости от Google. Поскольку почти каждое приложение, поддерживающее 4.0 и 2.2, самые последние и широко используемые приложения Android будут использовать эту библиотеку, это не должно быть проблемой

5. Не знал об этом, спасибо. На всякий случай, если это кому-то понадобится: пакет поддержки Android