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

logo_components_color_2x_web_96dp.png

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

material.io/develop

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

Что вы построите

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

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

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

  • AppBarLayout
  • MaterialCardView

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

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

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

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

Продолжение 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, чтобы установить/обновить их и синхронизировать свой проект.

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

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

  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.

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

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

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

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

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

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

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() . Если активность не равна null, настройте использование Toolbar в качестве ActionBar с помощью setSupportActionBar :

ProductGridFragment.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 в панель инструментов:

ProductGridFragment.java

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

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

ProductGridFragment.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 .

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

ProductGridFragment.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 должен выглядеть следующим образом:

ProductGridFragment.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);
   }

}

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

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

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

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

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

В 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>

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

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

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

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

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

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

Взгляните на файл 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 . Этот класс хранит представления, влияющие на макет нашей карточки, чтобы мы могли изменить их позже.

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 :

ProductGridFragment.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 должен выглядеть следующим образом:

ProductGridFragment.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);
   }

}

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

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

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

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

ProductCardViewHolder.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 (это тема, выходящая за рамки данной практической работы, но вы можете изучить код самостоятельно).

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

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

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

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

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

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

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

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

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

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