1. 简介
Material Components (MDC) 有助于开发者实现 Material Design。MDC 是由一组 Google 工程师和用户体验设计人员倾心打造的,提供数十种精美实用的界面组件,可用于 Android、iOS、Web 和 Flutter.material.io/develop |
在 Codelab MDC-101 中,您使用以下两种 Material Components (MDC) 组件构建了一个登录页面:文本字段和按钮。下面,我们将在此基础上添加导航功能、结构和数据,来扩充此页面。
构建内容
在此 Codelab 中,您将为名为 Shrine 的应用构建一个主屏幕。Shrine 是一款销售服装和家居用品的电子商务应用。其中包含:
- 顶部应用栏
- 商品网格列表
此 Codelab 中的 MDC-Android 组件
- AppBarLayout
- MaterialCardView
所需条件
- 已掌握 Android 开发方面的基础知识
- Android Studio(如果尚未安装,请在此处下载)
- Android 模拟器或设备(可通过 Android Studio 获取)
- 示例代码(参见下一步)
您如何评价自己在构建 Android 应用方面的经验水平?
2. 设置您的开发环境
接着 MDC-101 继续操作?
如果您已完成 MDC-101,那么您应该已经准备好用于此 Codelab 的代码。您可以跳至第 3 步:添加顶部应用栏。
从头开始?
下载起始 Codelab 应用
起始应用位于 material-components-android-codelabs-102-starter/java
目录中。请务必先通过 cd
命令转到该目录,然后再开始操作。
…或从 GitHub 克隆
如需从 GitHub 克隆此 Codelab,请运行以下命令:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 102-starter
在 Android Studio 中加载起始代码
- 在设置向导已完成且系统显示 Welcome to Android Studio 窗口后,点击 Open an existing Android Studio project。转到已安装示例代码的目录,然后选择 java -> hide(或在您的计算机中搜索 shrine)以打开 Shrine 项目。
- 稍等片刻,让 Android Studio 构建和同步项目,如 Android Studio 窗口底部的 activity 指示器所示。
- 此时,由于缺少 Android SDK 或构建工具,因此 Android Studio 可能会显示一些构建错误(如下所示)。按照 Android Studio 中的说明安装/更新这些内容,并同步您的项目。
添加项目依赖项
项目需要一个 MDC Android 支持库的依赖项。您下载的示例代码应该已经列出了此依赖项,但您最好按照以下步骤操作,以确保万无一失。
- 转到
app
模块的build.gradle
文件,并确保dependencies
代码块包含 MDC Android 的依赖项:
api 'com.google.android.material:material:1.1.0-alpha06'
- (可选)如有必要,请修改
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' }
运行起始应用
|
大功告成!您应该会看到在 MDC-101 Codelab 中构建的 Shrine 登录页面。
现在,登录屏幕看起来没有问题,下面我们要在应用中填充一些商品。
3. 添加顶部应用栏
登录页面关闭后,系统会显示主屏幕,其中一个屏幕会显示“You did it!”。太棒了!不过,现在用户没有可执行的操作,也不知道自己在应用中所处的位置。为了解决此问题,我们来添加导航功能。
Material Design 可提供确保高度易用性的导航模式。最重要的导航组件之一是顶部应用栏。
为了提供导航功能并让用户快速执行其他操作,我们来添加一个顶部应用栏。
添加 AppBar widget
在 shr_product_grid_fragment.xml
中,删除包含“You do it!”TextView
的 <LinearLayout>
标记,并替换成以下代码:
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
中,将以下内容添加到(您刚刚添加到布局中的)Toolbar
XML 组件:
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()
获取对 activity 的引用。如果 activity 不为 null,请使用 setSupportActionBar
将 Toolbar
设置为用作 ActionBar
:
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);
}
现在,我们要使用以下代码,为我们向 onCreateView()
方法的内容添加的 setUpToolbar
方法添加一个调用:
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;
}
最后,为 ProductGridFragment.java
添加 onCreate()
方法。在方法正文中,将 setHasOptionMenu
的参数设为 true
。
该方法应如下所示:
ProductGridFragment.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
以上代码将 XML 布局中的应用栏设为该 activity 的操作栏。回调 onCreateOptionsMenu
会告知 activity 要用作菜单的内容。在本例中,它会将 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);
}
}
构建并运行。您的主屏幕应如下所示:
现在,工具栏中会显示一个导航图标、一个标题,并在右侧显示两个操作图标。工具栏还使用细微的阴影来显示高度,这表明高度与内容位于不同的图层。
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>
构建并运行:
在此预览中,您可以看到卡片是从屏幕左侧边缘插入的,该卡片带有圆角和用于表达卡片高度的阴影。整个区域称为“容器”。除了容器本身之外,容器中的所有元素都是可选的。
您可以在容器中添加以下元素:标题文本、缩略图或头像、子标题文本、分隔线,甚至是按钮和图标。例如,我们刚刚创建的卡片在 LinearLayout
中包含两个 TextView
(一个用于标题,一个用于辅助文本),并且与卡片底部对齐。
卡片通常以集合的形式和其他卡片一起出现,在此 Codelab 的下一部分中,我们会将它们作为集合放置在网格中。
5. 创建卡片网格
当屏幕上出现多张卡片时,它们就会组成一个或多个集合。网格中的卡片同处一个平面,这意味着它们的静止高度相同(除非被选中或拖动,但我们不会在此 Codelab 中讨论这些)。
设置卡片网格
看看我们为您提供的 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
,它允许包含来自网址的图片)和两个 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
}
}
为了设置网格,我们首先要从 shr_product_grid_fragment.xml
中移除占位符 MaterialCardView
。接下来,您应添加代表卡片网格的组件。在本例中,请将 RecyclerView 组件添加到 shr_product_grid_fragment.xml
中的 AppBarLayout
XML 组件下方:
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>
最后,在 ProductGridFragment.java
中,将 RecyclerView
初始化代码添加到 onCreateView()
中,就放在调用 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);
}
}
上面的代码使用 ViewHolder
告知 RecyclerView
的适配器如何处理每张卡片。
在这里,它会设置 ViewHolder
中每个 TextView
的文本数据,并调用 ImageRequester
,以获取来自网址的图片。ImageRequester
是我们为方便您而提供的一个类,它使用 Volley
库(这不是此 Codelab 讨论的主题,但您可以自行探索该代码)。
构建并运行:
我们的商品现在出现在应用中了!
6. 回顾
我们的应用已经有了基本的流程,可将用户从登录页面转到主屏幕,然后用户可在主屏幕中查看商品。通过几行代码,我们添加了一个顶部应用栏(包含标题和三个按钮),以及一个用于展示应用内容的卡片网格。现在,我们的主屏幕非常简单实用,具有基本的结构和可操作的内容。
后续步骤
您现在使用了 MDC-Android 库中的四个 Material Design 核心组件:顶部应用栏、卡片、文本字段和按钮!您可以在 MDC Android 的 MDC-Android Catalog 组件中探索更多组件。
尽管我们的应用具有完善的功能,但尚未表达任何特定的品牌。在 MDC-103:通过颜色、形状、高度和类型设置 Material Design 主题中,我们将自定义这些组件的样式,来诠释一个充满活力的、现代的品牌。