Skip to content

Instantly share code, notes, and snippets.

@yyaammaa
Last active December 8, 2016 09:08
Show Gist options
  • Save yyaammaa/8033421 to your computer and use it in GitHub Desktop.
Save yyaammaa/8033421 to your computer and use it in GitHub Desktop.
Butter Knifeを使ってListViewの複雑なHeaderをすっきり書く

Butter Knifeを使ってListViewの複雑なHeaderをすっきり書く

前提知識

問題

  • ListViewに複雑なHeader (もしくはFooter) を置きたい
  • が、Activity/Fragmentに直接書いてしまうと見づらくなる、他の場所で再利用したいときも大変

そこで

  • ViewHolderパターン的なものをつかってHeaderをクラスにする
  • なおかつButter Knifeを使ってすっきり書く

サンプル

  • TextViewが2つ、Buttonが3つあるHeader
    • TextViewの中身はあとで更新したりしたい(サーバから文字列を取得して表示したり)
    • Buttonのクリックイベントを取得して何かしたい
public class ComplexHeaderHolder {

  public interface HeaderListener {
    public void onLeftButtonClick();
    public void onMiddleButtonClick();
    public void onRightButtonClick();
  }

  @InjectView(R.id.header_title)
  public TextView title;
  
  @InjectView(R.id.header_description)
  public TextView description;

  public View view;

  private HeaderListener mListener;

  public ComplexHeaderHolder(LayoutInflater inflater) {
    view = inflater.inflate(R.layout.header, null);
    ButterKnife.inject(this, view);
  }

  /** Listenerをセットする */
  public void setListener(HeaderListener listener) {
    mListener = listener;
  }

  @OnClick(R.id.header_button_left)
  void onLeftButtonClick() {
    if (mListener != null) {
      mListener.onLeftButtonClick();
    }
  }

  @OnClick(R.id.header_button_middle)
  void onMiddleButtonClick() {
    if (mListener != null) {
      mListener.onMiddleButtonClick();
    }
  }

  @OnClick(R.id.header_button_right)
  void onRightButtonClick() {
    if (mListener != null) {
      mListener.onRightButtonClick();
    }
  }

}

Activity/Fragment側の実装

public class MainFragment extends Fragment
    implements ComplexHeaderHolder.HeaderListener {

  @InjectView(R.id.fragment_listview)
  ListView mListView;

  private ComplexHeaderHolder mHeaderHolder;

  /** onCreateViewなどでのViewの初期化 */
  private void setUpViews() {

    // … 他のViewの初期化処理 …

    // Headerをつくる
    mHeaderHolder = new ComplexHeaderHolder(inflater);

    // Listenerをセットする
    mHeaderHolder.setListener(this);
    
    // ListViewにHeaderを追加する
    mListView.addHeaderView(mHeaderHolder.view, null, false);

    mListView.setAdapter(adapter);
  }

  /** Headerのテキストをサーバから取得して表示したり */
  private void setHeaderText() {
    mHeaderHolder.title.setText("title");
    mHeaderHolder.description.setVisibility(View.GONE);
  }

  @Override
  public void onLeftButtonClick() {
    // Headerの左ボタンがクリックされたとき    
  }

  @Override
  public void onMiddleButtonClick() {
    // Headerの中ボタンがクリックされたとき    
  }

  @Override
  public void onRightButtonClick() {
    // Headerの右ボタンがクリックされたとき    
  }

}

これで、Activity/Fragment側がすっきりして、ComplexHeaderHolderも他のActivity/Fragmentで簡単に再利用できるようになった。

FAQ

ComplexHeaderHolderってカスタムのViewGroupでもいいんじゃないの?

いいと思います。

ComplexHeaderHolderってFragmentでもいいんじゃないの?

いいと思います。が、Fragmentにするのはなにか違和感があるような気がしなくもない

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment