
Привіт усім! Думаю, всі вже подивилися презентацію Android L і побачили її революційні нововведення для платформи матеріального дизайну Android. Ну, не доведеться чекати довго на реліз; а поки уважні користувачі могли помітити появу нових елементів дизайну в деяких застосунках. Моя увага була прикута до оновлення «Play Press». Воно виглядає і відчувається справді революційно; я застряг на кілька хвилин і навіть почав переглядати пресу.
Кожен розділ супроводжується анімованим фоном, який плавно зсувається і, розчиняючись, змінює зображення. Є багато незвичних анімацій, які приносять певну свіжість до застосунку.
Природно, кожен розробник, побачивши всі ці приємні речі, хоче реалізувати дані рішення у своїх проектах, навіть без навчальних посібників. На жаль, на момент презентації доступні рекомендації та документація не рясніли деталями, вони більше нагадували рекламний прайс-лист. На щастя, до моменту написання цієї статті Google виправив ситуацію, і ми побачимо, що у них є.
Рекомендації досить лаконічно і чітко описують філософію матеріального дизайну. Рекомендую всім ознайомитися з матеріалом, щоб уникнути помилок у майбутньому, і я не буду дублювати його тут. Лише одна заувага: напис «Цей документ є попереднім» інтригує і показує, що, можливо, це не фінальна версія.
Далі йде документація. Що вони обіцяють нам у новій версії? Якщо коротко, все зводиться до нової теми, нових віджетів, кастомних тіней і анімацій.
Матеріальна тема
Нова тема додасть нові стилі до старих віджетів, нові стилі кнопок, анімації на реакцію на дотики до елементів інтерфейсу, нові анімації переходів активностей. Що ще нам потрібно?! :)
Нові віджети
RecyclerView
RecyclerView, насправді, є логічним продовженням ListView — найпопулярнішого з розроблених віджетів Android. Насправді, його призначення залишається точно таким же — відображати список елементів, але з'явилися деякі проблеми.
Обов'язкове використання шаблону ViewHolder. Раніше, використовуючи ListView і не маючи достатнього досвіду, можна було використовувати адаптер, який створював окремий вигляд для кожного елемента в списку з нуля, і маючи великий список, це могло призвести до меншої чутливості інтерфейсу та використання зайвої пам'яті. Тепер розробник Android RecyclerView змушує розробника реалізувати лише шаблон ViewHolder. Давайте подивимося, як це виглядає в коді адаптера для RecyclerView.
LayoutManager. Щоб використовувати RecyclerView, потрібно передати клас об'єкта за допомогою методу setLayoutManager(), який реалізує LayoutManager. Цей клас відповідає за роботу з адаптером, тільки він вирішує, чи повторно використовувати View, чи створити новий, і відповідно викликає методи адаптера onCreateViewHolder(), onBindViewHolder() та getItemCount(). Наразі доступна лише одна реалізація цього класу — LinearLayoutManager, для створення кастомного LayoutManager потрібно використовувати RecyclerView.LayoutManager.
Анімація операцій зі списком. Якщо ви дивилися презентацію про Material design, то могли помітити, що однією з його основних характеристик є плавність інтерфейсу, що досягається за рахунок широкого використання анімації. Безумовно, за особливим бажанням, ви також можете додати анімацію до ListView. Я ще цього не робив, але в RecyclerView це реалізується всього кількома рядками коду.
Для об'єкта RecyclerView потрібно вказати клас, що реалізує анімацію:
RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator(); recyclerView.setItemAnimator(itemAnimator);
При додаванні або видаленні елемента списку вам слід відповідно викликати метод адаптера notifyItemInserted(int position) або notifyItemRemoved(int position).
За запитом ви можете написати власну реалізацію анімації на основі RecyclerView.ItemAnimator.
Сирість. Пам'ятайте, що віджет ще недопрацьований, і, можливо, він зазнає значних змін. Наприклад, наразі в RecyclerView немає можливості визначити заголовок і нижній колонтитул списку, і взагалі в Інтернеті все ще дуже мало інформації про це.
CardView
CardView — це віджет, що реалізує такий елемент Material design, як картка. Насправді це контейнер, в якому можна визначити радіус округленості кутів, колір картки та висоту вздовж осі Z.
Відображення тіней
Рендеринг тіней є цікавою інновацією для прихильників матеріальної філософії. Я уявляв це так: якщо елементи інтерфейсу є матеріальними, вони повинні кидати тінь. І якою має бути ця тінь? Звичайно, розмір залежатиме від положення елемента відносно фону та інших елементів. Ось чому віджети отримали нову настройку. Раніше ми визначали їхні розміри X і Y, тепер ми додали висоту Z. Таким чином, віджет на вищому рівні буде кидати більшу тінь.
Ця опція називається «android:elevation» і використовується наступним чином:
<TextView android:id="@+id/my_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/next" android:background="@color/white" android:elevation="5dp" />
Такий підхід також дозволяє контролювати багатошарові опції нашого інтерфейсу. Віджети можуть зміщуватися один відносно одного, кидаючи відповідну тінь, частково або повністю перекриваючи шари під ними. Це виглядає дуже вражаюче і природно, нагадує колаж або аплікацію, зроблену з елементів інтерфейсу.
Анімації
Анімація насправді зазнала великих змін, і ті, хто дивився рекомендації, погодяться зі мною, а ті, хто не дивився — поспішили це зробити :).
У новому API нам представлені нові анімації реакції на дотики користувача; нові анімації для змін станів окремих віджетів та анімації для змін активностей. Давайте коротко розглянемо кожну групу.
Зворотний зв'язок при дотику. Нова анімація реакції на дотик підсвічує координатну точку, на яку натиснув користувач, та демонструє подальший ефект хвилі від цієї точки в усіх напрямках. Анімація має логічний початок і кінець, виглядає дійсно чудово і розроблена для заміни старих селекторів. Вона реалізована класом RippleDrawable. Її можна реалізувати як в xml, так і в коді, застосовуючи до свого/вашого виду. Приклад реалізації в xml, встановлений як фон:
android:attr/selectableItemBackground android:attr/selectableItemBackgroundBorderless
Існує реалізація цього класу для попередніх версій. Її можна побачити на github.
Ефект Revealing. Цей ефект дозволяє ефективно показувати та приховувати різні види, реалізований класом ViewAnimationUtils.createCircularReveal. Ось кілька прикладів пояснень, взятих з документації.
Щоб показати раніше прихований View:
View myView = findViewById(R.id.my_view); // отримуємо центр для відкриття кола int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // отримуємо фінальний радіус відкриття кола int finalRadius = myView.getWidth(); // анімація починається зі значення 0 ValueAnimator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); anim.start();
Щоб приховати раніше відображений View:
final View myView = findViewById(R.id.my_view); // отримуємо центр закриття кола int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // отримуємо початковий радіус відкриття кола int initialRadius = myView.getWidth(); // створюємо анімацію з фінальним радіусом 0 ValueAnimator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0); // робимо вид невидимим, коли анімація закінчена anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); myView.setVisibility(View.INVISIBLE); } }); // початок анімації anim.start();
Перехід активностей. Тут не обійшлося без змін. Google додав концепцію «загального» елемента між активностями. Тобто, під час переходу між активностями анімації у нас є елемент, який може змінювати своє місцезнаходження та розмір, не залишаючи екран — це виглядає круто.
Всі анімації переходів описані в стилях; елементи повинні бути передані як параметр до intent:
// отримати елемент, який отримує подію натискання final View imgContainerView = findViewById(R.id.img_container); // отримати загальний елемент для переходу в цій активності final View androidRobotView = findViewById(R.id.image_small); // визначити слухача натискання imgContainerView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(this, Activity2.class); // створити анімацію переходу - зображення в макетах // обох активностей визначені з android:viewName="robot" ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation(this, androidRobotView, "robot"); // запустити нову активність startActivity(intent, options.toBundle()); } });
Ви можете передати кілька параметрів, якщо ми використовуємо кілька загальних елементів:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));
Криволінійний рух. Усі анімації в Material повинні бути плавними та змінюватися з часом, тобто змінювати свою швидкість. Раніше все було інакше. Якщо будь-яка анімація починалася з певної швидкості, вона закінчувалася б з тією ж. Тепер, якщо представити хід подій у вигляді графіка, він нагадуватиме параболу з розгладженим верхом. Це пояснення можна побачити на відео в інструкціях.
Класи PathInterpolator та ObjectAnimator допоможуть нам створити таку анімацію, перший використовується для анімації в xml-ресурсах, а другий — безпосередньо в коді:
ObjectAnimator mAnimator; mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); ... mAnimator.start();
Анімація змін стану View. Анімація змін стану нашого view здійснюється за допомогою розширеного селектора та класу StateListAnimator.
<!-- анімуйте властивість translationZ елемента при натисканні --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="2" android:valueType="floatType"/> <!-- ви можете мати інші елементи objectAnimator тут для "x" та "y", або інших властивостей --> </set> </item> <item android:state_enabled="true" android:state_pressed="false" android:state_focused="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="2" android:valueType="floatType"/> </set> </item> </selector>
Також з'явилася анімована версія селектора:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- надайте різний drawable для кожного стану --> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- задайте перехід --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Видобуток основних кольорів з зображення. З'явився потужний інструмент для дизайну в реальному часі під назвою клас Palette. Він повертає домінуючий колір з переданого зображення. Це дозволяє використовувати маску для того ж зображення, щоб накладати текст на нього або для інших цілей. Таким чином, палітра, яку використовує ваш дизайн, може бути налаштована в реальному часі відповідно до вмісту. Цей випадок використовується в матеріальній версії Play Music і виглядає справді круто.
Аргументація
На жаль, не все так райдужно, і тут також є муха в мазі... Практично всі нововведення доступні лише в L-preview версії, тому ви не можете скористатися ними з першої спроби. Щоб отримати цю можливість, нам потрібно використовувати останню версію Android Studio з новим менеджером маніфестів. Це утиліта, яка надає вам більшу гнучкість у контролі процесу «узгодження» всіх маніфестів бібліотек, що беруть участь у проекті.
Підключіть нову xml-схему під назвою tools:
xmlns:tools="http://schemas.android.com/tools"
Перевизначте версію, яка в кінцевому підсумку буде відшліфована у файлі build.gradle:
<uses-sdk tools:node="replace" />
Додайте залежні бібліотеки:
dependencies { compile 'com.android.support:cardview-v7:+' compile 'com.android.support:recyclerview-v7:+' compile 'com.android.support:palette-v7:+' }
Таким чином, нам, можливо, доведеться використовувати нові віджети, але функціональність буде обмежена. Що стосується теми, вона буде доступна лише в API версії 21. Після написання програми за допомогою нового SDK на пристрої з kitkat, ми побачимо, що майже нічого не змінилося. Все повинно виглядати відповідним чином, якщо встановити L-preview у тій же програмі — ключове слово тут «повинно», тому що наразі все жахливо крашиться. Ви, звичайно, можете спробувати виправити це, але відсутність підтримки теми в старіших версіях повністю вбиває будь-яке бажання це робити.
Висновок: Play Press є спробою Google адаптувати додаток до переходу на новий API, використовуючи нові віджети, і надати вигляд, схожий на Material, залучаючи старі інструменти. Можливо, це було зроблено для експериментів з підтримкою нової версії, але до сих пір Play Press не готовий до цього, оскільки після установки на Nexus 5 L-preview він також крашиться.
Щодо нових можливостей, вони поки що невизначені... Якщо Google не забезпечить належну підтримку попередніх версій і серій пристроїв, які мають отримати нове оновлення, найближчими шістьма місяцями наша робота з новим дизайном та наші інші зусилля можуть бути оцінені лише дуже малим відсотком користувачів... Ну, я, як завжди, сподіваюся на краще :).
Наша компанія з розробки програмного забезпечення рада оголосити про вихід нового блогу 2023 року, в якому представлені останні оновлення в Android Material Design 3, і ми щиро запрошуємо вас ознайомитися з цими досягненнями.