本文為菜鳥窩作者劉婷的連載。”商城項(xiàng)目實(shí)戰(zhàn)”系列來聊聊仿”京東淘寶的購物商城”如何實(shí)現(xiàn)。
這篇文章是接著上篇文章《商城項(xiàng)目實(shí)戰(zhàn) | 16.1 TabLayout 實(shí)現(xiàn)商品排序功能》的,本文將著重介紹如何輕松商品列表 list 和 grid 模式切換,先看實(shí)現(xiàn)效果吧。

大家一定很奇怪,為什么商品列表 list 和 grid 模式切換要特別寫一篇文章來講呢?因?yàn)樾【幬矣龅娇恿耍恢揽吹奖疚牡母魑皇欠裼型瑯拥慕?jīng)歷啊,下面就詳細(xì)說說怎么回事吧。
RecyclerView 的 notify 的坑
RecyclerView 是 ListView 和 GridView 的新的列表控件,意在代替 ListView 和 GridView,它有很多的優(yōu)點(diǎn),不必小編我來多說了,誰用誰知道啊,但是小編在使用 RecyclerView 的自帶的 notifyItemRangeChanged(int positionStart, int itemCount) 和 notifyDataSetChanged() 想要來實(shí)現(xiàn)商品列表 list 和 grid 模式切換時(shí),卻不小心掉坑里了。
下面是我最開始實(shí)現(xiàn)商品列表 list 和 grid 模式切換的過程。
1. 設(shè)置list 和 grid 兩種模式
既然需要切換兩種模式,自然需要標(biāo)志來標(biāo)識(shí)兩種模式。
public static final int ACTION_LIST=1;
public static final int ACTION_GIRD=2;
ACTION_LIST 是 list 列表模式,ACTION_GIRD 是 grid 模式。
2. Adapter 中添加刷新布局的方法
在商品列表的 Adapter 中添加布局刷新的方法,為之后的模式切換時(shí)調(diào)用。
public void resetLayout(int layoutId){
this.layoutResId = layoutId;
notifyItemRangeChanged(0,getDatas().size());
}
layoutResId 為 item 項(xiàng)的布局 id,getDatas() 方法是用來獲取列表所有的數(shù)據(jù) list 的,簡(jiǎn)單來看,這個(gè)方法的作用就是重置布局 id,也就是重置布局,然后調(diào)用 notifyItemRangeChanged(int positionStart, int itemCount) 方法來刷新布局。
3. 添加模式切換方法
private void changeMode(View v){
int action = (int) v.getTag();
if(ACTION_LIST == action){
mToolbar.setRightButtonIcon(R.drawable.icon_list_32);
mToolbar.getRightButton().setTag(ACTION_GIRD);
mWaresAdapter.resetLayout(R.layout.template_grid_wares);
mRecyclerview_wares.setLayoutManager(new GridLayoutManager(this,2));
}
else if(ACTION_GIRD == action){
mToolbar.setRightButtonIcon(R.drawable.icon_grid_32);
mToolbar.getRightButton().setTag(ACTION_LIST);
mWaresAdapter.resetLayout(R.layout.template_hot_wares);
mRecyclerview_wares.setLayoutManager(new LinearLayoutManager(this));
}
}
上面的代碼也很好理解,根據(jù)當(dāng)前的模式進(jìn)行切換操作,比如說當(dāng)前是 list 模式,則要修改 Toolbar 上面的圖標(biāo)為 list 的圖標(biāo),然后修改當(dāng)前模式為 ACTION_GIRD,調(diào)用前面在 Adapter 中寫好的刷新布局的方法 resetLayout(int layoutId),并且設(shè)置列表的 LayoutManager 為網(wǎng)格,也就是列表為網(wǎng)格模式,而當(dāng)前是 grid 模式時(shí)同理。
4. 效果圖
運(yùn)行代碼,獲取效果圖,初始的 list 模式?jīng)]有任何的問題,但是隨后進(jìn)行 grid 網(wǎng)格模式切換時(shí)就出錯(cuò)了,效果如下。

這是在模擬器上面運(yùn)行的情況,使用 notifyItemRangeChanged(int positionStart, int itemCount) 刷新布局看來是不行啊,隨后改用 notifyDataSetChanged() 方法來刷新,發(fā)現(xiàn)還是這樣,于是再多次嘗試之后,選擇了重置 Adapter。
輕松實(shí)現(xiàn)商品列表 list 和 grid 模式切換
在上面的方法失敗后,我改用了其他的辦法,最終選擇了重置 Adapter,那就是每次都要重新 new 一下 Adapter,這個(gè)辦法雖然不是很完美,但是實(shí)現(xiàn)的效果不錯(cuò),如果有更好的方法的話,歡迎一起討論。
1. 重置 Adapter
使用 RecyclerView 自帶的 notifyItemRangeChanged(int positionStart, int itemCount) 刷新方法雖然簡(jiǎn)單,但是在實(shí)際的使用過程中在數(shù)據(jù)量較大時(shí)一般都會(huì)使用 View 重用來解決滑動(dòng)卡頓的問題,所以即使刷新了,也還是會(huì)存在所謂的 View 緩沖,所以最好是重新 new 一下 Adapter 吧。
private void resetAdapter(List datas) {
if (ACTION_GIRD == (int) toolbar.getRightButton().getTag()) {
mWaresAdapter = new HWAdapter(this, datas, R.layout.grid_item_wares_layout);
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
recyclerView.setItemAnimator(new DefaultItemAnimator());
} else if (ACTION_LIST == (int) toolbar.getRightButton().getTag()) {
mWaresAdapter = new HWAdapter(this, datas, R.layout.recycler_item_wares_layout);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
}
if(mWaresAdapter == null){
recyclerView.addItemDecoration(new WareItemDecoration(this, WareItemDecoration.VERTICAL_LIST));
}
recyclerView.setAdapter(mWaresAdapter);
}
根據(jù)目前的模式狀態(tài),重新 new 適配器,同時(shí)重置布局和設(shè)置 RecyclerView 的布局排列方式。
2. 修改模式切換方法
修改之前的模式切換方法,在點(diǎn)擊圖標(biāo)時(shí),調(diào)用 resetAdapter(List datas) 來重置適配器。 Adapter。
private void changeMode(View v){
int action = (int) view.getTag();
if (ACTION_LIST == action) {//列表模式下
toolbar.setRightButtonIcon(R.mipmap.ic_list);
toolbar.getRightButton().setTag(ACTION_GIRD);
pager.refresh();
recyclerView.scrollToPosition(0);
} else if (ACTION_GIRD == action) {//網(wǎng)格模式下
toolbar.setRightButtonIcon(R.mipmap.ic_grid);
toolbar.getRightButton().setTag(ACTION_LIST);
pager.refresh();
recyclerView.scrollToPosition(0);
}
}
根據(jù)不同的模式下,對(duì)商品列表進(jìn)行 list 模式和 grid 模式的切換。
3. 效果圖
修改代碼之后,運(yùn)行效果得到如下圖所示。

搗鼓了一下,最終還是實(shí)現(xiàn)了商品列表 list 和 grid 模式切換,個(gè)人建議,Adapter 的 notify 方法還是需要一些完善的,所以在實(shí)際開發(fā)中還是盡量少通過這種來對(duì)布局刷新,對(duì)于實(shí)現(xiàn)商品列表 list 和 grid 模式切換,如果有更好的方法的話,請(qǐng)指教。
擼這個(gè)項(xiàng)目的一半,你就是大神 , 戳http://mp.weixin.qq.com/s/ZagocTlDfxZpC2IjUSFhHg