MDC-102 Android: структура и макет материала (Java)

1. Введение

logo_comComponents_color_2x_web_96dp.png

Material Components (MDC) помогают разработчикам реализовать Material Design. Созданный командой инженеров и UX-дизайнеров Google, MDC включает в себя десятки красивых и функциональных компонентов пользовательского интерфейса и доступен для Android, iOS, Интернета и Flutter.material.io/develop.

В кодовой лаборатории MDC-101 для создания страницы входа в систему вы использовали два компонента материала (MDC): текстовые поля и кнопки. Теперь давайте расширим эту основу, добавив навигацию, структуру и данные.

Что ты построишь

В этой лаборатории кода вы создадите главный экран для приложения Shrine — приложения для электронной коммерции, которое продает одежду и товары для дома. Он будет содержать:

  • Верхняя панель приложений
  • Сетчатый список продуктов

249db074eff043f4.png

Компоненты MDC-Android в этой лаборатории кода

  • AppBarLayout
  • МатериалКартаView

Что вам понадобится

  • Базовые знания Android-разработки.
  • Android Studio (скачайте здесь , если у вас его еще нет)
  • Эмулятор Android или устройство (доступно через Android Studio).
  • Пример кода (см. следующий шаг)

Как бы вы оценили свой опыт создания приложений для Android?

Новичок Средний Опытный

2. Настройте среду разработки

Продолжаем MDC-101?

Если вы прошли MDC-101, ваш код должен быть готов к этой лаборатории. Вы можете перейти к шагу 3: Добавьте верхнюю панель приложения .

Начиная с нуля?

Загрузите начальное приложение Codelab.

Стартовое приложение находится в каталоге material-components-android-codelabs-102-starter/java . Прежде чем начать, обязательно cd в этот каталог.

...или клонируйте его с GitHub

Чтобы клонировать эту кодовую лабораторию из GitHub, выполните следующие команды:

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 102-starter

Загрузите стартовый код в Android Studio.

  1. После завершения работы мастера установки и появления окна «Добро пожаловать в Android Studio» нажмите « Открыть существующий проект Android Studio» . Перейдите в каталог, в который вы установили пример кода, и выберите java -> shrine (или найдите на своем компьютере shrine ), чтобы открыть проект Shrine.
  2. Подождите, пока Android Studio создаст и синхронизирует проект, как показывают индикаторы активности в нижней части окна Android Studio.
  3. На этом этапе Android Studio может вызвать некоторые ошибки сборки, поскольку вам не хватает Android SDK или инструментов сборки, таких как показанный ниже. Следуйте инструкциям в Android Studio, чтобы установить/обновить их и синхронизировать проект.

F5H6srsw_5xOPGFpKrm1RwgewatxA_HUbDI1PWoQUAoJcT6DpfBOkAYwq3S-2vUHvweUaFgAmG7BtUKkGouUbhTwXQh53qec8tO5eVecdlo7QIoLc8rNxFEBb8l7RlS-KzBbZOzVhA

Добавить зависимости проекта

Проекту нужна зависимость от библиотеки поддержки Android MDC . В загруженном вами примере кода эта зависимость уже должна быть указана, но чтобы убедиться в этом, рекомендуется выполнить следующие шаги.

  1. Перейдите к файлу build.gradle модуля app и убедитесь, что блок dependencies включает зависимость от MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (Необязательно) При необходимости отредактируйте файл build.gradle , добавив следующие зависимости и синхронизировав проект.
dependencies {
    api 'com.google.android.material:material:1.1.0-alpha06'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:core:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}

Запустите стартовое приложение

  1. Убедитесь, что конфигурация сборки слева от кнопки «Выполнить/Воспроизвести»app .
  2. Нажмите зеленую кнопку «Выполнить/Воспроизвести», чтобы создать и запустить приложение.
  3. Если в окне «Выбор цели развертывания» у вас уже есть устройство Android в списке доступных устройств, перейдите к шагу 8 . В противном случае нажмите «Создать новое виртуальное устройство» .
  4. На экране «Выбор оборудования» выберите телефонное устройство, например Pixel 2 , и нажмите «Далее» .
  5. На экране «Образ системы» выберите последнюю версию Android , желательно самого высокого уровня API. Если он не установлен, щелкните появившуюся ссылку «Загрузить» и завершите загрузку.
  6. Нажмите Далее .
  7. На экране виртуального устройства Android (AVD) оставьте настройки без изменений и нажмите « Готово» .
  8. Выберите устройство Android в диалоговом окне цели развертывания.
  9. Нажмите «ОК» .
  10. Android Studio создает приложение, развертывает его и автоматически открывает на целевом устройстве.

Успех! Вы должны увидеть страницу входа в Shrine из лаборатории кода MDC-101.

4cb0c218948144b4.png

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

3. Добавьте верхнюю панель приложений.

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

Material Design предлагает шаблоны навигации, которые обеспечивают высокую степень удобства использования. Одним из наиболее заметных компонентов навигации является верхняя панель приложений.

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

Добавьте виджет AppBar

В shr_product_grid_fragment.xml удалите тег <LinearLayout> , содержащий фразу «Вы сделали это!» TextView и замените его следующим:

shr_product_grid_fragment.xml

<com.google.android.material.appbar.AppBarLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/app_bar"
       style="@style/Widget.Shrine.Toolbar"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>

Ваш shr_product_grid_fragment.xml должен выглядеть следующим образом:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

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

Добавьте значок навигации

Находясь в shr_product_grid_fragment.xml , добавьте следующее в XML-компонент Toolbar (который вы только что добавили в свой макет):

shr_product_grid_fragment.xml

app:navigationIcon="@drawable/shr_menu"

Ваш shr_product_grid_fragment.xml должен выглядеть следующим образом:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">
  
   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

Добавьте кнопки действий и стиль верхней панели приложений.

Вы также можете добавить кнопки в конце панели приложения. В Android они называются кнопками действий .

Мы оформим верхнюю панель приложения и программно добавим кнопки действий в ее меню.

Сначала давайте создадим метод для настройки панели инструментов. Метод должен получить ссылку на панель инструментов, используя ее id , а также получить ссылку на активность, используя getActivity() . Если активность не равна нулю, установите Toolbar для использования в качестве ActionBar с помощью setSupportActionBar :

ПродуктГридФрагмент.java

private void setUpToolbar(View view) {
   Toolbar toolbar = view.findViewById(R.id.app_bar);
   AppCompatActivity activity = (AppCompatActivity) getActivity();
   if (activity != null) {
       activity.setSupportActionBar(toolbar);
   }
}

Далее, непосредственно под только что добавленным методом setUpToolbar , давайте переопределим onCreateOptionsMenu чтобы раздуть содержимое shr_toolbar_menu.xml на панель инструментов:

ПродуктГридФрагмент.java

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
   super.onCreateOptionsMenu(menu, menuInflater);
}

Теперь добавьте вызов метода setUpToolbar , который мы добавили в содержимое метода onCreateView() следующим образом:

ПродуктГридФрагмент.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   // Inflate the layout for this fragment with the ProductGrid theme
   View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

   // Set up the toolbar
   setUpToolbar(view);

   return view;
}

Наконец, добавьте метод onCreate() в ProductGridFragment.java . В теле метода установите для параметра setHasOptionMenu значение true .

Метод должен выглядеть так:

ПродуктГридФрагмент.java

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setHasOptionsMenu(true);
}

Приведенный выше код устанавливает панель приложения из нашего XML-макета в качестве панели действий для этого действия. Обратный вызов onCreateOptionsMenu сообщает активности, что использовать в качестве меню. В этом случае пункты меню из R.menu.shr_toolbar_menu будут помещены в панель приложения.

Файл меню содержит два пункта: «Поиск» и «Фильтр».

shr_toolbar_menu.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/search"
       android:icon="@drawable/shr_search"
       android:title="@string/shr_search_title"
       app:showAsAction="always" />
   <item
       android:id="@+id/filter"
       android:icon="@drawable/shr_filter"
       android:title="@string/shr_filter_title"
       app:showAsAction="always" />
</menu>

После этих изменений ваш файл ProductGridFragment.java должен выглядеть следующим образом:

ПродуктГридФрагмент.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;


public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }
  
   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       return view;
   }
  
   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

Стройте и запускайте. Ваш главный экран должен выглядеть так:

d04e8aa3b27f4754.png

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

4. Добавьте карту

Теперь, когда наше приложение имеет некоторую структуру, давайте организуем контент, разместив его на карточках.

Добавить карту

Начнем с добавления одной карточки под верхней панелью приложения. На карточке должна быть область для изображения, заголовок и метка для дополнительного текста.

В shr_product_grid_fragment.xml добавьте следующее под AppBarLayout :

shr_product_grid_fragment.xml

<com.google.android.material.card.MaterialCardView
   android:layout_width="160dp"
   android:layout_height="180dp"
   android:layout_marginBottom="16dp"
   android:layout_marginLeft="16dp"
   android:layout_marginRight="16dp"
   android:layout_marginTop="70dp"
   app:cardBackgroundColor="?attr/colorPrimaryDark"
   app:cardCornerRadius="4dp">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
       android:background="#FFFFFF"
       android:orientation="vertical"
       android:padding="8dp">

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_title"
           android:textAppearance="?attr/textAppearanceHeadline6" />

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_description"
           android:textAppearance="?attr/textAppearanceBody2" />
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Сборка и запуск:

f6184a55ccb5f920.png

В этом предварительном просмотре вы можете видеть, что карточка вставлена ​​с левого края экрана, имеет закругленные углы и тень (которая выражает высоту карты). Вся эта область называется «контейнером». Помимо самого контейнера, все элементы внутри него являются необязательными.

В контейнер можно добавить следующие элементы: текст заголовка, миниатюру или аватар, текст подзаголовка, разделители и даже кнопки и значки. Например, карточка, которую мы только что создали, содержит два TextView (один для заголовка и один для вторичного текста) в LinearLayout , выровненных по нижней части карточки.

Карты обычно показываются в коллекции с другими картами. В следующем разделе этой кодовой лаборатории мы разместим их в виде коллекции в сетке.

5. Создайте сетку карточек.

Если на экране присутствует несколько карточек, они группируются в одну или несколько коллекций. Карты в сетке являются копланарными, то есть они имеют одну и ту же высоту покоя, что и друг друга (если только их не поднимают и не перетаскивают, но мы не будем рассматривать это в этой кодовой лаборатории).

Настройте сетку карточек

Взгляните на файл shr_product_card.xml , который мы вам предоставили:

shr_product_card.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   app:cardBackgroundColor="@android:color/white"
   app:cardElevation="2dp"
   app:cardPreventCornerOverlap="true">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">

       <com.android.volley.toolbox.NetworkImageView
           android:id="@+id/product_image"
           android:layout_width="match_parent"
           android:layout_height="@dimen/shr_product_card_image_height"
           android:background="?attr/colorPrimaryDark"
           android:scaleType="centerCrop" />

       <LinearLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:padding="16dp">

           <TextView
               android:id="@+id/product_title"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_title"
               android:textAppearance="?attr/textAppearanceHeadline6" />

           <TextView
               android:id="@+id/product_price"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_description"
               android:textAppearance="?attr/textAppearanceBody2" />
       </LinearLayout>
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Этот макет карты содержит карточку с изображением (здесь NetworkImageView , которая позволяет нам включать изображения из URL-адреса) и два TextViews .

Затем посмотрите на ProductCardRecyclerViewAdapter , который мы вам предоставили. Он находится в том же пакете, что и ProductGridFragment .

ProductCardRecyclerViewAdapter.java

package com.google.codelabs.mdc.java.shrine;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.codelabs.mdc.java.shrine.network.ImageRequester;
import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

import java.util.List;

/**
* Adapter used to show a simple grid of products.
*/
public class ProductCardRecyclerViewAdapter extends RecyclerView.Adapter<ProductCardViewHolder> {

   private List<ProductEntry> productList;
   private ImageRequester imageRequester;

   ProductCardRecyclerViewAdapter(List<ProductEntry> productList) {
       this.productList = productList;
       imageRequester = ImageRequester.getInstance();
   }

   @NonNull
   @Override
   public ProductCardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
       View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.shr_product_card, parent, false);
       return new ProductCardViewHolder(layoutView);
   }

   @Override
   public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
       // TODO: Put ViewHolder binding code here in MDC-102
   }

   @Override
   public int getItemCount() {
       return productList.size();
   }
}

Класс адаптера выше управляет содержимым нашей сетки. Чтобы определить, что каждое представление должно делать со своим содержимым, мы вскоре напишем код для onBindViewHolder() .

В том же пакете вы также можете взглянуть на ProductCardViewHolder . В этом классе хранятся представления, которые влияют на макет нашей карточки, поэтому мы можем изменить их позже.

ПродуктКардвиевхолдер.java

package com.google.codelabs.mdc.java.shrine;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       // TODO: Find and store views from itemView
   }
}

Чтобы настроить нашу сетку, сначала нам нужно удалить заполнитель MaterialCardView из shr_product_grid_fragment.xml . Далее вам следует добавить компонент, представляющий нашу сетку карточек. В этом случае добавьте компонент RecyclerView в shr_product_grid_fragment.xml под XML-компонентом AppBarLayout :

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:paddingStart="@dimen/shr_product_grid_spacing"
   android:paddingEnd="@dimen/shr_product_grid_spacing"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/recycler_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</androidx.core.widget.NestedScrollView>

Ваш shr_product_grid_fragment.xml должен выглядеть следующим образом:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>

   <androidx.core.widget.NestedScrollView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_marginTop="56dp"
       android:background="@color/productGridBackgroundColor"
       android:paddingStart="@dimen/shr_product_grid_spacing"
       android:paddingEnd="@dimen/shr_product_grid_spacing"
       app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <androidx.recyclerview.widget.RecyclerView
           android:id="@+id/recycler_view"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

   </androidx.core.widget.NestedScrollView>

</FrameLayout>

Наконец, в onCreateView() добавьте код инициализации RecyclerView в ProductGridFragment.java после вызова setUpToolbar(view) и перед оператором return :

ПродуктГридФрагмент.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   ...
   setUpToolbar(view);

   // Set up the RecyclerView
   RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
   recyclerView.setHasFixedSize(true);
   recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
   ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
           ProductEntry.initProductEntryList(getResources()));
   recyclerView.setAdapter(adapter);
   int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
   int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
   recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

   return view;
}

Приведенный выше фрагмент кода содержит необходимые шаги инициализации для настройки RecyclerView . Сюда входит настройка менеджера компоновки RecyclerView , а также инициализация и настройка адаптера RecyclerView .

Ваш файл ProductGridFragment.java теперь должен выглядеть следующим образом:

ПродуктГридФрагмент.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;


import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }

   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       // Set up the RecyclerView
       RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
       recyclerView.setHasFixedSize(true);
       recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
       ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
               ProductEntry.initProductEntryList(getResources()));
       recyclerView.setAdapter(adapter);
       int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
       int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
       recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

       return view;
   }

   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

Стройте и запускайте.

f9aeab846fc3bb4c.png

Карты уже там! Они пока ничего не показывают, поэтому давайте добавим немного данных о продукте.

Добавьте изображения и текст

Для каждой карточки добавьте изображение, название продукта и цену. Наша абстракция ViewHolder содержит представления для каждой карточки. В нашем ViewHolder добавьте три представления следующим образом:

ПродуктCardViewHolder.java

package com.google.codelabs.mdc.java.shrine;

import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;

import com.android.volley.toolbox.NetworkImageView;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public NetworkImageView productImage;
   public TextView productTitle;
   public TextView productPrice;

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       productImage = itemView.findViewById(R.id.product_image);
       productTitle = itemView.findViewById(R.id.product_title);
       productPrice = itemView.findViewById(R.id.product_price);
   }
}

В нашем адаптере RecyclerView в ViewHolder, обновите метод onBindViewHolder() чтобы установить информацию для каждого представления:

ProductCardRecyclerViewAdapter.java

@Override
public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
   if (productList != null && position < productList.size()) {
       ProductEntry product = productList.get(position);
       holder.productTitle.setText(product.title);
       holder.productPrice.setText(product.price);
       imageRequester.setImageFromUrl(holder.productImage, product.url);
   }
}

Приведенный выше код сообщает адаптеру нашего RecyclerView , что делать с каждой картой, используя ViewHolder .

Здесь он устанавливает текстовые данные для каждого из TextView ViewHolder и вызывает ImageRequester для получения изображения из URL-адреса. ImageRequester — это класс, который мы предоставили для вашего удобства, и он использует библиотеку Volley (это тема, выходящая за рамки данной лаборатории кода, но вы можете изучить код самостоятельно).

Сборка и запуск:

249db074eff043f4.png

Наши продукты теперь отображаются в приложении!

6. Подведение итогов

В нашем приложении есть базовый процесс, который переводит пользователя с экрана входа в систему на главный экран, где можно просмотреть товары. Всего за несколько строк кода мы добавили верхнюю панель приложения с заголовком и тремя кнопками, а также сетку карточек для представления содержимого нашего приложения. Наш главный экран теперь стал простым и функциональным, с базовой структурой и полезным контентом.

Следующие шаги

В верхней панели приложения, карточке, текстовом поле и кнопке мы теперь использовали четыре основных компонента Material Design из библиотеки MDC-Android! Вы можете изучить еще больше компонентов в каталоге компонентов MDC-Android в MDC Android .

Несмотря на то, что наше приложение полностью функционально, оно еще не представляет какой-либо конкретный бренд. В MDC-103: Темы дизайна материалов с использованием цвета, формы, высоты и типа мы настроим стиль этих компонентов, чтобы выразить яркий, современный бренд.

Мне удалось завершить эту кодовую работу, потратив разумное количество времени и усилий.

Полностью согласен Соглашаться Нейтральный Не согласен Категорически не согласен

Я хотел бы продолжать использовать Material Components в будущем.

Полностью согласен Соглашаться Нейтральный Не согласен Категорически не согласен