Что-то пауза с постами у нас получается совсем нечеловеческая. Попробуем еще разок возобновить публикации.
И сегодня мы познакомимся с библиотекой, реализующей UI-паттерн Action Bar для Android-приложений.

Разработчики библиотеки позиционируют ее как расширение к Compatibility Library, которое для создания ActionBar использует нативную реализацию, если это поддерживается системой, или же вручную дублирует нужный функционал.

Библиотека является open-source проектом и доступна для загрузки на GitHub.

Начало

Начать пользоваться библиотекой довольно просто. Нужно сделать вот что:

  • Унаследовать активити от SherlockActivity (или SherlockListActivity)
  • Переопределить метод onCreateOptionsMenu() и в нем заполнить объект Menu информацией о кнопках
  • В onCreate() или в манифесте указать что используется тема Theme_Sherlock

В итоге код получится приблизительно таким:

package ru.mobiledeveloper.actionbarsherlocktest;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

import android.os.Bundle;
import ru.mobiledeveloper.actionbarsherlocktest.R;

public class ActionBarSherlockTestActivity extends SherlockActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    	setTheme(R.style.Theme_Sherlock);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add("Save")
            .setIcon(R.drawable.ic_compose)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

        menu.add("Search")
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | 
                MenuItem.SHOW_AS_ACTION_WITH_TEXT);

        return true;
    }
}

В результате получим такой внешний вид окна приложения:

Режим действия

ActionBar Sherlock поддерживает возможность отображения контекстно-зависимого содержания. Такая возможность называется режим действий (ActionMode). режим действий можно использовать, например, для отображения контекстного “меню” при длинном нажатии на єлемент списка.
Для того, чтобі добавить возможность отображать режим действий в приложение, нужно сделать следующее:

  • Создать класс, производный от ActionMode.Callback
  • Реализовать в этом классе метод onCreateActionMode(), в котором добавить нужные команды.
  • Реализовать в этом классе метод onActionItemClicked(), в котором написать код, обрабатывающий нажатия на кнопки в ActionBar
  • Для перехода в режим действий вызвать метод startActionMode() и в качестве параметра передать ему объект выше указанного класса

В коде это выглядит приблизительно так:

public class ActionBarSherlockTestActivity extends SherlockActivity {
	
	ActionMode mMode;
	
	private final class ActionModeA implements ActionMode.Callback {

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            menu.add("Save")
                .setIcon(R.drawable.ic_compose)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            menu.add("Search")
                .setIcon(R.drawable.ic_search)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            return true;
        }

		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
			// TODO Auto-generated method stub
			return false;
		}

		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
			Toast.makeText(ActionBarSherlockTestActivity.this, 
                            "Got click: " + item, Toast.LENGTH_SHORT).show();
            mode.finish();
			return true;
		}

		public void onDestroyActionMode(ActionMode mode) {
			// TODO Auto-generated method stub
			
		}
        
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
    	setTheme(R.style.Theme_Sherlock);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button btnTest = (Button)findViewById(R.id.btnTest);
        if(btnTest != null) {
        	btnTest.setOnClickListener(new OnClickListener() {
				
				public void onClick(View v) {
					mMode = startActionMode(new ActionModeA());
				}
			});
        }
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add("Save")
            .setIcon(R.drawable.ic_compose)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

        menu.add("Search")
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | 
                MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        return true;
    }
}

И в результате получаем такое:

Существует, также, возможность отображать ActionBar только в режиме Action Mode и скрывать ее в остальное время работы приложения. Для этого в onCreate() надо вызвать requestWindowFeature(Window.FEATURE_NO_TITLE).

Провайдеры действий

ActionBar Sherlock поддерживает работу с провайдерами действий (Action Provider), которые позволяют реализовать отображение собственных виджетов в ActionBar и добавить более гибкое взаимодействие с пользователем. Action Provier можно повторно использовать в нескольких активитях.
Есть две возможности указать Action Provider для элемента – прописать его в XML файле для пункта меню или указать в коде с помощью setActionProvider().
Рассмотрим реализацию Action Provider’а, который по нажатию на кнопку в ActionBar открывает системные настройки:

public static class SettingsActionProvider extends ActionProvider {
	private static final Intent sSettingsIntent = new Intent(Settings.ACTION_SETTINGS);

	private final Context mContext;

    public SettingsActionProvider(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public View onCreateActionView() {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        View view = layoutInflater.inflate(R.layout.settings_action_provider, null);
        ImageButton button = (ImageButton) view.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                mContext.startActivity(sSettingsIntent);
            }
        });
        return view;
    }

    @Override
    public boolean onPerformDefaultAction() {
        mContext.startActivity(sSettingsIntent);
        return true;
    }
}
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Этот элемент будет отображен в ActionBar
    menu.add("Settings")
        .setActionProvider(new SettingsActionProvider(
        		ActionBarSherlockTestActivity.this))
        .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | 
        		MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        
    // Этот элемент будет отображен в стандартном меню
    menu.add("Settings")
        .setActionProvider(new SettingsActionProvider(
        		ActionBarSherlockTestActivity.this))
        .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    return true;
}

XML-файл для кнопки:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:focusable="true"
    android:addStatesFromChildren="true"
    android:background="?attr/actionBarItemBackground"
    style="?attr/actionButtonStyle">
    <ImageButton android:id="@+id/button"
        android:background="@drawable/ic_launcher_settings"
        android:layout_width="32dip"
        android:layout_height="32dip"
        android:layout_gravity="center"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true" />
</LinearLayout>

После создания провайдера действий и добавления его к пунктам меню получим такое:

Collapsible Actions

Есть возможность, при нажатии на пункт меню, отображать собственный контрол на всю ширину ActionBar. Например, для поиска можно отображать текстовое поле. Сделать это можно, указав дайаут с помощью setActionView() и стиль MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW.

public boolean onCreateOptionsMenu(Menu menu) {
    boolean isLight = SampleList.THEME == R.style.Theme_Sherlock_Light;
    menu.add("Search")
        .setIcon(isLight ? R.drawable.ic_search_inverse : R.drawable.ic_search)
        .setActionView(R.layout.collapsible_edittext)
        .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | 
                MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
    return true;
}

При нажатии на пункт в ActionBar будет отображен контрол из XML файла collapsible_edittext.xml.

Полезные функции

Индикатор прогресса
Есть возможность отобразить индикатор прогресса в ActionBar. Такая возможность может быть полезна для отображения прогресса длительной операции. Сделать это можно с помощью метода setSupportProgressBarIndeterminateVisibility().
Оверлей
Можно отображать ActionBar поверх контента при скроллинге. Очень полезная возможность, например, при просмотре текстов. Перевести ActinBar в режим оверлея можно с помощью метода requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY).

Различные типы активитей

В ActionBar Sherlock помимо обычной активити есть классы для отображения активитей со списками, активитей настройки, диалогов.
SherlockPreferenceActivity
Этот класс используется для отображения окон настройки. Функционал аналогичен PreferenceActivity из Android SDK.

SherlockListActivity и SherlockExpandableListActivity
Это активити, производные от ListActivity и ExpandableListActivity соответственно, в которую добавлен функционал по работе с ActionBar.
Диалоги
Есть возможность отображать активити в виде диалогов. Для этого надо указать соответствующую тему в манифесте (необходимо указывать тему именно в манифесте).

<activity
    android:name=".Dialog"
    android:label="@string/dialog"
    android:theme="@style/Theme.Sherlock.Dialog">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="com.actionbarsherlock.sample.demos.EXAMPLE" />
    </intent-filter>
</activity>

На вид выглядит так:

Пара слов о навигации

В ActionBar Sherlock есть возможность организовать навигацию внутри приложения средствами ActionBar. Визуально получается очень приятный результат, например можно реализовать навигацию посредством выпадающего списка или вкладками или еще каким-либо способом, встроив контрол для навигации в ActionBar.

Более подробно реализацию навигации рассмотрим в следующей части статьи.

Previous ArticleNext Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

Leave a Reply

Your email address will not be published. Required fields are marked *

О.

Обучающие материалы по Windows Mobile (Windows Mobile RampUp Track) доступны на MSDN

На MSDN доступен курс по разработке для Windows Mobile. Материал состоит из 7ми модулей, каждый из которых содержит лекции и медиа-материалы по разработке мобильных приложений. После прохождения курса можно получить что-то вроде серитификата. У них это называется “Graduation Award”.

О.

О сверхдешевых ноутбуках и о том как не надо делать бизнес – Часть II

Ага, а вот и продолжение истории о ноутбуках “для всех”. Первую часть можно почитать здесь.

Итак, покупка. Как это было? Было это мм.. довольно странно. Договаривался я с братьсями-китайцами две недели, письма писать они умеют, пишут вежливо: “Dear Sir, …” и все такое. В общем-то две недели общения посредством e-mail даром не прошли, информации я узнал об устройствах достаточно и это только укрепило мое желание сделать покупку. Сказали стоимость доставки: $224 если отправлять с помощью EMS (Express Mail Service). Почему именно EMS? Потому что они доставляют посылки каким-то чудесным образом и за них не надо платить таможенный сбор, который у нас может составоять до 30% от стоимости посылки. Именно из-за таможенных сборов мне пришлось отказаться от отправки с помощью DHL, хотя, конечно, я им как-то больше верю, сколько раз с ними работал, всегда все получалось, а FedEx не рассматривался по той причине что качество предоставляемых услуг у них ээ.. как бы это сказать, ниже плинтуса.

Да, в общем сошлись на EMS. Посчитаю-ка я общую стоимость, что у нас получается $162 * 5 + 224 итого $1034. Это получается почти по $207 за устройство. Фигасе!, – подумал я, а как же ж “для всех”? А как же ж “сверхдешевый да еще и на Linux’е”? Это ж 2/3 стоимости EEE PC! Но делать нечего, “Двадцать тыщ уже уплочено” (с) Масяня.

Прислали инвойс. Перевод сделал ПриватБанком. На удивление довольно шустро все произошло, за 40 минут мне открыли лицевой счет (по-моему 30 гривен это стоило, около $6) и $12 взяли за перевод международный. Я даже удивился, в ПриватБанке обычно все ооочень медленно, а тут вот так получилось шустро. Хоть что-то приятное. Итого $1034 + 6 + 12 получается $1052. Это по $210 за штучку. М-да.. почти в два раза стоимость увеличилась от заявленной.

Итак, денежка ушла в Китай. В тот же день отправил братьям-китайцам скан квитанции об оплате и получил от них “большое спасибо, технологические образцы будут готовы в течении 2х недель”.

Ну OK, две так две, можно и подождать, до нового года еще далеко 🙂

Прошло две недели, отписываю им, мол “как там дела с железками”, на что получаю, что-то типа “мы тут как бы пытаемся выпустить новую версию устройства со встроенным Wi-FI модулем, давайте мы вам новые пришлем образцы, но чуть позже”. Слово “Фигасе!” почему-то оять посетило мою голову, при чем тут встроенный вайфай? Я ж проплатил внешний. Ну, говорю, смотрите, я вам за внешний заплатил, дайте мне чего я хочу, просто вышлите и все. В ответ тишина…

Прошла неделя, опять им пишу, мол чего там с железом-то? Я тут заждался уже! На что получаю ответ “ну вот мы тут еще и экранчик улучшили, стало больше цветов и разрешение улучшилось и там еще помните, встроенный вайфай… но этот время, мы это все готовим… но если чего, можем вернуть вам деньги”. Ооо, отлично, экранчик.. но как же $60 за внешние вайфай модули? В общем, решил подождать, обещали разрешение 800х480 (оказывается раньше было меньше!).

Подождал до начал аоктября, опять тишина. Отписываю, мол, ну как там? Уже сделали? Опять тишина. Но я настойчивый, каждые три дня писал им письма 🙂 Наконец-то вот три дня назад получил ответ что мы отправили DHL’ом. Трекинг намбер бла-бла-бла.

Оооо! Отправили! Но DHL! Это получается что за все это добро мне прийдется платить таможенный сбор! Ну ёкарныбабай, мы же договаривались! С таким раскладом мне эти устройства выйдут по стоимости как EEE PC! Решил было успокоиться, но не ту-то было. На сайте DHL указанный tracking number оказался невалидным. Для пущей уверенности пошел проверить на сайте EMS, может в письме ошиблись с названием компании-курьера… Попробовал, то же самое, невалидный номер.

Сегодня отписал им по этому поводу, жду ответа, нервничаю…

Продолжение этой истории напишу как появятся новые сведения.

ЗЫ: У кого-нибудь еще есть опыт покупки оборудования в Китае? Как это было?