LoginSignup
6
7

More than 5 years have passed since last update.

RecyclerViewにヘッダーとフッターを付けたかった時に作った物のご紹介

Last updated at Posted at 2017-05-03

こんにちは。
こういう物は初めて書くので、勝手がわかりませんがよろしくお願いします。

あらすじ

AndroidアプリでListViewを使ってた

CoordinatorLayoutを使いたい

RecyclerView使おう

ヘッダーとフッターがパッと付けれない

ヘッダーとフッターを付けれるようにAdapter作った

この時に作ったAdapterを今回ご紹介します。(GitHubに置いてみました。
誰かのお役にたてればと。(もう既にあるのかな)
おかしいところあったらごめんなさい。:bow_tone1:

作ったAdapterの使い方

// 使いたいアダプタを作る
MyAdapter adapter = new MyAdapter();

// PaneRecyclerViewAdapter作る
PaneRecyclerViewAdapter paneRecyclerViewAdapter = new PaneRecyclerViewAdapter(adapter); // アダプタあげる

// GridViewならLayoutManagerあげる
//paneRecyclerViewAdapter.setGridLayoutManager(gridLayoutManager);

// ヘッダーとフッターのビューをあげる
paneRecyclerViewAdapter.setHeaderView(headerView);
paneRecyclerViewAdapter.setFooterView(footerView);

// RecyclerViewにPaneRecyclerVieAdapterをあげる
recyclerView.setAdapter(paneRecyclerViewAdapter);

動きを軽く解説

コンストラクタでメインで動くアダプタをもらいます。
基本こいつに横流しで動いてもらいます。

public PaneRecyclerViewAdapter(RecyclerView.Adapter adapter) {
    mAdapter = adapter;
}

適当に種類を仕分けします。

@Override
public int getItemViewType(int position) {
    if(isHeader(position)) {
        return ITEM_VIEW_TYPE_HEADER;
    }
    if(isFooter(position)) {
        return ITEM_VIEW_TYPE_FOOTER;
    }

    return ITEM_VIEW_TYPE_ITEM;
}

private boolean isHeader(int position) {
    return mHeaderView != null && position == 0;
}

private boolean isFooter(int position) {
    int extraCount = mHeaderView != null ? 1 : 0;
    return mFooterView != null && position == mAdapter.getItemCount() + extraCount;
}

アイテム数はヘッダーとフッターの個数を足して返します。

@Override
public int getItemCount() {
    int extraCount = 0;
    if(mHeaderView != null) extraCount += 1;
    if(mFooterView != null) extraCount += 1;
    return mAdapter.getItemCount() + extraCount;
}

普通のアイテムのViewHolderは貰ったAdapterに作らせます。

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if(viewType == ITEM_VIEW_TYPE_HEADER) {
        return new ViewHolder(mHeaderView);
    }

    if(viewType == ITEM_VIEW_TYPE_FOOTER) {
        return new ViewHolder(mFooterView);
    }

    RecyclerView.ViewHolder viewHolder = mAdapter.onCreateViewHolder(parent, viewType);
    return new ViewHolder(viewHolder);
}

ちなみに、PaneRecyclerのViewHolderは以下の感じです。
普通アイテムは生のViewHolder型でとっておいて、必要になったら渡します。
HeaderやFooterは既にViewなので横流しの親まかせです。

static class ViewHolder extends RecyclerView.ViewHolder {
    private RecyclerView.ViewHolder mItemViewHolder;

    ViewHolder(View itemView) {
        super(itemView);
    }

    ViewHolder(RecyclerView.ViewHolder viewHolder) {
        super(viewHolder.itemView);
        mItemViewHolder = viewHolder;
    }

    RecyclerView.ViewHolder getItemViewHolder() {
        return mItemViewHolder;
    }
}

onBindも普通のアイテムはもらったAdapter任せです。
HeaderFooterはやること無いから何もしないでいい、はず

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    if(isHeader(position)) return;
    if(isFooter(position)) return;
    int extraCount = mHeaderView != null ? 1 : 0;
    mAdapter.onBindViewHolder(holder.getItemViewHolder(), position - extraCount);
}

GridLayoutの時に、HeaderFooterは横いっぱいに居て欲しいので、SpanSizeLookup?で設定するみたいです。
Linearはみんな横いっぱいなので何もしなくても良いっぽいです。
簡単に設定できるようにと中でやってますが、外で設定したい場合はそうしてもらっても大丈夫です。(下に用意したgetSpanSize使えば外でもできる、はず)

public void setGridLayoutManager(GridLayoutManager gridLayoutManager) {
    mSpanCount = gridLayoutManager.getSpanCount();
    gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            return PaneRecyclerViewAdapter.this.getSpanSize(position);
        }
    });
}
public int getSpanSize(int position) {
    if(isHeader(position) || isFooter(position)) {
        return mSpanCount;
    }
    return 1;
}

おわり

難しいことはして無いはずです。
が、当時はヒイヒイ言いながら作ってました。
何かありましたら教えてください。
失礼します。:walking_tone1:

Github

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7