iOSのUITableViewと同様の行/セクションロジックの処理は、AndroidではiOSほど単純ではありませんが、RecyclerViewを使用すると、実行できることの柔軟性が大幅に向上します。
結局のところ、アダプタに表示しているビューのタイプを把握する方法がすべてです。それを理解したら、それは簡単に航行できるはずです(実際にはそうではありませんが、少なくともそれはソートされています)。
アダプターは、オーバーライドする必要がある2つのメソッドを公開します。
getItemViewType(int position)
このメソッドのデフォルト実装は常に0を返し、ビューのタイプが1つしかないことを示します。あなたのケースではそうではありませんので、どの行がどのビュータイプに対応するかを表明する方法を見つける必要があります。これを行とセクションで管理するiOSとは異なり、ここでは依存するインデックスが1つだけあり、開発者のスキルを使用して、位置がセクションヘッダーと相関しているとき、およびそれがいつ相関しているのかを知る必要があります。通常の行。
createViewHolder(ViewGroup parent, int viewType)
とにかくこのメソッドをオーバーライドする必要がありますが、通常、人々は単にviewTypeパラメータを無視します。ビューのタイプに応じて、適切なレイアウトリソースをインフレートし、それに応じてビューホルダーを作成する必要があります。RecyclerViewは、異なるビュータイプの衝突を回避する方法で、異なるビュータイプのリサイクルを処理します。
などのデフォルトのLayoutManagerの使用を計画している場合は、準備完了ですLinearLayoutManager
。独自のLayoutManager実装を作成することを計画している場合は、もう少し努力する必要があります。実際に操作する必要がある唯一のAPI findViewByPosition(int position)
は、特定の位置で特定のビューを提供するものです。このビューのタイプに応じてレイアウトを変えたいと思うので、いくつかのオプションがあります。
通常、ViewHolderパターンを使用するときは、ビューのタグをビューホルダーで設定します。実行時にレイアウトマネージャーでこれを使用して、これを表すフィールドをビューホルダーに追加することで、ビューのタイプを確認できます。
どの位置がどのビュータイプに相関するかを決定する関数が必要になるため、このメソッドを何らかの方法でグローバルにアクセスできるようにすることもできます(データを管理するシングルトンクラスの場合もあるでしょう)。位置。
ここにコードサンプルがあります:
// in this sample, I use an object array to simulate the data of the list.
// I assume that if the object is a String, it means I should display a header with a basic title.
// If not, I assume it's a custom model object I created which I will use to bind my normal rows.
private Object[] myData;
public static final int ITEM_TYPE_NORMAL = 0;
public static final int ITEM_TYPE_HEADER = 1;
public class MyAdapter extends Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE_NORMAL) {
View normalView = LayoutInflater.from(getContext()).inflate(R.layout.my_normal_row, null);
return new MyNormalViewHolder(normalView); // view holder for normal items
} else if (viewType == ITEM_TYPE_HEADER) {
View headerRow = LayoutInflater.from(getContext()).inflate(R.layout.my_header_row, null);
return new MyHeaderViewHolder(headerRow); // view holder for header items
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final int itemType = getItemViewType(position);
if (itemType == ITEM_TYPE_NORMAL) {
((MyNormalViewHolder)holder).bindData((MyModel)myData[position]);
} else if (itemType == ITEM_TYPE_HEADER) {
((MyHeaderViewHolder)holder).setHeaderText((String)myData[position]);
}
}
@Override
public int getItemViewType(int position) {
if (myData[position] instanceof String) {
return ITEM_TYPE_HEADER;
} else {
return ITEM_TYPE_NORMAL;
}
}
@Override
public int getItemCount() {
return myData.length;
}
}
これらのビューホルダーがどのように見えるかのサンプルを次に示します。
public MyHeaderViewHolder extends ViewHolder {
private TextView headerLabel;
public MyHeaderViewHolder(View view) {
super(view);
headerLabel = (TextView)view.findViewById(R.id.headerLabel);
}
public void setHeaderText(String text) {
headerLabel.setText(text);
}
}
public MyNormalViewHolder extends ViewHolder {
private TextView titleLabel;
private TextView descriptionLabel;
public MyNormalViewHolder(View view) {
super(view);
titleLabel = (TextView)view.findViewById(R.id.titleLabel);
descriptionLabel = (TextView)view.findViewById(R.id.descriptionLabel);
}
public void bindData(MyModel model) {
titleLabel.setText(model.getTitle());
descriptionLabel.setText(model.getDescription());
}
}
もちろん、このサンプルでは、この方法でアダプターを簡単に実装できる方法でデータソース(myData)を構築していることを前提としています。例として、名前のリストを表示するデータソースを構築する方法と、名前の最初の文字が変更されるたびにヘッダーがどのように構成されるかを示します(リストがアルファベット順であると想定)-連絡先と同様リストは次のようになります。
// Assume names & descriptions are non-null and have the same length.
// Assume names are alphabetized
private void processDataSource(String[] names, String[] descriptions) {
String nextFirstLetter = "";
String currentFirstLetter;
List<Object> data = new ArrayList<Object>();
for (int i = 0; i < names.length; i++) {
currentFirstLetter = names[i].substring(0, 1); // get the 1st letter of the name
// if the first letter of this name is different from the last one, add a header row
if (!currentFirstLetter.equals(nextFirstLetter)) {
nextFirstLetter = currentFirstLetter;
data.add(nextFirstLetter);
}
data.add(new MyModel(names[i], descriptions[i]));
}
myData = data.toArray();
}
この例はかなり具体的な問題を解決するためのものですが、これにより、リサイクラーでさまざまな行タイプを処理する方法の概要がわかり、ニーズに合わせて独自のコードで必要な調整を行えるようになることを願っています。