作電商APP的朋友應該都會遇到訂單列表頁面這個需求,相似於下圖這個需求。android
有些朋友可能會使用addView的方式來實現這個需求,不過在View到達一個數量級的時候,整個頁面會很是卡。這個需求其實能夠用一個RecyclerView中getItemViewType()這個函數實現這一個需求。簡單來講就是將一個二維數組變成一維數組,這樣就能夠直接傳入Adapter中使用,咱們再根據數據結構類型的不用來判斷加載哪種Item。git
首先咱們要將這個Item進行切分,劃分爲3個部分,以下圖所示:github
根據頁面切割部分編寫各自對應的layout文件,後端
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="@drawable/bg_item_header"
android:layout_height="30dp">
<ImageView
android:id="@+id/iv_shop_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginStart="8dp"
android:src="@drawable/icon_tmall"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_shop_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="8dp"
android:layout_toEndOf="@id/iv_shop_icon"
android:drawableEnd="@drawable/icon_enter"
android:drawablePadding="8dp"
android:textColor="@color/text_main"
android:textSize="14sp"
android:textStyle="bold"
tools:text="Android死丟丟旗艦店" />
<TextView
android:id="@+id/tv_transaction_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="8dp"
android:textColor="@color/colorPrimary"
android:textSize="14sp"
android:textStyle="bold"
tools:text="交易成功" />
</RelativeLayout>
複製代碼
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#fff">
<ImageView
android:id="@+id/iv_goods_icon"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginStart="8dp"
tools:ignore="ContentDescription"
tools:src="@drawable/icon_default_goods" />
<TextView
android:id="@+id/tv_goods_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="12dp"
android:layout_toEndOf="@id/iv_goods_icon"
android:maxWidth="230dp"
android:maxLines="2"
android:textColor="@color/text_main"
android:textSize="16sp"
tools:text="垃圾Android死丟丟毀我青春" />
<TextView
android:id="@+id/tv_goods_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginTop="12dp"
android:layout_marginEnd="8dp"
android:maxWidth="64dp"
android:textColor="@color/text_main"
android:textSize="16sp"
tools:ignore="RelativeOverlap"
tools:text="¥499.00" />
<TextView
android:id="@+id/tv_goods_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_goods_price"
android:layout_alignParentEnd="true"
android:layout_marginEnd="8dp"
android:textColor="@color/text_second"
android:textSize="16sp"
tools:text="x1" />
</RelativeLayout>
複製代碼
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_item_footer">
<TextView
android:id="@+id/tv_total_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
tools:text="共兩件商品 合計: ¥999.00" />
<Button
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_below="@id/tv_total_price"
android:layout_alignParentEnd="true"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/bg_button_main"
android:text="確認收貨"
android:textColor="#fff" />
</RelativeLayout>
複製代碼
在界面切割完成之後,咱們也要根據頁面切分的狀況進行後端返回JSON數據的封裝,將二維數組變成一維數組。數組
通常服務端返回數據的數據結構以下圖左所示,須要將圖左的數據結構轉爲右邊這種給RecyclerView使用:數據結構
具體代碼實現(類OrderListDataHelper)ide
public static List<Object> getDataAfterHandle(List<OrderListModel.RecordBean> resultList) {
// 得到服務端返回Json實體
List<Object> dataList = new ArrayList<>();// 新建單鏈表
OrderListHeaderModel orderHeaderModel = null;
OrderListContentModel orderContentModel = null;
OrderListFooterModel orderFooterModel = null;
//遍歷每一張訂單
for (OrderListModel.RecordBean recordBean : resultList) {
//設置item頭部訂單狀態
orderHeaderModel = new OrderListHeaderModel();
//TODO 設置數據
dataList.add(orderHeaderModel);
//設置item訂單商品列表
for (ProductListModel productListBean : recordBean.getProductList()) {
orderContentModel = new OrderListContentModel();
//TODO 設置數據
dataList.add(orderContentModel);
}
//設置item訂單尾部信息
orderFooterModel = new OrderListFooterModel();
//TODO 設置數據
dataList.add(orderFooterModel);
}
// 返回封裝好的單鏈表
return dataList;
}
複製代碼
目前使用的是原生未封裝的Adapter,更簡潔的使用方法能夠了解一下BaseRecyclerViewAdapterHelper,使用起來更方便喲,在商品列表須要多類型Item的話也能夠參考他的Demo,寫的很完美。函數
在Adapter中,咱們首先要複寫getItemCount方法:spa
@Override
public int getItemCount() {
return data != null ? data.size() : 0 ;
}
複製代碼
其次複寫getItemViewType方法code
@Override
public int getItemViewType(int position) {
if (data.get(position) instanceof OrderListHeaderModel) {// 判斷數據類型是否爲頭部Item
return ITEM_HEADER;
} else if (data.get(position) instanceof OrderListContentModel) {// 判斷數據類型是否爲內容Item
return ITEM_CONTENT;
} else if (data.get(position) instanceof OrderListFooterModel) {// 判斷數據類型是否爲尾部Item
return ITEM_FOOTER;
}
return ITEM_CONTENT;// 默認返回內容Item
}
複製代碼
複寫onCreateViewHolder方法,將view與viewType對應
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == ITEM_HEADER) {// 返回訂單頭部view
view = LayoutInflater.from(mContext).inflate(R.layout.mallmodule_item_order_header, parent, false);
return new OrderViewHolderHeader(view);
} else if (viewType == ITEM_CONTENT) {// 返回訂單商品列表view
view = LayoutInflater.from(mContext).inflate(R.layout.mallmodule_item_order_goods, parent, false);
return new OrderViewHolderContent(view);
} else if (viewType == ITEM_FOOTER) {// 返回訂單尾部view
view = LayoutInflater.from(mContext).inflate(R.layout.mallmodule_item_order_footer, parent, false);
return new OrderViewHolderFooter(view);
}
// 默認爲訂單商品列表view
return new OrderViewHolderContent(LayoutInflater.from(mContext).inflate(R.layout.mallmodule_item_order_goods, parent, false));
}
複製代碼
複寫onBindViewHolder方法,設置Model數據到View
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
if (holder instanceof OrderViewHolderHeader) {// 訂單頭部View數據設置
final OrderListHeaderModel orderHeaderModel = (OrderListHeaderModel) data.get(position);
final OrderViewHolderHeader viewHolderHeader = (OrderViewHolderHeader) holder;
// TODO 設置Model數據到View
} else if (holder instanceof OrderViewHolderContent) {// 訂單商品View數據設置
final OrderListContentModel orderContentModel = (OrderListContentModel) data.get(position);
final OrderViewHolderContent viewHolderContent = (OrderViewHolderContent) holder;
// TODO 設置Model數據到View
}
} else if (holder instanceof OrderViewHolderFooter) {// 訂單尾部View數據設置
final OrderListFooterModel orderFooterModel = (OrderListFooterModel) data.get(position);
final OrderViewHolderFooter viewHolderFooter = (OrderViewHolderFooter) holder;
// TODO 設置Model數據到View
}
}
複製代碼
週末補 (無限火力連跪的話)。