Material 2.0 для разработчиков. Краткий обзор новых компонентов



    В мае на Google I/O мы впервые увидели Material Design 2.0. Команда Google провела крупный рефакторинг и выпустила обновленную библиотеку дизайна. В ней появились новые компоненты и анимации. Мы следим за развитием Material Components с самого начала. Сейчас все находится на стадии RC1, и уже скоро выйдет в релиз. Под катом обзор новых и обновленных UI-компонентов для тех, кто еще не пробовал их в работе, но интересуется.


    Android X вместо Support library


    «Как это уже задеприкейтили? Я даже попробовать ее толком не успел», – сказал один мой знакомый, когда узнал о переезде Material Components в новый пакет. Действительно, поддержки support.design больше не будет, а на ее место придет com.google.android.material.
    В рамках проекта Android X Google устроили рефакторинг всей библиотеки поддержки и архитектурных компонентов. Подробнее можно почитать в их блоге. Вот пример некоторых пакетов:


    старый пакет


    android.support.@
    android.databinding.@
    android.design.@

    новый пакет


    androidx.@
    androidx.databinding.@
    com.google.android.material.@

    К счастью, для «мягкого» переезда на новую библиотеку, в студии появится инструмент, позволяющий автоматически обновить все зависимости. Сейчас это доступно уже в Android Studio Canary 3.3. Он призван автоматически находить все зависимости в импортах, в gradle файлах, в XML и в Proguard.





    Material library


    Все старые UI-компоненты из Support Library переехали в Material library, а ещё появились новые компоненты. Добавим в проект новую зависимость:


    implementation 'com.google.android.material:material:1.0.0-rc01'

    Обратной совместимости с Support не предполагается. Придется избавиться от всех остальных зависимостей, где встречается слово support, и заменить их на соответствующие из Android X. Иначе проект просто не соберется из-за множества конфликтов. Для тестовой сборки мне пришлось даже заменить Glide на Picasso, потому что первый тянет за собой android-support. На большом проекте вручную это делать будет неудобно.




    Однако для тестирования Material Components можем воспользоваться support:design версии 28-beta, куда Google любезно продублировала все актуальные компоненты. Несмотря на это, 28 версия Support library будет последней, и в дальнейшем ее поддержка прекратится. А теперь давайте посмотрим на новые компоненты, и измененные старые.


    BottomAppbar




    BottomAppbar – это что-то похожее на Appbar, только с возможностью прикрепления Floating Action Button и вырезом под него. Предназначен для работы внутри CoordinatorLayout.
    Вот некоторые параметры, которые мы можем кастомизировать:


    • app:backgroundTint — цвет заполненного пространства
    • app:fabAlignmentMode — положение FAB
    • app:fabCradleMargin — отступ между FAB и BottomAppbar
    • app:fabCradleRoundedCornerRadius — закругление на углах выреза для FAB
    • app:fabCradleVerticalOffset
    • app:hideOnScroll

    <com.google.android.material.floatingactionbutton.FloatingActionButton
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       app:layout_anchor="@id/bottomAppBar"/>
    
    <com.google.android.material.bottomappbar.BottomAppBar
       android:id="@+id/bottomAppBar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
       app:backgroundTint="@color/colorPrimary"
       app:fabCradleMargin="4dp"/>

    На момент написания статьи, BottomAppBar доделан не до конца. Например, нельзя разместить NavigationIcon в центре по вертикали, но, наверное, это скоро допилят.


    Chips




    Chip – еще одна новая View в библиотеке. С её помощью можно удобно показывать перечисление небольших объектов. Например, фильтры или какие-нибудь подсказки для пользователя. По гайдлайнам Chip обладает следующими свойствами:


    • Может иметь иконку контента (слева).
    • Может иметь иконку для удаления (справа).
    • Содержит текст.
    • Может находится в двух состояниях, как CheckBox.

    Реализация в Material library представляет из себя расширенную версию AppCompatCheckBox, и может порадовать нас такими кастомизируемыми параметрами:


    • app:chipCornerRadius
    • app:chipMinHeight
    • app:chipBackgroundColor
    • app:chipStrokeColor
    • app:chipStrokeWidth
    • app:rippleColor
    • android:text
    • android:textAppearance
    • app:chipIconVisible
    • app:chipIcon
    • app:chipIconTint
    • app:chipIconSize
    • app:closeIconVisible
    • app:closeIcon
    • app:closeIconSize
    • app:closeIconTint
    • app:checkable
    • app:checkedIconVisible
    • app:checkedIcon
    • app:showMotionSpec
    • app:hideMotionSpec

    Приятно удивило наличие ChipGroup, являющегося наследником FlexboxLayout, которого наконец-то включили в библиотеку дизайна.


    BackDrop




    BackDrop – новый для Android паттерн навигации. Есть основной контент, который расположен на переднем плане, и дополнительная область, лежащая позади (обычно это меню навигации). Если нужно добраться до контента сзади, то передний план съезжает вниз до нужного уровня.
    Состоит Backdrop из трех элементов:


    • Toolbar
    • Front layout
    • Back layout

    На момент написания статьи он еще не реализован в библиотеке, и в соответствующем репозитории пока пусто. Поэтому пришлось делать свою реализацию, обернув ее в библиотеку:


    Просто прикрепляем BackdropBehavior на нужный Front Container и передаем ему Toolbar и Back Container.


    XML


    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
        <LinearLayout
            android:id="@+id/backContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"/>
    
        <!-- Add BackdropBehavior to this view -->
        <android.support.design.card.MaterialCardView
            android:id="@+id/foregroundContainer"
            app:layout_behavior="ru.semper_viventem.backdrop.BackdropBehavior"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </android.support.design.widget.CoordinatorLayout>

    Kotlin


    val backdropBehavior: BackdropBehavior = foregroundContainer.findBehavior() // find behavior
    
    with(backdropBehavior) {
            attachBackContainer(R.id.backContainer) // set back container
            attachToolbar(R.id.toolbar) // set toolbar
    
            // set navigation icons for toolbar
            setClosedIcon(R.drawable.ic_menu)
            setOpenedIcon(R.drawable.ic_close)
    
            // add listener
            addOnDropListener(object : BackdropBehavior.OnDropListener {
                override fun onDrop(dropState: BackdropBehavior.DropState, fromUser: Boolean) {
                    // TODO: handle listener            
                }
            })
    }

    Это просто один из вариантов реализации. Но для моего кейса получилось удобно. Думаю, решение Google будет несколько отличаться. Если вдруг есть предложения, то с радостью готов обсудить их в комментариях под статьей.


    MaterialButtons




    MaterialButtons – обновленные более кастомизируемые кнопки. У них есть следующие параметры для кастомизации:


    • android:inset (Left, Top, Right, Bottom) — отступ кнопки от края View
    • app:backgroundTint — цвет заполнения кнопки
    • app:backgroundTintMode
    • app:icon — можно добавить иконку, по умолчанию слева от текста
    • app:iconPadding
    • app:iconTint
    • app:iconTintMode
    • app:strokeColor — для создания кнопок с обводкой
    • app:strokeWidth
    • app:cornerRadius
    • app:rippleColor


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


    Например, чтобы сделать кнопку с крестиком, раньше пришлось бы писать два XML файла:


    Layout:


    <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:background="@drawable/bg_button"
       android:drawablePadding="@dimen/small_gap"
       android:drawableStart="@drawable/ic_close"
       android:paddingStart="@dimen/small_gap"
       android:paddingEnd="@dimen/small_gap"
       android:drawableTint="@color/colorAccent"
       android:text="Icon button"/>

    bg_button.xml


    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
       <item>
           <ripple android:color="@color/colorAccent">
               <item android:id="@android:id/mask">
                   <shape android:shape="rectangle">
                       <solid android:color="@color/white"/>
                       <corners android:radius="16dp"/>
                   </shape>
               </item>
           </ripple>
       </item>
       <item>
           <shape android:shape="rectangle">
               <stroke
                   android:color="@color/colorAccent"
                   android:width="1dp"/>
               <corners android:radius="16dp"/>
           </shape>
       </item>
    </layer-list>

    Теперь описать кнопку можно сразу на месте:


    <com.google.android.material.button.MaterialButton
       style="@style/Widget.MaterialComponents.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       app:cornerRadius="16dp"
       app:icon="@drawable/ic_close"
       app:strokeColor="@color/colorAccent"
       app:strokeWidth="1dp"
       android:text="Icon button"/>

    Text Fields




    Text Fields – тоже претерпел изменения. Теперь текстовому полю «из коробки» можно добавить обводку по контуру, сделать его залитым каким-то цветом, или закруглить отдельные углы.


    Как и раньше, можно использовать конструкцию из InputLayout с дочерним EditText, для более удобного для отображения подсказок, ошибок и прочего выделения текста.


    • app:boxCornerRadiusTopLeft
    • app:boxCornerRadiusTopRight
    • app:boxCornerRadiusBottomLeft
    • app:boxCornerRadiusBottomRight
    • android:hint
    • app:hintEnabled
    • app:errorEnabled
    • app:setError
    • app:helperTextEnabled
    • app:helperText
    • app:passwordToggleEnabled
    • app:passwordToggleDrawable
    • app:counterEnabled
    • app:counterMaxLength

    Изменения тоже не очень существенные, но кастомные решения можно разрабатывать теперь намного быстрее. С точки зрения бизнеса, скорость разработки имеет значение, и тут Google постарались неплохо.


    MaterialCardView




    MaterialCardView – это все старая CardView, но теперь с обводкой по контуру, как у кнопок.


    • app:strokeColor
    • app:strokeWidth

    Итого


    Существенных изменений не так много. Новые механизмы кастомизации просто позволяют сделать чуточку проще то, что мы все делали и раньше. Зато появилась проблема совместимости с Support library. Разработчикам библиотек придется переезжать на Android X, что отнимет много времени и нервов. Особенно, если учесть, какая кодовая база сейчас support-ориентированна. Несмотря на то, что Google предоставляет инструмент для автоматизации переезда с заменой всех импортов, работает он не идеально. Подобные переезды на своих проектах все-таки придется пережить с некоторыми трудностями.


    На данный момент не все заявленные Material-компоненты реализованы корректно, а некоторые не реализованы совсем. Будем смотреть, будем пробовать.

    MobileUp

    76,00

    Мобильная разработка повышенной сложности

    Поделиться публикацией

    Похожие публикации

    Комментарии 13
      0
      off впечатление, что дизайн развивается по спирали и снова возвращается к закруглениям A.2.3
        0
        Справедливое замечание. Вообще, дизайну свойственна цикличность. Например, в apple отказались от скевоморфизма в IOS 7, однако в последних версиях системы можно наблюдать концепцию глубины интерфейса. Стараются избавиться от ненужных деталей, которые когда-то привлекали взгляд пользователя (объемные иконки, лишние тени, дивайдеры и прочая шелуха, создающая информационный «шум» в интерфейсе). Сейчас уклон идет в пользу полезной нагрузки.
        А закругленные края — это просто более привычная человеческому глазу геометрия, ведь в природе прямых углов практически не существует.
        0
        впечатление, что дизайн развивается по спирали
        Не только дизайн :)
          +2
          C Backdrop интересная ситуация: в репозитории его нет, но вот тут есть лаба по его созданию: codelabs.developers.google.com/codelabs/mdc-104-kotlin/#0
            0
            Спасибо за наводку. Кодлабу не видел в момент написания. Но хочется все-таки посмотреть гугловую реализацию в духе навигационного дровера :)
            0

            По поводу библиотек, которые тянут за собой старые support зависимости — есть же jetify, который как раз и занимается переписыванием зависимостей в подключаемых либах с support на androidx

              0

              *Jetifier

              0
              А вы пробовали запустить TextInputLayout с новым дизайном, потому что когда я пробовал RC, там ну вот совсем не по гайдам было. Например, hint, когда нет текста и фокуса, был прижат к низу, хотя по гайдам по центру.
              Так же проблемы при фокусе или если поле содержит текст, подсказка, которая уезжает наверх имела слишком большой отступ сверху. В итоге пришлось наследоваться и немного поправить отступы, чтобы получить то, что надо.
                0
                Да, пробовал TextInputLayout. «Из коробки» у него и правда были проблемы с отступами. Но я бы не сказал, что это как-то нарушает гайдлайны, поскольку гайдлайны теперь стали более абстрактными и менее обязательными. А вообще, текстовые поля ведь тоже хорошо кастомизируются сейчас.
                  +1
                  Оно выглядит отвратительно. А кастомизация не спасает от этого, невозможно из коробки сделать так, как нарисовал гугл
                    0
                    Это ведь только RC. До релиза еще есть время поправить материал-либу. У них сейчас сформирован API для элементов, но такие вещи, думаю, приведут в порядок.
                +1
                Хотелось бы услышать про новый RecyclerView с «красивым» multiselect и слайсы для асистента, Даешь сиквел!
                  0
                  Я что-то пропустил? Какой ещё новый RecyclerView? multiselect ведь отдельной бибилиотекой подключается или вообще стал частью support library.

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

                Самое читаемое