Создание анимаций переходов между Activity в Android. Добавление анимации на основе физики в Android приложения
Обозначение металлических труб. Рассмотрим обозначения наиболее распространенных металлических трубопроводов согласно ГОСТ. Стальные водогазопроводные трубы по ГОСТ В обозначении трубы указывают условны диаметр, длину (при использовании труб мерной длины), толщину стенки. Рассмотрим пример обозначения трубы с диаметром условного прохода 32 мм, толщиной стенки 2,8 мм, без покрытия цинком: Труба 32х2,8 ГОСТ Наличие цинкового покрытия обозначают буквой Ц, которую размещают после слова "Труба".
При необходимости в обозначении трубы указывается отметка о наличии резьбы. Маркировка стальных труб по ГОСТ производится на заводе после изготовления и содержит информацию о размере, марке стали, из которой изготовлена труба, а также товарный знак производителя. Размер букв и цифр клеймления прямо пропорционально зависит от размера изделия и может наноситься несколькими методами.
Самые распространенные – клеймление и водостойкая краска. Виды контроля и их обозначение в маркировке изделий рассмотрены в таблице (Таблица); Следующий пункт «» обозначает толщину стенки в миллиметрах; Четвертое значение указывает длину изделия в миллиметрах от среза до среза, в данном случае это «».
Как расшифровать маркировку стальных труб: диаметр, марка стали и иные показатели по ГОСТу. Условные обозначения, нанесенные на стальную трубу, дают исчерпывающую информацию о продукции.
Маркировка – своеобразный паспорт изделия, из которого становится понятно, кто, где и для каких целей его изготовил. О том, как правильно расшифровать все символы маркировки на трубах, расскажет эта статья.
Примечание. Маркировка труб стальных (и чугунных) регламентируется ГОСТ № от года. В этом документе определены все нюансы нанесения пояснительных надписей, их размеры, расстояния между цифрами и.
Трубы стальные бесшовные холоднодеформированные ГОСТ (Сортамент) Настоящий стандарт распространяется на холоднодеформированные бесшовные трубы общего назначения из углеродистой и легированной стали. Диаметры: 5 - мм. В условных обозначениях труб индекс А или В проставляется перед маркой стали. Трубы изготовляют термически обработанными или без термической обработки.
Концы труб должны быть обрезаны под прямым углом. Способы нанесения маркировки на стальные трубы: стандарты ГОСТ, примеры расшифровки условных обозначений. Прочитав цифры на изделии, специалист может определить размер трубы, ее тип, марку стали, прочность, предприятие-изготовитель и некоторые другие параметры изделия.
Маркировка стальных труб специального назначения содержит дополнительную маркировку. К изделиям специального назначения относятся: Трубы из легированных марок стали. 4. Ссы ЛО чн Ы Е Норм ативно-технические докум енты. Обозначение НТД. на который дана ссылка. Ш с г -80 ГОСТ ю С1 Номер пункта. Изменение № 2 ГОСТ - 91 Трубы стальные элоктросвариые прямош овные.
Сортамент Принято Межгосударственным советом по стандартизации, метрологии и сертификации по пере писке (протокол № 45- от) Зарегистрировано Бюро по стандартам МГС № За принятие изменения проголосовали национальные органы по стандартизации следующих госу дарств: BY, KG, RU, TJ [код ы альфа-2 по МК (ИСО) ].
Продажа и покупка. Трубы стальные обозначение. Трубы стальные электросварные прямошовные. Сортамент. ГОСТ ИПК Издательство с тандартов. Государственный стандарт союза сср. Трубы стальные электросварные пр ямо шов ные. С ортамент. Electrically w elded steel line-weld lubes. Range. ГОСТ Дата введ ения 1. Настоящи й стандарт устана вливает сор тамент стальных электросварных прямошовных труб.
2. Размеры труб должны соответство вать табл. 1. 3. По длине трубы изготовляют: немерной длины Обозначение НТД, на который дана ссылка. Номер пункта. ГОСТ
Categories Post navigationНачиная с Android 4.4 в арсенале разработчиков появился дополнительный инструмент для создания анимаций - Transitions Framework. Изначально он предназначался для создания анимаций изменения состояния приложения путём манипулирования несколькими View. С выходом Android 5.0 набор доступных для использования анимаций был расширен, чтобы соответствовать представленной тогда же концепции Material Design.
Transitions Framework позволяет быстро и безболезненно создавать различные анимации. Поэтому в процессе работы над iFunny было невозможно пройти мимо этого инструментария. Вниманию читателей предлагается частный случай использования Transitions API - создание анимации перехода между Activity с эффектом «бесшовности».
С визуальной точки зрения представленные в Transitions Framework анимации переходов между Activity можно условно разделить на два типа: обычные анимации и анимации с общим элементом. Концепт анимации с общим элементом продемонстрирован на честно украденном с сайта developer.android.com рис. 1. На нём в роли общих элементов выступают аватар и имя контакта.
Рис. 1. Анимация перехода между Activity с общими элементами
Но никто не любит длинные вступления, поэтому сразу перейдём к рассказу о том, как создавались анимации данного типа в приложении iFunny. В качестве первого примера рассмотрим анимацию, показанную на рис. 2. Для её использования нам потребуется Android версии 5.0 и выше.
Рис. 2. Анимация перехода между Activity на экране аутентификации пользователя
С точки зрения пользователя, здесь нет ничего необычного: один экран, простенькая анимация. Но, как вы уже могли догадаться, «под капотом» - переход между двумя экранами с одним общим элементом.
Первым шагом к созданию подобного перехода является, как ни странно, выбор этого самого элемента и определение его местоположения в вёрстке обеих Activity. После этого в описание каждого View, отображающего выбранный элемент, нужно добавить атрибут android:transitionName, а также назначить им android:id, если таковой отсутствует.
В нашем случае это обычные ImageView следующего вида:
Здесь стоит отметить два важных момента. Во-первых, в обоих ImageView необходимо установить одинаковые transitionName, что логично. Во-вторых, коль скоро мы используем ImageView, то и содержимое у них должно быть одним и тем же, поскольку использование двух отличающихся ресурсов может привести к неожиданным последствиям (как минимум к морганию анимируемого View в начале и конце анимации).
На втором шаге необходимо добавить опции для запускаемой (второй) Activity, сообщающие о том, что при её запуске должна быть запущена анимация.
Примечание. Под «второй» подразумевается запускаемая Activity, переход к которой должен быть осуществлён, а под «первой» - запускающая Activity.
Делается это следующим образом:
Bundle bundle = null; if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { View v = activity.findViewById(R.id.auth_logo); if (v != null) { ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(activity, v, activity.getString(R.string.email_auth_transition)); bundle = options.toBundle(); } } Intent intent = new Intent(activity, SecondActivity.class); if (bundle == null) { activity.startActivity(intent); } else { activity.startActivity(intent, bundle); }
В приведённом листинге:
- R.id.auth_logo - ImageView из первой Activity, используемый в анимации;
- activity - первая Activity;
- R.string.email_auth_transition - метка, ранее оставленная в вёрстке обоих ImageView;
- SecondActivity.class - вторая Activity.
И сейчас внимательный читатель может испытать недоумение: во вступлении речь шла об использовании API level 19, в примере фигурировал API level 21, а в листинге выше стоит ограничение на API level 22. К сожалению, при написании кода выяснилось, что анимации перехода с общим элементом могут вести себя некорректно на телефонах c API level 21. Проявляется это в виде подтормаживаний анимации в целом и артефактов на анимируемом View в частности. Если вы уже знакомы с темой, знаете причины подобного поведения и/или способы решения описанной проблемы - расскажите нам об этом в комментариях.
На третьем шаге необходимо описать анимацию перехода, т.е. указать путь, проходимый анимируемым View, и трансформацию самого View. Для этого создадим отдельный файл projectName/src/main/res/transitions/email_auth_transition.xml со следующим содержимым:
Немного теории. Тег transitionSet предназначен для описания сразу нескольких трансформаций, применяемых к анимируемому View. Параметр transitionOrdering отвечает за порядок применения этих трансформаций. В нашем случае они применяются одновременно. Существует несколько типов готовых трансформаций, представленных в Transitions Framework. С полным списком можно ознакомиться на этой странице . Мы же остановимся на двух конкретных: changeBounds и changeImageTransform.
Первая предназначена для трансформации размера View. Вторая работает только с ImageView и в связке с первой позволяет изменять не только размер, но и форму ImageView. Использовав данные трансформации, получаем на выходе анимацию изменения размера изображения, представленную на рис. 2. Если не указывать тип движения анимируемого View, то он будет двигаться по кратчайшему пути. Более интересный способ передвижения рассмотрим во втором примере.
Последним шагом создания анимации является её объявление в темах обеих Activity. Для этого отредактируем описание тем следующим образом (или создадим новые в папке projectName/src/main/res/values-v22/theme.xml):
- android:windowActivityTransitions разрешает выполнение анимации перехода;
- android:windowSharedElementEnterTransition указывает на файл с описанием анимации перехода от первой Activity ко второй;
- android:windowSharedElementExitTransition указывает на файл с описанием анимации перехода при возвращении из второй Activity в первую.
Следует отметить, что для версий ОС ниже 5.1 необходимо создать темы с идентичными стилями, чтобы избежать вполне ожидаемых последствий в виде падения приложения. Например, поместим их в файл projectName/src/main/res/values/theme.xml:
Итак, для создания анимации перехода от Activity к Activity необходимо:
- Описать анимации (в нашем случае в xml-файле);
- Добавить эти анимации в xml-описание темы Activity;
- Пометить анимируемый общий элемент (View) в разметке;
- При запуске второй Activity указать в параметрах запуска, что для неё необходимо задействовать анимацию перехода.
Как видите, создавать такие анимации совсем не трудно, если не считать некоторых ограничений, упомянутых в первом примере. Теперь рассмотрим второй, более сложный пример. Тут нас интересует переход из раздела комментариев к профилю пользователя (рис. 3).
Рис. 3. Анимация перехода из комментариев к профилю пользователя
Все шаги по созданию перехода, рассмотренные выше, также подходят для этой анимации. А вот трансформация общего элемента реализована немного иначе. В приведённом ниже листинге описано перемещение общего элемента «по дуге» вместе с изменением его размера.
В чём же сложность второго примера? В первом случае использовалось изображение из ресурсов самого приложения, а тут - картинка загружается из сети. К тому же для комментариев изображение аватара пользователя берётся в более низком разрешении, чем для профиля. Поэтому требуется не только дать второй Activity доступ к изображению, используемому в первой, но и по завершении анимации подгрузить требуемое изображение в более высоком качестве. Так и получается две проблемы.
Для решения первой можно было бы собственноручно закэшировать изображение на диск или же передать его адрес в параметре второй Activity. Однако решение данной проблемы переложили на используемую в приложении библиотеку для загрузки изображений - Glide. При загрузке изображения достаточно просто добавить параметр diskCacheStrategy(DiskCacheStrategy.SOURCE), и оно будет закэшировано самой библиотекой (актуально для Glide версии 3.x). Следовательно, при повторном обращении к данному ресурсу из второй Activity будет использоваться кэшированный файл, что поможет нам избежать моргания анимируемого ImageView.
Вторая проблема также решается достаточно просто. В то время как осуществляется анимация перехода, профиль пользователя вместе с аватаром в более высоком разрешении скачиваются из сети и ожидают её завершения. Как только выполняются оба условия (завершение анимации и завершение загрузки), аватар пользователя обновляется. Добиться такого поведения можно, если использовать специальный Listener, в котором реализованы колбэки, вызываемые при смене статуса анимации. Для этого во Fragment, который принадлежит второй Activity, зададим этот самый Listener:
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { getActivity().getWindow().getSharedElementEnterTransition() .addListener(mEnterTransitionListener); } setAvatar(); }
Здесь происходит следующее:
- С помощью getSharedElementEnterTransition().addListener() задаётся Listener для анимации появления Activity;
- В методе setAvatar() производится попытка загрузки и установки аватара (который уже лежит в кэше).
Рассмотрим, как именно реализован Listener:
Private Transition.TransitionListener mEnterTransitionListener = new Transition.TransitionListener() { @Override public void onTransitionStart(Transition transition) { } @Override public void onTransitionEnd(Transition transition) { onProfileUpdated(); } @Override public void onTransitionCancel(Transition transition) { } @Override public void onTransitionPause(Transition transition) { } @Override public void onTransitionResume(Transition transition) { } };
В методе onProfileUpdated() мы обновляем содержимое профиля, в т.ч. и аватар.
Стоит отдельно упомянуть случай, когда общий элемент уходит за пределы экрана. Особенность его состоит в том, что, вопреки (а может, и согласно) логике, анимация перехода всё равно будет выполнена и будет смотреться достаточно забавно (рис. 4).
Рис. 4. Анимация возвращения из профиля в комментарии
Чтобы избежать подобного поведения, достаточно в момент ухода общего элемента за пределы экрана выставить ему видимость, отличную от View.VISIBLE.
В целом можно сказать, что Transitions Framework является простым и мощным инструментом для создания анимаций. Он не ограничивается только анимациями перехода между Activity - в статье был рассмотрен лишь частный случай его использования. Также стоит отметить, что помимо предоставляемых трансформаций имеется возможность создавать свои собственные, но это уже совсем другая история, достойная отдельного поста.
P.S. А о том, как придумывались анимации для iFunny, вы можете прочитать .
Начиная с Android 4.4 в арсенале разработчиков появился дополнительный инструмент для создания анимаций - Transitions Framework. Изначально он предназначался для создания анимаций изменения состояния приложения путём манипулирования несколькими View. С выходом Android 5.0 набор доступных для использования анимаций был расширен, чтобы соответствовать представленной тогда же концепции Material Design.
Transitions Framework позволяет быстро и безболезненно создавать различные анимации. Поэтому в процессе работы над iFunny было невозможно пройти мимо этого инструментария. Вниманию читателей предлагается частный случай использования Transitions API - создание анимации перехода между Activity с эффектом «бесшовности».
С визуальной точки зрения представленные в Transitions Framework анимации переходов между Activity можно условно разделить на два типа: обычные анимации и анимации с общим элементом. Концепт анимации с общим элементом продемонстрирован на честно украденном с сайта developer.android.com рис. 1. На нём в роли общих элементов выступают аватар и имя контакта.
Рис. 1. Анимация перехода между Activity с общими элементами
Но никто не любит длинные вступления, поэтому сразу перейдём к рассказу о том, как создавались анимации данного типа в приложении iFunny. В качестве первого примера рассмотрим анимацию, показанную на рис. 2. Для её использования нам потребуется Android версии 5.0 и выше.
Рис. 2. Анимация перехода между Activity на экране аутентификации пользователя
С точки зрения пользователя, здесь нет ничего необычного: один экран, простенькая анимация. Но, как вы уже могли догадаться, «под капотом» - переход между двумя экранами с одним общим элементом.
Первым шагом к созданию подобного перехода является, как ни странно, выбор этого самого элемента и определение его местоположения в вёрстке обеих Activity. После этого в описание каждого View, отображающего выбранный элемент, нужно добавить атрибут android:transitionName, а также назначить им android:id, если таковой отсутствует.
В нашем случае это обычные ImageView следующего вида:
Здесь стоит отметить два важных момента. Во-первых, в обоих ImageView необходимо установить одинаковые transitionName, что логично. Во-вторых, коль скоро мы используем ImageView, то и содержимое у них должно быть одним и тем же, поскольку использование двух отличающихся ресурсов может привести к неожиданным последствиям (как минимум к морганию анимируемого View в начале и конце анимации).
На втором шаге необходимо добавить опции для запускаемой (второй) Activity, сообщающие о том, что при её запуске должна быть запущена анимация.
Примечание. Под «второй» подразумевается запускаемая Activity, переход к которой должен быть осуществлён, а под «первой» - запускающая Activity.
Делается это следующим образом:
Bundle bundle = null;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
View v = activity.findViewById(R.id.auth_logo);
if (v != null) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(activity, v, activity.getString(R.string.email_auth_transition));
bundle = options.toBundle();
}
}
Intent intent = new Intent(activity, SecondActivity.class);
if (bundle == null) {
activity.startActivity(intent);
} else {
activity.startActivity(intent, bundle);
}
В приведённом листинге:
- R.id.auth_logo - ImageView из первой Activity, используемый в анимации;
- activity - первая Activity;
- R.string.email_auth_transition - метка, ранее оставленная в вёрстке обоих ImageView;
- SecondActivity.class - вторая Activity.
На третьем шаге необходимо описать анимацию перехода, т.е. указать путь, проходимый анимируемым View, и трансформацию самого View. Для этого создадим отдельный файл projectName/src/main/res/transitions/email_auth_transition.xml со следующим содержимым:
Немного теории. Тег transitionSet предназначен для описания сразу нескольких трансформаций, применяемых к анимируемому View. Параметр transitionOrdering отвечает за порядок применения этих трансформаций. В нашем случае они применяются одновременно. Существует несколько типов готовых трансформаций, представленных в Transitions Framework. С полным списком можно ознакомиться на этой странице . Мы же остановимся на двух конкретных: changeBounds и changeImageTransform.
Первая предназначена для трансформации размера View. Вторая работает только с ImageView и в связке с первой позволяет изменять не только размер, но и форму ImageView. Использовав данные трансформации, получаем на выходе анимацию изменения размера изображения, представленную на рис. 2. Если не указывать тип движения анимируемого View, то он будет двигаться по кратчайшему пути. Более интересный способ передвижения рассмотрим во втором примере.
Последним шагом создания анимации является её объявление в темах обеих Activity. Для этого отредактируем описание тем следующим образом (или создадим новые в папке projectName/src/main/res/values-v22/theme.xml):
Здесь:
- android:windowActivityTransitions разрешает выполнение анимации перехода;
- android:windowSharedElementEnterTransition указывает на файл с описанием анимации перехода от первой Activity ко второй;
- android:windowSharedElementExitTransition указывает на файл с описанием анимации перехода при возвращении из второй Activity в первую.
Итак, для создания анимации перехода от Activity к Activity необходимо:
- Описать анимации (в нашем случае в xml-файле);
- Добавить эти анимации в xml-описание темы Activity;
- Пометить анимируемый общий элемент (View) в разметке;
- При запуске второй Activity указать в параметрах запуска, что для неё необходимо задействовать анимацию перехода.
Рис. 3. Анимация перехода из комментариев к профилю пользователя
Все шаги по созданию перехода, рассмотренные выше, также подходят для этой анимации. А вот трансформация общего элемента реализована немного иначе. В приведённом ниже листинге описано перемещение общего элемента «по дуге» вместе с изменением его размера.
В чём же сложность второго примера? В первом случае использовалось изображение из ресурсов самого приложения, а тут - картинка загружается из сети. К тому же для комментариев изображение аватара пользователя берётся в более низком разрешении, чем для профиля. Поэтому требуется не только дать второй Activity доступ к изображению, используемому в первой, но и по завершении анимации подгрузить требуемое изображение в более высоком качестве. Так и получается две проблемы.
Для решения первой можно было бы собственноручно закэшировать изображение на диск или же передать его адрес в параметре второй Activity. Однако решение данной проблемы переложили на используемую в приложении библиотеку для загрузки изображений - Glide. При загрузке изображения достаточно просто добавить параметр diskCacheStrategy(DiskCacheStrategy.SOURCE), и оно будет закэшировано самой библиотекой (актуально для Glide версии 3.x). Следовательно, при повторном обращении к данному ресурсу из второй Activity будет использоваться кэшированный файл, что поможет нам избежать моргания анимируемого ImageView.
Вторая проблема также решается достаточно просто. В то время как осуществляется анимация перехода, профиль пользователя вместе с аватаром в более высоком разрешении скачиваются из сети и ожидают её завершения. Как только выполняются оба условия (завершение анимации и завершение загрузки), аватар пользователя обновляется. Добиться такого поведения можно, если использовать специальный Listener, в котором реализованы колбэки, вызываемые при смене статуса анимации. Для этого во Fragment, который принадлежит второй Activity, зададим этот самый Listener:
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
getActivity().getWindow().getSharedElementEnterTransition()
.addListener(mEnterTransitionListener);
}
setAvatar();
}
Здесь происходит следующее:
- С помощью getSharedElementEnterTransition().addListener() задаётся Listener для анимации появления Activity;
- В методе setAvatar() производится попытка загрузки и установки аватара (который уже лежит в кэше).
Private Transition.TransitionListener mEnterTransitionListener =
new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
onProfileUpdated();
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
};
В методе onProfileUpdated() мы обновляем содержимое профиля, в т.ч. и аватар.
Стоит отдельно упомянуть случай, когда общий элемент уходит за пределы экрана. Особенность его состоит в том, что, вопреки (а может, и согласно) логике, анимация перехода всё равно будет выполнена и будет смотреться достаточно забавно (рис. 4).
Рис. 4. Анимация возвращения из профиля в комментарии
Чтобы избежать подобного поведения, достаточно в момент ухода общего элемента за пределы экрана выставить ему видимость, отличную от View.VISIBLE.
В целом можно сказать, что Transitions Framework является простым и мощным инструментом для создания анимаций. Он не ограничивается только анимациями перехода между Activity - в статье был рассмотрен лишь частный случай его использования. Также стоит отметить, что помимо предоставляемых трансформаций имеется возможность создавать свои собственные, но это уже совсем другая история, достойная отдельного поста.
P.S. А о том, как придумывались анимации для iFunny, вы можете прочитать .
Теги:
- android
- material design
Уже довольно давно в Андроиде существует возможность использовать векторные ресурсы вместо png нарезки. Такая возможность появилась с релизом Android 5.0 Lollipop и API 21. Для более ранних версий системы, мы можем использовать AppCompat (библиотека совместимости), благодаря которой статичный вектор будет работать с API 7 (Android 2.1), а анимированный с API 11 (Android 3.0 Honeycomb).
Векторные ресурсы, в отличие от обычной нарезки, занимают примерно в 10 раз меньше места. Нет необходимости адаптировать графику под разные плотности экранов. Кроме того, можно переиспользовать ресурс в разном контексте, размере и цвете.
Другим важным преимуществом является возможность добавить анимацию. Да, конечно, анимацию можно сделать и при использовании png - например спрайтовую, но такая анимация будет занимать в десятки раз больше места с учетом поддержки всех разрешений.
Вектор на Андроид?
Прежде чем приступить к созданию векторных ассетов, необходимо разобраться что из себя представляет вектор на Андроиде. Понимание структуры очень важно, так как в настоящий момент не существует инструментов для удобного создания и визуального контроля анимации.
К сожалению (или к счастью), в Андроиде нельзя использовать svg файлы напрямую, по крайней мере, без использования сторонних библиотек. Причина очень проста и состоит в том, что SVG формат очень комплексный и богатый на возможности и поддержка столь богатого функционала сложна и не целесообразна для таких простых вещей как иконки, ну и не стоит забывать о проблеме производительности и совместимости. Именно поэтому в андроиде используют более простой формат, который, тем не менее, во многом похож на svg.
Векторная графика представлена в виде двух классов VectorDrawable и AnimatedVectorDrawable. Из названия классов понятно, что первый отвечает за статичный вектор, а второй за его анимацию. Классы описываются обычным XML ресурсом.
Для начала рассмотрим VectorDrawable, который имеет следующую структуру:
В элементе
Для того чтобы добавить анимацию мы используем класс ObjectAnimator который просто применяем на объекты VectorDrawable. Мы можем применять анимацию как к общей группе так и к конкретному
Раньше для реализации анимации в приложении необходимо было использовать как минимум 3 xml файла: 1 файл для VectorDrawable который необходимо анимировать, другой для аниматора описывающего анимацию и последний файл - объединяющий непосредственно аниматор и VectorDrawable. Чем сложнее анимация, тем больше файлов необходимо создавать, что часто приводило к путанице.
На Google I/O 2016 был представлен новый формат - XML bundle. Он позволяет описывать векторную анимацию одним файлом.
Пример XML Bundle
По сути, мы всю необходимую информацию размещаем в AnimatedVectorDrawable. Собрать такой файл очень легко, на картинке выделены куски, которые просто вырезаются из соответствующих ресурсов и вставляются между специальными aapt тэгами.
Готовим вектор под андроид
Для начала нам нужен любой графический редактор, который умеет на выходе выдавать svg файл. К счастью, их великое множество: Photoshop, Illustrator, Sketch, Inkscape, Affinity Designer и т.д.
При создании векторного изображения нужно использовать самые базовые инструменты, так как тени и прочие фильтры просто не будут работать.
Для примера я сделал простую иконку замка и разделил её на два шейпа (группы) для последующей анимации. Сохраняем в svg и обязательно проверяем корректность экспорта. Очень часто проблемы возникают со stroke и от избыточной вложенности объектов. Как правило, старайтесь по максимуму объединять всё в один объект, а stroke переводить в shape(outline).
Конвертация SVG в XML
Есть несколько способов сделать конвертацию svg файла в xml.
Первый способ - это сделать всё руками. Это конечно, не очень удобно, но ничего сложного тут нет. Просто переносим куски из svg в xml используя правильные имена параметров. Ниже я выделил куски, которые практически полностью совпадают.
Второй способ - В Android Studio есть инструмент Vector Asset Studio, который позволяет автоматически выполнить перевод SVG файла в XML. Ресурсы можно выбирать из библиотеки иконок или указать свой SVG файл. Благодаря превью можно сразу оценить корректность экспорта. Есть полезные настройки.
Третий способ - это использовать онлайн инструменты, например
В этом уроке мы:
Рассмотрим анимацию View-компонентов
Перед серьезными темами я решил все таки рассмотреть еще одну интересную и, на мой взгляд, несложную тему. Правда рассмотрю я только вершину и в дебри не полезу. Тема – анимация. Мы научимся проделывать следующие трансформации с обычными View-компонентами:
- менять прозрачность
- менять размер
- перемещать
- поворачивать
Создадим проект :
Project name
: P0201_SimpleAnimation
Build Target
: Android 2.3.3
Application name
: SimpleAnimation
Package name
: ru.startandroid.develop.p0201simpleanimation
Create Activity
: MainActivity
Трансформации конфигурируются в XML файлах, затем в коде программы считываются и присваиваются View-элементам. Я не буду дублировать и все расписывать, а сразу перейду к практике.
В нашем проекте есть папка res . Надо в ней создать папку anim . Сделать это можно, например, так: правой кнопкой на res и в меню выбираем New -> Folder . В папке anim надо создать файлы. Делается это аналогично: правой кнопкой на anim и в меню выбираем New -> File . В этих файлах будем конфигурировать анимацию.
Создаем следующие файлы в папке res/anim:
Имя файла : myalpha.xml
Содержимое :
Описание трансформации : меняется прозрачность с 0 до 1 в течение трех секунд.
Имя файла : myscale.xml
Содержимое :
Описание трансформации : изменение размера с 0.1 от оригинальной ширины и высоты до 1. Точка, относительно которой будет производиться масштабирование, лежит ровно посередине объекта (pivotX, pivotY). Продолжительность – 3 сек.
Имя файла : mytrans.xml
Содержимое :
Описание трансформации : перемещение с -150 относительно текущей позиции по оси X и -200 по оси Y в текущую позицию (0,0). Продолжительность – 3 сек.
Имя файла : myrotate.xml
Содержимое :
Описание трансформации : поворот относительно левого верхнего угла (т.к. не указаны pivotX, pivotY) на 360 градусов в течение трех секунд
Имя файла : mycombo.xml
Содержимое :
Описание трансформации
: одновременно увеличение размера и вращение в течение трех секунд. Обратите внимание, для комбинации трансформ использован тег
Итак, мы создали 5 файлов анимации.
И теперь можем применять их к View-компонентам.
Открываем main.xml и создадим экран:
По центру экрана находится TextView , к нему и будем применять трансформации. Для этого создадим контекстное меню для TextView, добавим пункты меню, соответствующие нашим наборам и при нажатии будем запускать анимацию.
Package ru.startandroid.develop.p0201simpleanimation; import android.app.Activity; import android.os.Bundle; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.MenuItem; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.TextView; public class MainActivity extends Activity { // константы для ID пунктов меню final int MENU_ALPHA_ID = 1; final int MENU_SCALE_ID = 2; final int MENU_TRANSLATE_ID = 3; final int MENU_ROTATE_ID = 4; final int MENU_COMBO_ID = 5; TextView tv; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView) findViewById(R.id.tv); // регистрируем контекстное меню для компонента tv registerForContextMenu(tv); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.tv: // добавляем пункты menu.add(0, MENU_ALPHA_ID, 0, "alpha"); menu.add(0, MENU_SCALE_ID, 0, "scale"); menu.add(0, MENU_TRANSLATE_ID, 0, "translate"); menu.add(0, MENU_ROTATE_ID, 0, "rotate"); menu.add(0, MENU_COMBO_ID, 0, "combo"); break; } super.onCreateContextMenu(menu, v, menuInfo); } @Override public boolean onContextItemSelected(MenuItem item) { Animation anim = null; // определяем какой пункт был нажат switch (item.getItemId()) { case MENU_ALPHA_ID: // создаем объект анимации из файла anim/myalpha anim = AnimationUtils.loadAnimation(this, R.anim.myalpha); break; case MENU_SCALE_ID: anim = AnimationUtils.loadAnimation(this, R.anim.myscale); break; case MENU_TRANSLATE_ID: anim = AnimationUtils.loadAnimation(this, R.anim.mytrans); break; case MENU_ROTATE_ID: anim = AnimationUtils.loadAnimation(this, R.anim.myrotate); break; case MENU_COMBO_ID: anim = AnimationUtils.loadAnimation(this, R.anim.mycombo); break; } // запускаем анимацию для компонента tv tv.startAnimation(anim); return super.onContextItemSelected(item); } }
Анимация читается из xml-файла методом AnimationUtils.loadAnimation , на выходе получается объект типа Animation . Его используем в методе startAnimation , который запускает анимацию.
Все сохраним и запустим приложение. Вызываем контекстное меню для TextView, и тестируем анимации
Я использовал не все возможности и параметры. Есть еще, например, параметр android:startOffset
– он указывает задержку при старте анимации. Т.е. если указать android:startOffset=”1000”, то анимация начнется через секунду. Это удобно использовать если вы делаете набор трансформ (