本文為菜鳥(niǎo)窩作者劉婷的連載。”商城項(xiàng)目實(shí)戰(zhàn)”系列來(lái)聊聊仿”京東淘寶的購(gòu)物商城”如何實(shí)現(xiàn)。
還記得商城項(xiàng)目的首頁(yè)模塊嗎,上面是滾動(dòng)的炫酷輪播廣告,下面是商品活動(dòng)分類,不記得話就看下效果圖,就明白了。

在下面部分的商品活動(dòng)分類中,點(diǎn)擊任意商品項(xiàng),就可以跳轉(zhuǎn)到活動(dòng)商品列表頁(yè)面去,先來(lái)看下活動(dòng)商品列表的界面。

這個(gè)界面很簡(jiǎn)單,上部三個(gè)分類,為默認(rèn)、價(jià)格和銷量,然后就是顯示總共多少商品數(shù),以及一個(gè)顯示商品的列表,這個(gè)界面的實(shí)現(xiàn),也就是本文的關(guān)鍵,使用 TabLayout 來(lái)實(shí)現(xiàn)商品排序的功能。
TabLayout 的介紹
TabLayout 是 Android Support Design 中的其中一個(gè)控件,有了它,可以輕松實(shí)現(xiàn)滑動(dòng)標(biāo)簽頁(yè)的效果,也是受到廣大開(kāi)發(fā)者的喜愛(ài)。
1. TabLayout 的相關(guān)屬性
要了解 TabLayout 的相關(guān)屬性,就要知道它的相應(yīng)的 Style 源碼,開(kāi)發(fā)者可以通過(guò)自定義 Style 來(lái)改變 TabLayout 的樣式和屬性。
<style name="Widget.Design.TabLayout" parent="Base.Widget.Design.TabLayout">
<item name="tabGravity">fill</item>
<item name="tabMode">fixed</item>
</style>
<style name="Base.Widget.Design.TabLayout" parent="android:Widget">
<item name="tabMaxWidth">@dimen/design_tab_max_width</item>
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">?attr/selectableItemBackground</item>
<item name="tabTextAppearance">@style/TextAppearance.Design.Tab</item>
<item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>
TabLayout 的主要組成就是 Tab,所以它相關(guān)的屬性也主要是 Tab 的屬性。從上面的源碼中可以看下, TabLayout 的 Tab 的背景、最大寬度、位置模式等都是可以通過(guò)自定義來(lái)調(diào)整和修改的,十分靈活。
2. TabLayout 的基本用法
TabLayout 的主要組成是 Tab,它的基本用法也就和 Tab 有關(guān)了,也很簡(jiǎn)單,但是記住 TabLayout 是 Android Support Design 中的控件,所以必須要添加對(duì) Android Support Design 的依賴,這里是在 build.gradle 中添加依賴。
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'
compile 'com.android.support:design:25.2.0'
}
然后先在 xml 文件中添加 TabLayout。
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</android.support.design.widget.TabLayout>
最后就是要添加 Tab 以及事件的監(jiān)聽(tīng),先來(lái)看下 Tab 的添加。
TabLayout.Tab tab = tabLayout.newTab();
tab.setText(getResources().getString(R.string.default_campaign));
tab.setTag(TAG_DEFAULT);
tabLayout.addTab(tab);
先 new 一個(gè) Tab ,然后給對(duì)應(yīng)的 Tab 添加文字、tag等屬性,最后添加到 TabLayout 中。
而至于 TabLayout 的監(jiān)聽(tīng)事件就更加簡(jiǎn)單了,直接調(diào)用 API 接口就好,這里就展示下最常用的 Tab 選擇事件監(jiān)聽(tīng)。
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
//Tab 被選擇時(shí)的處理
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
//Tab 未被選擇的處理
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
//Tab 重新被選擇的處理
}
});
已經(jīng)對(duì) TabLayout 做了簡(jiǎn)單的介紹了,也已經(jīng)對(duì) TabLayout 有了一定的認(rèn)識(shí),言歸正傳,下面開(kāi)始詳細(xì)講解如何使用 TabLayout 實(shí)現(xiàn)商品排序功能。
TabLayout 實(shí)現(xiàn)商品排序功能
活動(dòng)商品列表界面中商品會(huì)根據(jù)上面的默認(rèn)、銷售和價(jià)格三個(gè) Tab 的選擇情況來(lái)確定怎樣的排序方法,然后將商品展示在列表中,同時(shí)列表上面的還會(huì)顯示總的商品數(shù)量,如何實(shí)現(xiàn)呢?往下看。
1. Gradle 添加依賴
既然使用了 TabLayout,那么首先就是要添加 Android Support Design 的依賴,在 build.gradle 中添加。
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'
compile 'com.android.support.constraint:constraint-layout:1.0.1'
testCompile 'junit:junit:4.12'
compile 'com.daimajia.slider:library:1.1.5@aar'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.nineoldandroids:library:2.4.0'
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'
compile 'com.squareup.okhttp3:okhttp:3.6.0'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.github.d-max:spots-dialog:0.7'
compile 'com.facebook.fresco:fresco:1.2.0'
compile 'com.cjj.materialrefeshlayout:library:1.3.0'
compile 'org.xutils:xutils:3.5.0'
compile 'com.android.support:design:25.2.0'
}
商城項(xiàng)目開(kāi)發(fā)到這里,build.gradle 中依賴也越來(lái)越多了。
2. 添加權(quán)限
權(quán)限的添加就不用多解釋了啊,這里是網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求,自然要網(wǎng)絡(luò)權(quán)限,加上圖片的顯示需要緩存,所以需要的權(quán)限也就是網(wǎng)絡(luò)權(quán)限和寫的權(quán)限。
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
權(quán)限加好了,就可以開(kāi)始動(dòng)工設(shè)計(jì)界面了。
3. 自定義 TabLayout 的樣式
自定義 TabLayout 的 Style,命名為 customTabLayout,擴(kuò)展于 Widget.Design.TabLayout 的 Style。
<style name="customTabLayout" parent="Widget.Design.TabLayout">
<!--<item name="tabMaxWidth">@dimen/tab_max_width</item>-->
<item name="tabIndicatorColor">#eb4f38</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">@color/white</item>
<item name="tabTextAppearance">@style/customTabTextAppearance</item>
<item name="tabSelectedTextColor">#eb4f38</item>
</style>
TabLayout 的自定義樣式可以根據(jù)實(shí)際情況進(jìn)行調(diào)整。
4. 添加活動(dòng)商品主界面布局
上文效果圖中可以看到的是上部的 Toolbar、可滑動(dòng)的標(biāo)簽頁(yè)、顯示商品總數(shù)的文本以及顯示商品的列表,這個(gè)列表也要可以下拉刷新和上拉加載更多。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_color">
<com.liuting.cniao_shop.widget.CNiaoToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:isShowSearchView="false"
app:navigationIcon="@mipmap/ic_back"
app:contentInsetEnd="56dp"
app:title="@string/product_list">
</com.liuting.cniao_shop.widget.CNiaoToolbar>
<android.support.design.widget.TabLayout
android:id="@+id/ware_tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/customTabLayout"
app:tabGravity="fill"
app:tabMode="fixed"
>
</android.support.design.widget.TabLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="30dp"
android:gravity="center_vertical"
android:padding="5dp"
android:background="@color/gold_yellow">
<TextView
android:id="@+id/ware_tv_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/gray"/>
</LinearLayout>
<com.cjj.MaterialRefreshLayout
android:id="@+id/ware_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:overlay="false"
app:wave_show="false"
app:wave_color="#90ffffff"
app:progress_colors="@array/material_colors"
app:wave_height_type="higher"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/ware_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</com.cjj.MaterialRefreshLayout>
</LinearLayout>
因?yàn)榱斜硪惨梢韵吕⑿潞蜕侠虞d更多,所以就還是使用之前的 MaterialRefreshLayout 下拉刷新和上拉加載更多的控件。
而商品列表的 item 布局和之前寫好的熱門商品列表 item 布局是一樣的,另外商品屬性也一致,這里就直接請(qǐng)參考文章《商城項(xiàng)目實(shí)戰(zhàn) | 8.2 SwipeRefreshLayout 實(shí)現(xiàn)可以下拉刷新和加載更多的熱門商品列表》,這里就不多廢話了。
5. 初始化 TabLayout
在活動(dòng)商品列表的 Activity 中初始化 TabLayout,也就是要初始化 Tab。
TabLayout.Tab tab = tabLayout.newTab();
tab.setText("默認(rèn)");
tab.setTag(TAG_DEFAULT);
tabLayout.addTab(tab);
tab = tabLayout.newTab();
tab.setText("價(jià)格");
tab.setTag(TAG_PRICE);
tabLayout.addTab(tab);
tab = tabLayout.newTab();
tab.setText("銷量");
tab.setTag(TAG_SALE);
tabLayout.addTab(tab);
總共有默認(rèn)、價(jià)格和銷量三個(gè) Tab, new 好后,添加到 TabLayout,初始化就寫好了。
6. 添加事件監(jiān)聽(tīng)
選擇上部不同的 Tab 項(xiàng),下面的商品列表就會(huì)相應(yīng)改變排序,就要為 TabLayout 添加 setOnTabSelectedListener() Tab 選擇事件監(jiān)聽(tīng)。
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
orderBy = (int) tab.getTag();
pager.putParam("orderBy", orderBy);
pager.refresh();
recyclerView.scrollToPosition(0);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
//Tab 未被選擇的處理
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
//Tab 重新被選擇的處理
}
});
orderBy 為排序方式,pager 則是分頁(yè)工具類,在文章《商城項(xiàng)目實(shí)戰(zhàn) | 15.1 實(shí)現(xiàn)分頁(yè)工具類的封裝》中已經(jīng)有詳細(xì)說(shuō)明,recyclerView 則是列表。這里實(shí)現(xiàn)的就是改變排序方式,然后刷新列表,并且列表滑動(dòng)到最頂部。
效果圖
碼完了所有的代碼,最后就是看效果的時(shí)候啊。

效果我們基本上都已經(jīng)實(shí)現(xiàn)了,不過(guò)有大家應(yīng)該也注意到了在最上面 Toolbar 的右側(cè),也就是標(biāo)題的右側(cè)有個(gè)網(wǎng)格的圖標(biāo),這個(gè)圖標(biāo)是用來(lái)干什么的呢?那是用來(lái)實(shí)現(xiàn)商品列表 list 和 grid 模式切換的,如何實(shí)現(xiàn)呢?請(qǐng)繼續(xù)關(guān)注,在下篇文章中將著重介紹。
擼這個(gè)項(xiàng)目的一半,你就是大神 , 戳http://mp.weixin.qq.com/s/ZagocTlDfxZpC2IjUSFhHg