天天看點

android支付寶首頁布局,類似支付寶首頁——RecycleView多布局結構實作

大家都知道,RecycleView預設隻能通過setLayoutManager()方法指定一種布局結構,那麼像支付寶首頁這樣複雜的多布局情況如何處理呢?在ListView中,我們也遇到過這種情況,是通過getItemViewType結合其他方法,通過判斷類型來加載不同的布局。在RecycleView中也同樣使用,今天我們主要介紹RecycleView多布局實作,其中布局嵌套了GridView,有些坑需要注意,避免陷入。

一、效果圖

廢話不多說,獻上效果圖。

android支付寶首頁布局,類似支付寶首頁——RecycleView多布局結構實作
android支付寶首頁布局,類似支付寶首頁——RecycleView多布局結構實作

從圖中可以看出,一共有三種布局樣式。第一種:頭布局,包含各種類型的新聞頻道。第二種布局:普通的新聞。第三種布局:多圖圖集新聞。

二、多布局實作的思路

步驟一、getItemViewType()方法判斷不同的布局,傳回判斷結果。

步驟二、建立不同的ViewHolder類,針對不同的布局類型,進行對應的布局内控件的初始化。

步驟三、onCreateViewHolder()方法根據第一步的判斷結果,得到viewType,根據viewType值,執行個體化不同類型的ViewHolder對象。

步驟四、onBindViewHolder()方法判斷holder所屬類型,進行相對應類型的布局内控件内容的指派。

以上就是實作多布局的思路,很簡單(可能描述不到位,不易了解),下面我們以代碼的形式更直覺的來了解具體步驟。

三、RecycleView多布局實作代碼

首先定義三種類型常量

//新聞模式

private static final int TYPE_SINGLE = 0;

//圖集模式

private static final int TYPE_MULTI = 1;

//頭布局模式

private static final int TYPE_HEADER = 2;

getItemViewType()方法判斷不同的布局,傳回判斷結果

@Override

public int getItemViewType(int position) {

//所有的新聞詳情資料,在第一個位置自己手動加入了一個假的新聞資料,把它的title設定為“頭布局”

NewsInfo info = list.get(position);

//識别出“頭布局”,則是第一個資料,把它歸于頭布局類型

if(info.getTitle().endsWith("頭布局")){

return TYPE_HEADER;

}

//有新聞具體内容,是普通新聞

if (!TextUtils.isEmpty(info.getDigest()))

{

return TYPE_SINGLE;

}

//其他情況,是圖集新聞

return TYPE_MULTI;

}

建立不同的ViewHolder類,針對不同的布局類型,進行對應的布局内控件的初始化。

省略了具體的初始化操作

public class SingleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

.......

.......

public SingleViewHolder(View itemView) {

super(itemView);

.......

.......

}

@Override

public void onClick(View view) {

Toast.makeText(context,"點選了",Toast.LENGTH_SHORT).show();

}

}

public class MultiViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

.......

.......

public MultiViewHolder(View itemView) {

super(itemView);

.......

.......

}

@Override

public void onClick(View view) {

Toast.makeText(context,"點選了",Toast.LENGTH_SHORT).show();

}

}

public class HeaderViewHolder extends RecyclerView.ViewHolder{

.......

.......

public HeaderViewHolder(View itemView) {

super(itemView);

.......

.......

}

}

onCreateViewHolder()方法根據第一步的判斷結果,得到viewType,根據viewType值,執行個體化不同類型的ViewHolder對象。

@Override

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

switch (viewType) {

case TYPE_SINGLE:

return new SingleViewHolder(inflater.inflate(R.layout.item_news, parent, false));

case TYPE_MULTI:

return new MultiViewHolder(inflater.inflate(R.layout.item_news_photo, parent, false));

case TYPE_HEADER:

return new HeaderViewHolder(inflater.inflate(R.layout.item_news_header,parent,false));

}

return null;

}

onBindViewHolder()方法判斷holder所屬類型,進行相對應類型的布局内控件内容的指派。

@Override

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

//設定不同的布局内控件的值

if (holder instanceof SingleViewHolder) {

setNormalItemValues((SingleViewHolder) holder,position);

}else if(holder instanceof MultiViewHolder){

setMultiItemValues((MultiViewHolder) holder,position);

}else{

setHeaderItemValues((HeaderViewHolder) holder);

}

}

針對不同類型,設定布局内控件的值的具體内容就不介紹了,比較繁多,下面有源碼連結。

由于本例中頭布局是個GridView,需要注意的一點是RecycleView中嵌套GridView會出現隻顯示一行的問題。下面給出具體解決方法:

在setHeaderItemValues((HeaderViewHolder) holder);中,主動測量出GridView的高度,并設定給布局。本例中預設GridView是兩行。

//解決GridView隻顯示一行的原因 主動設定GridView的高度

ViewGroup.LayoutParams params = holder.mGridView.getLayoutParams();

View view = mAdapter.getView(0, null, holder.mGridView);

view.measure(0,0);

int height =view.getMeasuredHeight();

int totalHeight = holder.mGridView.getVerticalSpacing() * 2 + height * 2;

params.height = totalHeight;

holder.mGridView.setLayoutParams(params);

源碼位址比較亂,直接看NewsFragment相關内容即可。