商城项目实战 | 5.1 RecyclerView 和 Card
本文为菜鸟窝作者刘婷的连载。”商城项目实战”系列来聊聊仿”京东淘宝的购物商城”如何实现。
在前面的两篇文章《商城项目实战 | 4.1 RecyclerView 使用完全解析 体验艺术般的控件(一)》和《商城项目实战 | 4.2 RecyclerView 使用完全解析 体验艺术般的控件(二)》中已经对 RecyclerView 的属性以及使用做了非常详细的介绍了,这里就不多说了,我们就先来讲讲 CardView 吧。
CardView 的概述
1. CardView是什么
CardView 和 RecyclerView 一样,也是在安卓5.0提出的,顾名思义,CardView 是一款卡片式控件,可以设置阴影、圆角等属性,卡片效果很优美,同时在用户体验上更加受到好评。
2. CardView 的基本属性
了解控件的基本属性,可以知道如何更好的使用该控件,其基本属性如下。
<attr name="cardBackgroundColor" format="color" /><!-- 背景色 -->
<attr name="cardCornerRadius" format="dimension" /><!-- 边缘弧度数 -->
<attr name="cardElevation" format="dimension" /> <!-- 高度 -->
<attr name="cardMaxElevation" format="dimension" /> <!-- 最大高度 -->
<!-- 设置内边距 设置内边距,v21+的版本和之前的版本仍旧具有一样的计算方式-->
<attr name="cardUseCompatPadding" format="boolean" />
<!-- 在v20和之前的版本中添加内边距,这个属性是为了防止卡片内容和边角的重叠 -->
<attr name="cardPreventCornerOverlap" format="boolean" />
<!-- 下面是卡片边界距离内部的距离-->
<attr name="contentPadding" format="dimension" />
<attr name="contentPaddingLeft" format="dimension" />
<attr name="contentPaddingRight" format="dimension" />
<attr name="contentPaddingTop" format="dimension" />
<attr name="contentPaddingBottom" format="dimension" />
实现首页商品分类
对于 CardView 和 RecyclerView 都有了一定的认识了,那些下面就要开始实现商品分类的效果了,具体的效果如下图所示。
上面的广告轮播在文章《商城项目实战 | 3.1 AndroidImageSlider 实现炫酷轮播广告》已经介绍了,下面的商品分类就是这次需要实现的。
1. Gradle 添加依赖
在 module 下的 build.gradle 文件下面添加对 RecyclerView 和 CardView 的依赖。
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.2.0'
testCompile 'junit:junit:4.12'
compile 'com.android.support:support-v4:25.2.0'
compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'com.android.support:cardview-v7:25.2.0'
}
2. 定义实体类
根据商品分类的效果展示,可以了解到实体类的属性有 title 、大图以及两张小图,所以定义实体类如下。
public class HomeCategoryInfo extends CategoryInfo {
private String name;//分类名称
private int imgBig;//大图
private int imgSmallTop;//上面的小图
private int imgSmallBottom;//下面的小图
public HomeCategoryInfo(String name, int imgBig, int imgSmallTop, int imgSmallBottom) {
this.name = name;
this.imgBig = imgBig;
this.imgSmallTop = imgSmallTop;
this.imgSmallBottom = imgSmallBottom;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImgBig() {
return imgBig;
}
public void setImgBig(int imgBig) {
this.imgBig = imgBig;
}
public int getImgSmallTop() {
return imgSmallTop;
}
public void setImgSmallTop(int imgSmallTop) {
this.imgSmallTop = imgSmallTop;
}
public int getImgSmallBottom() {
return imgSmallBottom;
}
public void setImgSmallBottom(int imgSmallBottom) {
this.imgSmallBottom = imgSmallBottom;
}
}
3. 布局设计
布局中有标题、大图和两张小图,而且第一项中是大图在右边,两张小图在左边,而第二项中是大图在左边,两张小图在右边,所以至少要设计两个布局文件,但是首先是要在首页 Fragment 中写入 RecyclerView 。
<android.support.v7.widget.RecyclerView
android:id="@+id/home_recycler_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
下面就是 item 项的布局设计了,需要有个布局文件,唯一的差别是图片的摆放左右有所不同,这里就展示大图在左边的 layout 文件了,大图在右边的可以直接仿照的写就行了。因为布局中的控件是一样的,所以 id 也就使用相同的就可以了。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#fff"
app:contentPadding="10dp"
app:cardCornerRadius="4dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/category_tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="热门活动"
android:textSize="20dp"
android:textColor="@color/black"
android:paddingTop="10dp"
/>
<View
style="@style/line_vertical"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"></View>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/category_img_big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<View
android:id="@+id/line"
style="@style/line_horizontal"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<ImageView
android:id="@+id/category_img_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<View
android:id="@+id/line2"
style="@style/line_vertical"
></View>
<ImageView
android:id="@+id/category_img_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
4. 定义 Adapter
列表 item 的布局文件已经写好了,接下来需要准备的就是适配器 Adapter 了。在定义的时候注意第一项中是大图在右边,两张小图在左边,而第二项中是大图在左边,两张小图在右边,所以需要判断下根据 position 的位置来确定布局的样式。定义的 Adapter 必须继承于 RecyclerView.Adapter,然后绑定布局和数据,具体代码如下。
private static int VIEW_TYPE_L=0;
private static int VIEW_TYPE_R=1;
private LayoutInflater mInflater;
private List<HomeCategoryInfo> mDatas;
public HomeCategoryAdapter(List<HomeCategoryInfo> datas){
mDatas = datas;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
mInflater = LayoutInflater.from(viewGroup.getContext());
if(type == VIEW_TYPE_R){
return new ViewHolder(mInflater.inflate(R.layout.recycler_item_even_layout,viewGroup,false));
}
return new ViewHolder(mInflater.inflate(R.layout.recycler_item_odd_layout,viewGroup,false));
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
HomeCategoryInfo category = mDatas.get(i);
viewHolder.textTitle.setText(category.getName());
viewHolder.imageViewBig.setImageResource(category.getImgBig());
viewHolder.imageViewSmallTop.setImageResource(category.getImgSmallTop());
viewHolder.imageViewSmallBottom.setImageResource(category.getImgSmallBottom());
}
@Override
public int getItemCount() {
return mDatas.size();
}
@Override
public int getItemViewType(int position) {
if(position % 2==0){
return VIEW_TYPE_R;
}
else return VIEW_TYPE_L;
}
static class ViewHolder extends RecyclerView.ViewHolder{
TextView textTitle;
ImageView imageViewBig;
ImageView imageViewSmallTop;
ImageView imageViewSmallBottom;
public ViewHolder(View itemView) {
super(itemView);
textTitle = (TextView) itemView.findViewById(R.id.category_tv_title);
imageViewBig = (ImageView) itemView.findViewById(R.id.category_img_big);
imageViewSmallTop = (ImageView) itemView.findViewById(R.id.category_img_top);
imageViewSmallBottom = (ImageView) itemView.findViewById(R.id.category_img_bottom);
}
}
5. 实现商品分类
在首页的 Fragment 中声明 RecyclerView ,设置适配器,绑定数据,设置 RecyclerView 的 ItemDecoration 间隔线和 LayoutManager 为线性布局,完成设置就可以了。
public void initRecyclerView() {
recyclerCategory = (RecyclerView) view.findViewById(R.id.home_recycler_category);
List<HomeCategoryInfo> datas = new ArrayList<>(15);
HomeCategoryInfo category = new HomeCategoryInfo("热门活动", R.drawable.img_big_1, R.drawable.img_1_small1, R.drawable.img_1_small2);
datas.add(category);
category = new HomeCategoryInfo("有利可图", R.drawable.img_big_4, R.drawable.img_4_small1, R.drawable.img_4_small2);
datas.add(category);
category = new HomeCategoryInfo("品牌街", R.drawable.img_big_2, R.drawable.img_2_small1, R.drawable.img_2_small2);
datas.add(category);
category = new HomeCategoryInfo("金融街 包赚翻", R.drawable.img_big_1, R.drawable.img_3_small1, R.drawable.imag_3_small2);
datas.add(category);
category = new HomeCategoryInfo("超值购", R.drawable.img_big_0, R.drawable.img_0_small1, R.drawable.img_0_small2);
datas.add(category);
mAdatper = new HomeCategoryAdapter(datas);
recyclerCategory.setAdapter(mAdatper);
recyclerCategory.addItemDecoration(new DividerItemDecoration());
recyclerCategory.setLayoutManager(new LinearLayoutManager(this.getActivity()));
}
6. 效果图展示
运行代码,获取到最终效果,如下图所示。
上面的广告轮播在文章《商城项目实战 | 3.1 AndroidImageSlider 实现炫酷轮播广告》已经介绍了,下面的商品分类就是这次需要实现的。
1. Gradle 添加依赖
在 module 下的 build.gradle 文件下面添加对 RecyclerView 和 CardView 的依赖。
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.2.0'
testCompile 'junit:junit:4.12'
compile 'com.android.support:support-v4:25.2.0'
compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'com.android.support:cardview-v7:25.2.0'
}
2. 定义实体类
根据商品分类的效果展示,可以了解到实体类的属性有 title 、大图以及两张小图,所以定义实体类如下。
public class HomeCategoryInfo extends CategoryInfo {
private String name;//分类名称
private int imgBig;//大图
private int imgSmallTop;//上面的小图
private int imgSmallBottom;//下面的小图
public HomeCategoryInfo(String name, int imgBig, int imgSmallTop, int imgSmallBottom) {
this.name = name;
this.imgBig = imgBig;
this.imgSmallTop = imgSmallTop;
this.imgSmallBottom = imgSmallBottom;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImgBig() {
return imgBig;
}
public void setImgBig(int imgBig) {
this.imgBig = imgBig;
}
public int getImgSmallTop() {
return imgSmallTop;
}
public void setImgSmallTop(int imgSmallTop) {
this.imgSmallTop = imgSmallTop;
}
public int getImgSmallBottom() {
return imgSmallBottom;
}
public void setImgSmallBottom(int imgSmallBottom) {
this.imgSmallBottom = imgSmallBottom;
}
}
3. 布局设计
布局中有标题、大图和两张小图,而且第一项中是大图在右边,两张小图在左边,而第二项中是大图在左边,两张小图在右边,所以至少要设计两个布局文件,但是首先是要在首页 Fragment 中写入 RecyclerView 。
<android.support.v7.widget.RecyclerView
android:id="@+id/home_recycler_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
下面就是 item 项的布局设计了,需要有个布局文件,唯一的差别是图片的摆放左右有所不同,这里就展示大图在左边的 layout 文件了,大图在右边的可以直接仿照的写就行了。因为布局中的控件是一样的,所以 id 也就使用相同的就可以了。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#fff"
app:contentPadding="10dp"
app:cardCornerRadius="4dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/category_tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="热门活动"
android:textSize="20dp"
android:textColor="@color/black"
android:paddingTop="10dp"
/>
<View
style="@style/line_vertical"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"></View>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/category_img_big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<View
android:id="@+id/line"
style="@style/line_horizontal"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<ImageView
android:id="@+id/category_img_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<View
android:id="@+id/line2"
style="@style/line_vertical"
></View>
<ImageView
android:id="@+id/category_img_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
4. 定义 Adapter
列表 item 的布局文件已经写好了,接下来需要准备的就是适配器 Adapter 了。在定义的时候注意第一项中是大图在右边,两张小图在左边,而第二项中是大图在左边,两张小图在右边,所以需要判断下根据 position 的位置来确定布局的样式。定义的 Adapter 必须继承于 RecyclerView.Adapter,然后绑定布局和数据,具体代码如下。
private static int VIEW_TYPE_L=0;
private static int VIEW_TYPE_R=1;
private LayoutInflater mInflater;
private List<HomeCategoryInfo> mDatas;
public HomeCategoryAdapter(List<HomeCategoryInfo> datas){
mDatas = datas;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
mInflater = LayoutInflater.from(viewGroup.getContext());
if(type == VIEW_TYPE_R){
return new ViewHolder(mInflater.inflate(R.layout.recycler_item_even_layout,viewGroup,false));
}
return new ViewHolder(mInflater.inflate(R.layout.recycler_item_odd_layout,viewGroup,false));
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
HomeCategoryInfo category = mDatas.get(i);
viewHolder.textTitle.setText(category.getName());
viewHolder.imageViewBig.setImageResource(category.getImgBig());
viewHolder.imageViewSmallTop.setImageResource(category.getImgSmallTop());
viewHolder.imageViewSmallBottom.setImageResource(category.getImgSmallBottom());
}
@Override
public int getItemCount() {
return mDatas.size();
}
@Override
public int getItemViewType(int position) {
if(position % 2==0){
return VIEW_TYPE_R;
}
else return VIEW_TYPE_L;
}
static class ViewHolder extends RecyclerView.ViewHolder{
TextView textTitle;
ImageView imageViewBig;
ImageView imageViewSmallTop;
ImageView imageViewSmallBottom;
public ViewHolder(View itemView) {
super(itemView);
textTitle = (TextView) itemView.findViewById(R.id.category_tv_title);
imageViewBig = (ImageView) itemView.findViewById(R.id.category_img_big);
imageViewSmallTop = (ImageView) itemView.findViewById(R.id.category_img_top);
imageViewSmallBottom = (ImageView) itemView.findViewById(R.id.category_img_bottom);
}
}
5. 实现商品分类
在首页的 Fragment 中声明 RecyclerView ,设置适配器,绑定数据,设置 RecyclerView 的 ItemDecoration 间隔线和 LayoutManager 为线性布局,完成设置就可以了。
public void initRecyclerView() {
recyclerCategory = (RecyclerView) view.findViewById(R.id.home_recycler_category);
List<HomeCategoryInfo> datas = new ArrayList<>(15);
HomeCategoryInfo category = new HomeCategoryInfo("热门活动", R.drawable.img_big_1, R.drawable.img_1_small1, R.drawable.img_1_small2);
datas.add(category);
category = new HomeCategoryInfo("有利可图", R.drawable.img_big_4, R.drawable.img_4_small1, R.drawable.img_4_small2);
datas.add(category);
category = new HomeCategoryInfo("品牌街", R.drawable.img_big_2, R.drawable.img_2_small1, R.drawable.img_2_small2);
datas.add(category);
category = new HomeCategoryInfo("金融街 包赚翻", R.drawable.img_big_1, R.drawable.img_3_small1, R.drawable.imag_3_small2);
datas.add(category);
category = new HomeCategoryInfo("超值购", R.drawable.img_big_0, R.drawable.img_0_small1, R.drawable.img_0_small2);
datas.add(category);
mAdatper = new HomeCategoryAdapter(datas);
recyclerCategory.setAdapter(mAdatper);
recyclerCategory.addItemDecoration(new DividerItemDecoration());
recyclerCategory.setLayoutManager(new LinearLayoutManager(this.getActivity()));
}
6. 效果图展示
运行代码,获取到最终效果,如下图所示。
扫我”