Created
May 12, 2016 13:03
-
-
Save hoshi-takanori/c43b6527c6f505e675ae8e6b0138d2f4 to your computer and use it in GitHub Desktop.
RecyclerView with sections.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.recyclertest; | |
import android.os.Bundle; | |
import android.support.v7.app.AppCompatActivity; | |
import android.support.v7.widget.GridLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class MainActivity extends AppCompatActivity { | |
private RecyclerView recyclerView; | |
private GridLayoutManager gridLayoutManager; | |
private SectionAdapter sectionAdapter; | |
private SampleSubAdapter subAdapter; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
recyclerView = (RecyclerView) findViewById(R.id.recycler_view); | |
recyclerView.setHasFixedSize(true); | |
gridLayoutManager = new GridLayoutManager(this, 2); | |
recyclerView.setLayoutManager(gridLayoutManager); | |
List<SampleSubAdapter.Section> data = new ArrayList<>(); | |
for (int i = 0; i < 5; i++) { | |
List<String> items = new ArrayList<>(); | |
for (int j = 0; j < 10; j++) { | |
items.add("Item " + (i + 1) + "-" + (j + 1)); | |
} | |
data.add(new SampleSubAdapter.Section("Section #" + (i + 1), items)); | |
} | |
subAdapter = new SampleSubAdapter(this, data, 2); | |
sectionAdapter = new SectionAdapter(subAdapter); | |
recyclerView.setAdapter(sectionAdapter); | |
gridLayoutManager.setSpanSizeLookup(sectionAdapter.new SpanSizeLookup()); | |
} | |
@Override | |
public boolean onCreateOptionsMenu(Menu menu) { | |
menu.add(Menu.NONE, 1, Menu.NONE, "1 column"); | |
menu.add(Menu.NONE, 2, Menu.NONE, "2 columns"); | |
menu.add(Menu.NONE, 3, Menu.NONE, "3 columns"); | |
menu.add(Menu.NONE, 4, Menu.NONE, "4 columns"); | |
menu.add(Menu.NONE, 5, Menu.NONE, "5 columns"); | |
return super.onCreateOptionsMenu(menu); | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
int id = item.getItemId(); | |
if (id >= 1 && id <= 5) { | |
gridLayoutManager.setSpanCount(id); | |
subAdapter.setSpanCount(id); | |
recyclerView.requestLayout(); | |
return true; | |
} | |
return super.onOptionsItemSelected(item); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.recyclertest; | |
import android.content.Context; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.TextView; | |
import java.util.List; | |
public class SampleSubAdapter extends SectionAdapter.SubAdapter { | |
private final LayoutInflater inflater; | |
private List<Section> data; | |
private int spanCount; | |
public SampleSubAdapter(Context context, List<Section> data, int spanCount) { | |
inflater = LayoutInflater.from(context); | |
this.data = data; | |
this.spanCount = spanCount; | |
} | |
@Override | |
public int getSectionCount() { | |
return data.size(); | |
} | |
@Override | |
public int getItemCountForSection(int section) { | |
return data.get(section).items.size(); | |
} | |
@Override | |
public int getSpanCount() { | |
return spanCount; | |
} | |
public void setSpanCount(int spanCount) { | |
this.spanCount = spanCount; | |
} | |
@Override | |
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |
if (viewType == VIEW_TYPE_HEADER) { | |
return new HeaderViewHolder(inflater.inflate(HeaderViewHolder.LAYOUT_ID, parent, false)); | |
} else { | |
return new ItemViewHolder(inflater.inflate(ItemViewHolder.LAYOUT_ID, parent, false)); | |
} | |
} | |
@Override | |
public void onBindSectionHeaderViewHolder(RecyclerView.ViewHolder holder, int section) { | |
HeaderViewHolder h = (HeaderViewHolder) holder; | |
h.textView.setText(data.get(section).title); | |
} | |
@Override | |
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int section, int position) { | |
ItemViewHolder h = (ItemViewHolder) holder; | |
h.textView.setText(data.get(section).items.get(position)); | |
} | |
public static class Section { | |
public String title; | |
public List<String> items; | |
public Section(String title, List<String> items) { | |
this.title = title; | |
this.items = items; | |
} | |
} | |
public static class HeaderViewHolder extends RecyclerView.ViewHolder { | |
static final int LAYOUT_ID = android.R.layout.simple_list_item_1; | |
public final TextView textView; | |
public HeaderViewHolder(View itemView) { | |
super(itemView); | |
textView = (TextView) itemView.findViewById(android.R.id.text1); | |
textView.setTextSize(20); | |
} | |
} | |
public static class ItemViewHolder extends RecyclerView.ViewHolder { | |
static final int LAYOUT_ID = android.R.layout.simple_list_item_1; | |
public final TextView textView; | |
public ItemViewHolder(View itemView) { | |
super(itemView); | |
textView = (TextView) itemView.findViewById(android.R.id.text1); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.recyclertest; | |
import android.support.v7.widget.GridLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.ViewGroup; | |
public class SectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { | |
private SubAdapter subAdapter; | |
public SectionAdapter(SubAdapter subAdapter) { | |
this.subAdapter = subAdapter; | |
} | |
@Override | |
public int getItemCount() { | |
int count = 0; | |
for (int section = 0; section < subAdapter.getSectionCount(); section++) { | |
if (subAdapter.hasSectionHeader(section)) { | |
count++; | |
} | |
count += subAdapter.getItemCountForSection(section); | |
} | |
return count; | |
} | |
@Override | |
public int getItemViewType(int position) { | |
IndexPath indexPath = indexPathOfPosition(position); | |
if (indexPath.position == IndexPath.POSITION_HEADER) { | |
return subAdapter.getSectionHeaderViewType(indexPath.section); | |
} else { | |
return subAdapter.getItemViewType(indexPath.section, indexPath.position); | |
} | |
} | |
@Override | |
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |
return subAdapter.onCreateViewHolder(parent, viewType); | |
} | |
@Override | |
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { | |
IndexPath indexPath = indexPathOfPosition(position); | |
if (indexPath.position == IndexPath.POSITION_HEADER) { | |
subAdapter.onBindSectionHeaderViewHolder(holder, indexPath.section); | |
} else { | |
subAdapter.onBindItemViewHolder(holder, indexPath.section, indexPath.position); | |
} | |
} | |
public IndexPath indexPathOfPosition(int position) { | |
if (position < 0) { | |
return null; | |
} | |
for (int section = 0; section < subAdapter.getSectionCount(); section++) { | |
if (subAdapter.hasSectionHeader(section)) { | |
if (position == 0) { | |
return new IndexPath(section, IndexPath.POSITION_HEADER); | |
} | |
position--; | |
} | |
if (position < subAdapter.getItemCountForSection(section)) { | |
return new IndexPath(section, position); | |
} | |
position -= subAdapter.getItemCountForSection(section); | |
} | |
return null; | |
} | |
public static class IndexPath { | |
public static final int POSITION_HEADER = -1; | |
public final int section; | |
public final int position; | |
public IndexPath(int section, int position) { | |
this.section = section; | |
this.position = position; | |
} | |
} | |
public class SpanSizeLookup extends GridLayoutManager.SpanSizeLookup { | |
@Override | |
public int getSpanSize(int position) { | |
IndexPath indexPath = indexPathOfPosition(position); | |
if (indexPath.position == IndexPath.POSITION_HEADER) { | |
return subAdapter.getSpanCount(); | |
} else { | |
return subAdapter.getItemSpanSize(indexPath.section, indexPath.position); | |
} | |
} | |
} | |
public static abstract class SubAdapter { | |
public static final int VIEW_TYPE_HEADER = 1; | |
public static final int VIEW_TYPE_ITEM = 2; | |
public abstract int getSectionCount(); | |
public boolean hasSectionHeader(int section) { return true; } | |
public abstract int getItemCountForSection(int section); | |
public int getSpanCount() { return 1; } | |
public int getItemSpanSize(int section, int position) { return 1; } | |
public int getSectionHeaderViewType(int section) { return VIEW_TYPE_HEADER; } | |
public int getItemViewType(int section, int position) { return VIEW_TYPE_ITEM; } | |
public abstract RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType); | |
public abstract void onBindSectionHeaderViewHolder(RecyclerView.ViewHolder holder, int section); | |
public abstract void onBindItemViewHolder(RecyclerView.ViewHolder holder, int section, int position); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment