В июле 2013 года Google анонсировала ActionBarCompat как часть своего пакета поддержки библиотеки. Эта библиотека облегчает использование панели действий, которая должна поддерживать старые устройства. Многие ждали, что это произойдет с тех пор, как была представлена панель действий с Honeycomb.
Я, однако, не ожидал, что это произойдет. В конце концов, Action Bar был анонсирован давно, и у нас был ActionBarSherlock. Так почему же вдруг?
Я написал несколько сообщений о ActionBarSherlock в этом блоге до этого объявления. Эти посты по-прежнему привлекают много внимания и поисковых запросов. Но в то время как основные понятия все еще применяются, любые специфические части ActionBarSherloc устарели
Я твердо верю, что вы должны использовать ActionBarCompat для всех новых проектов, которые хотят поддерживать старые устройства. Также может иметь смысл перенести существующие проекты. Так что читайте дальше, чтобы узнать, почему вы должны мигрировать или использовать ActionBarCompat прямо сейчас, и как перенести существующие проекты.
Почему вы должны предпочитать ActionBarCompat вместо ActionBarSherlock
Есть много причин, почему вы должны предпочесть ActionbarCompat, а не ActionbarSherlock.
Прежде всего, этот проект от Google, является частью библиотеки поддержки и, таким образом, вероятно, будет поддерживать новые вещи, связанные с Action Bar, в то же время Google выпускает их со стандартным Android.
Еще одна веская причина и доказательство предыдущего пункта заключается в том, что ActionBarCompat поддерживает шаблон «Ящик навигации» прямо из коробки, а ActionBarSherlock — нет. Таким образом, если вы хотите добавить этот ящик в существующий проект / приложение, вы должны выполнить миграцию.
Последняя и не в последнюю очередь причина заключается в том, что создатель ActionBarSherlock Джейк Уортон объявил в Google+, что дальнейшее развитие ActionBarSherlock остановлено . ActionBarSherlock 4.4 является последним выпуском и может получить исправления ошибок, но новых функций не будет:
Несмотря на то, что в ближайшие недели может появиться один или несколько выпусков, версия 4.4 станет последней версией ™.
Он тоже не слишком огорчен. Смотрите эту цитату, которую Джейк Уортон написал в своем блоге о том, что ActionBarSherlock должен быть в конечном итоге отброшен :
Это вся цель библиотеки. Он был специально разработан для этого случая использования. Он устарел с самого начала с намерением, что когда-нибудь вы сможете его выбросить.
Пример проекта
Чтобы продемонстрировать, как работает миграция, я перенес пример ActionViews проекта в ActionBarCompat. В этом примере проекта показано, как использовать панель действий со старыми устройствами и, в качестве особого случая, как использовать ActionView в вашей панели действий. Вы можете найти больше информации о ActionViews в моем предыдущем посте. Первоначально написанный с учетом ActionBarSherlock, вы можете легко перенести эти примеры кода в ActionBarSherlock. В следующих разделах показано, как адаптировать фрагменты кода для перехода от ActionBarSherlock к ActionBarCompat.
Вы можете найти пример проекта ActionViews на bitbucket . Если вам нравится, вы можете увидеть все изменения, необходимые для миграции ActionBarCompat, просмотрев фиксацию .
Конечно, вы должны интегрировать ActionBarCompat в IDE по вашему выбору. Я не освещаю это здесь. Габриэле Мариотти написала отличную статью, рассказывающую об интеграции интегрированной среды разработки ActionBarCompat . Первоначально я разработал этот проект с использованием Eclipse — вот почему я иногда ссылаюсь на специальные ярлыки Eclipse или почему позже я включаю диалог Eclipse. Но суть этого поста не зависит от IDE, которую вы хотите использовать.
Как поступить
Поэтому я предполагаю, что вы удалили ActionBarSherlock из проекта ActionViews и вместо этого добавили ActionBarCompat. После этого ваш проект должен быть подвержен ошибкам. Что не слишком удивительно. В следующих разделах я проведу вас через все шаги, необходимые для повторного развертывания проекта.
Я начну с ресурсов и позже займусь изменениями кода. Инструменты разработки Android генерируют новый R.java
файл только тогда, когда ресурсы безошибочны. А без правильного R
файла ваши исходные коды Java не будут компилироваться должным образом. Поэтому я предпочитаю сначала исправить ресурсы.
Смена стиля
Первое, что нужно сделать, это исправить стиль. Я использовал стиль ActionBarSherlock ранее. Этот стиль должен измениться на правильный стиль ActionBarCompat. Как и в случае с ActionBarSherlock, вы должны использовать стиль ActionBarCompat , в противном случае вы получите RuntimeException при запуске приложения.
Измените стиль с именем, AppBaseTheme
чтобы использовать Theme.AppCompat.Light.DarkActionBar
его в качестве родителя:
<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar"> <!-- nothing API level dependent yet --> </style>
Поскольку вы можете забыть об этом шаге в будущих проектах — по крайней мере, я склонен изначально забывать этот шаг — вот исключение, которое вы увидите в logcat в этом случае. Увидев это здесь, вы можете вспомнить, что с этим делать.
E/AndroidRuntime( 1413): Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity. E/AndroidRuntime( 1413): at android.support.v7.app.ActionBarActivityDelegate.onCreate(ActionBarActivityDelegate.java:111) E/AndroidRuntime( 1413): at android.support.v7.app.ActionBarActivityDelegateICS.onCreate(ActionBarActivityDelegateICS.java:58) E/AndroidRuntime( 1413): at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:98) E/AndroidRuntime( 1413): at com.grokkingandroid.sampleapp.samples.actionbar.actionviews.BaseActivity.onCreate(BaseActivity.java:30)
Инструменты разработчика подсвечивают атрибут android:textIsSelectable
где-то в файле после его сохранения. Это связано с тем, что минимальный уровень API проекта — SDK 7, а атрибут введен только в SDK 11. Вы можете смело игнорировать это. Если вы очистите свой проект после еще нескольких исправлений, этот маркер исчезнет. У вас не будет проблем с более низкими версиями, несмотря на это.
Исправление определений меню
Следующим шагом является исправление файлов определений меню. Старые версии Android не знают о панели действий и, следовательно, не поддерживают эти новые атрибуты xml для панели действий. Таким образом , вы должны изменить все атрибуты с именем android:showAsAction
, android:actionViewClass
, android:actionProviderClass
, илиandroid:actionLayout
. Исправить легко. Просто измените пространство имен с android
на app
и добавьте это пространство имен.
Например, для файла menu_fragment_expandable.xml
новый XML выглядит так:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id= "@+id/actionViewLayout" app:actionLayout= "@layout/expandable_actionview_edittext" android:icon= "@drawable/ic_action_add_inverse" app:showAsAction= "ifRoom|collapseActionView" android:title= "@string/add_item"/> </menu>
Я делаю пространство имен известным парсеру в строке 3. Я использую это пространство имен для определенных атрибутов панели действий в строках 6 и 8. Таким образом, ActionBarCompat может читать эти атрибуты и обеспечивать правильный внешний вид пунктов меню.
Исправление Searchview для использования
Взгляните на файл menu_fragment_search.xml. Ни ваша IDE, ни Android Lint Checker не пометят этот файл как неправильный. Все же это так.
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id= "@+id/searchView" app:actionViewClass= "com.actionbarsherlock.widget.SearchView" android:icon= "@drawable/ic_action_search_inverse" app:showAsAction= "ifRoom|collapseActionView" android:title= "@string/search"/> </menu>
Очевидно, строка 7 больше не будет работать. Вместо Шерлока SearchView
вы должны использовать SearchView
библиотеку ActionBarCompat. Теперь вы должны использовать класс android.support.v7.widget.SearchView
. Обновленный файл должен выглядеть следующим образом:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id= "@+id/searchView" app:actionViewClass= "android.support.v7.widget.SearchView" android:icon= "@drawable/ic_action_search_inverse" app:showAsAction= "ifRoom|collapseActionView" android:title= "@string/search"/> </menu>
Если вы забудете об этом шаге в своем проекте, вы увидите исключение в logcat:
W/SupportMenuInflater( 1308): Cannot instantiate class: com.actionbarsherlock.widget.SearchView W/SupportMenuInflater( 1308): java.lang.ClassNotFoundException: Didn't find class "com.actionbarsherlock.widget.SearchView" on path: DexPathList[[zip file "/data/app/com.grokkingandroid.sampleapp.samples.actionbar.actionviews-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.grokkingandroid.sampleapp.samples.actionbar.actionviews-2, /system/lib]] W/SupportMenuInflater( 1308): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) W/SupportMenuInflater( 1308): at java.lang.ClassLoader.loadClass(ClassLoader.java:497) W/SupportMenuInflater( 1308): at java.lang.ClassLoader.loadClass(ClassLoader.java:457) W/SupportMenuInflater( 1308): at android.support.v7.internal.view.SupportMenuInflater$MenuState.newInstance(SupportMenuInflater.java:480) W/SupportMenuInflater( 1308): at android.support.v7.internal.view.SupportMenuInflater$MenuState.setItem(SupportMenuInflater.java:441) W/SupportMenuInflater( 1308): at android.support.v7.internal.view.SupportMenuInflater$MenuState.addItem(SupportMenuInflater.java:462) W/SupportMenuInflater( 1308): at android.support.v7.internal.view.SupportMenuInflater.parseMenu(SupportMenuInflater.java:196) W/SupportMenuInflater( 1308): at android.support.v7.internal.view.SupportMenuInflater.inflate(SupportMenuInflater.java:118) W/SupportMenuInflater( 1308): at com.grokkingandroid.sampleapp.samples.actionbar.actionviews.SearchViewFragment.onCreateOptionsMenu(SearchViewFragment.java:40)
Всякий раз, когда вы переносите существующий проект, я предлагаю вам выполнить поиск по всем источникам, особенно по ресурсам. Ищите «Шерлок», чтобы узнать, пропустили ли вы какие-либо ссылки. Другим хорошим кандидатом для решения проблем является файл манифеста, если вы ранее использовали стили ActionBarSherlock непосредственно внутри него.
Если вы исправили все файлы меню, вы закончили с ресурсами. Выберите Project -> Clean, чтобы очистить проект actionviews и избавиться от android:textIsSelectable
маркера ошибки. Инструменты разработчика Android генерируют новый R.java
файл, и пришло время взглянуть на источники Java.
Исправление фрагментов
Сначала я покажу вам, как исправить фрагменты, а позже — как исправить действия.
Подставляя SherlockDialogFragment с DialogFragment
Первый и самый простой способ исправить это AboutFragment
. Вы должны исправить наследование, так как этот класс наследует от класса ActionBarSherlock, из которого вы хотите перенести. Просто замените SherlockDialogFragment
наDialogFragment
и все в AboutFragment
порядке. Конечно, вы должны исправить импорт, нажав Ctrl-O.
Примечание. Eclipse спросит вас, использовать ли импорт со стандартного Android или из библиотеки поддержки. Всякий раз, когда eclipse предлагает вам эту альтернативу, вы всегда должны использовать импорт библиотеки поддержки :
Замените SherlockListFragment на ListFragment
Далее идет SearchFragment
. Это наследуется от SherlockListFragment
. Замените это запасом ListFragment
и нажмите Ctrl-O.
Замените getSherlockActivity () на getActivity ()
Остаются два красных маркера — оба для вызова метода, чтобы получить объект активности. Просто замените getSherlockActivity()
на, getActivity()
и код снова в порядке.
Заменить ШерлокФрагмент Фрагментом
Теперь о тех других фрагментах, из которых состоит говядина образца. Все эти фрагменты наследуются от базового класса DemoBaseFragment
. Снова вы должны изменить тип суперкласса. Замените классом SherlockFragment
запаса Fragment
библиотеки поддержки. Затем нажмите Ctrl-O и измените getSherlockActivity()
вызовы на getActivity()
вызовы, как указано выше.
Для четырех оставшихся фрагментов сначала измените импорт. ActionBarCompat не нуждается ни в каких специальных объектах Menu
или MenuItem
объектах, как в ActionBarSherlock. Таким образом, два из четырех фрагментов сразу корректны после исправления импорта. Эти двое чуть более вовлечены.
Используйте MenuItemCompat для ActionViews и ActionProviders
Проблема в ActionViews — основном содержании примера приложения. ActionBarCompat использует простые объекты меню. Но те не знают о ActionView до уровня API 11. Поэтому ActionBarCompat использует вспомогательный класс, названный MenuItemCompat
для работы с ActionViews и ActionProviders .
Вместо вызова getActionView()
объекта MenuItem вы должны использовать MenuItemCompat.getActionView()
. Например, новый способ получить ActionView SearchViewFragment
выглядит следующим образом:
SearchView searchView = (SearchView)MenuItemCompat.getActionView(item);
То же самое относится и к настройке ActionView. PlaceholderActionViewFragment
, Например , используются следующие строки:
MenuItemCompat.setActionView( PlaceholderActionViewFragment.this.mProgress, R.layout.actionview_progress);
Для ActionProviders вы должны будете сделать то же самое — просто с разными именами методов, конечно.
Исправление деятельности
Как и в случае с фрагментами, вы должны поменять суперклассы на действия. Проект actionviews использует одно базовое действие для всех действий в рамках проекта. Этот класс, очевидно, является отправной точкой для изменений в деятельности.
Замените SherlockFragmentActivity на ActionBarActivity
Изменение суперкласса для действий немного отличается от изменений, которые вы применили к фрагментам на предыдущих шагах. С фрагментами вы просто меняете их на стандартные фрагменты библиотеки поддержки. С действиями, с другой стороны, вы должны использовать супер класс библиотеки ActionBarCompat.
Откройте BaseActivity
и измените суперкласс с SherlockFragmentActivity
на ActionBarActivity
.
Замените getSupportMenuInflater () на getMenuInflater ()
Одна проблема остается после исправления импорта. Первая проблема — это вызов getSupportMenuInflater()
. Просто замените его getMenuInflater()
вместо этого.
Заменить идентификаторы макета Шерлока
Следующее действие, которое вы собираетесь исправить, — это ActionViewActivity
. После исправления всего импорта осталось еще два красных маркера. Они предназначены для конкретных ресурсов макета шерлока.
Сначала замените R.layout.sherlock_spinner_item
на android.R.layout.simple_spinner_item
. Далее замените sherlock_spinnner_dropdown_item
наandroid.R.layout.simple_spinner_dropdown_item
.
Соответствующие строки должны выглядеть следующим образом после применения этих изменений:
ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource( getSupportActionBar().getThemedContext(), resId, android.R.layout.simple_spinner_item); spinnerAdapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item);
Для двух оставшихся действий, которые я еще не рассмотрел, вам просто нужно исправить импорт, чтобы он снова компилировался. После этого ваш проект не должен содержать больше ошибок и должен нормально работать.
Уроки выучены
Прочитав этот пост, вы сможете перенести существующий проект, основанный на ActionBarSherlock, в ActionBarCompat. Вы видели веские причины, почему это необходимо сделать, и шаги, которые необходимо выполнить, чтобы ваш проект снова заработал.
Есть и другие отличные посты о ActionBarCompat. Марк Эллисон написал серию о ActionBarCompat, а Антонио Лейва также выпустил серию из трех частей о ActionBarCompat . В последнем посте также рассказывается о миграции с ActionBarSherlock . И у Габриэле Мариотти также есть много сообщений о ActionBarCompat . Мы все используем разные подходы — так что ищите стиль поста, который вам нравится больше всего. Если вы чувствуете, что здесь отсутствуют важные части, взгляните на эти посты.
До следующего раза. Удачного кодирования — и счастливой миграции!