27. public class ViewHolder extends RecyclerView.ViewHolder {
private static final int LAYOUT_ID = android.R.layout.simple_list_item_1;
@NonNull
public static ViewHolder create(@NonNull LayoutInflater inflater,
ViewGroup parent) {
return new ViewHolder(inflater.inflate(LAYOUT_ID, parent, false));
}
final TextView textView;
private ViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(android.R.id.text1);
}
}
ViewHolder
28. public class SimpleAdapter extends RecyclerView.Adapter<ViewHolder> {
@NonNull
private final List<String> data;
public SimpleAdapter(@NonNull List<String> data) {
this.data = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext())
return ViewHolder.create(inflater, parent);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final String text = data.get(position);
holder.textView.setText(text);
}
@Override
public int getItemCount() {
return data.size();
}
}
Adapter
29. public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view)
recyclerView.setHasFixedSize(true);
List<String> data = new ArrayList<>();
for (int i = 0; i < 30; i++) {
data.add("Item : " + i);
}
final SimpleAdapter adapter = new SimpleAdapter(data);
recyclerView.setAdapter(adapter);
}
}
Activity
44. アイテム用のViewのOffsetを指定
final int offset = (int) (8 * getResources().getDisplayMetrics().density);
RecyclerView.ItemDecoration itemDecoration = new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.set(offset, offset, offset, offset);
}
};
recyclerView.addItemDecoration(itemDecoration);
45.
46. アイテム用のViewのOffsetを指定
RecyclerView.ItemDecoration itemDecoration = new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
int position = ((RecyclerView.LayoutParams) view.getLayoutParams())
.getViewLayoutPosition();
if (position == 0) {
outRect.set(offset, offset, offset, offset);
} else {
outRect.set(offset, 0, offset, offset);
}
}
};
recyclerView.addItemDecoration(itemDecoration);
47.
48. public class DividerDecoration extends RecyclerView.ItemDecoration {
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final int dividerHeight;
public DividerDecoration(Resources res) {
paint.setColor(Color.GRAY);
dividerHeight = (int) (4 * res.getDisplayMetrics().density);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
final int position = ((RecyclerView.LayoutParams) view.getLayoutParams())
.getViewLayoutPosition();
// 位置が2番目以降なら上部にdividerを描画したいので、
// divider分だけ上をあける
int top = position == 0 ? 0 : dividerHeight;
outRect.set(0, top, 0, 0);
}
Dividerを描画
49. @Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
// アイテムのビューより上に描画される
final RecyclerView.LayoutManager manager = parent.getLayoutManager();
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 1; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params =
(RecyclerView.LayoutParams) child.getLayoutParams();
if (params.getViewLayoutPosition() == 0) {
continue;
}
// ViewCompat.getTranslationY()を入れないと
// 追加・削除のアニメーション時の位置が変になる
final int top = manager.getDecoratedTop(child)
- params.topMargin + Math.round(ViewCompat.getTranslationY(child));
final int bottom = top + dividerHeight;
c.drawRect(left, top, right, bottom, paint);
}
}
}
Dividerを描画
61. public abstract class ArrayAdapter<T, VH extends RecyclerView.ViewHolder> extends
RecyclerView.Adapter<VH> {
private final Object lock = new Object();
private final List<T> objects;
public ArrayAdapter() {
this(new ArrayList<T>());
}
public ArrayAdapter(List<T> objects) {
this.objects = objects;
}
public void add(@NonNull T object) {
final int position;
synchronized (lock) {
position = objects.size();
objects.add(object);
}
notifyItemInserted(position);
}
ArrayAdapter的なRecyclerView用Adapter
62. public void addAll(@NonNull Collection<? extends T> collection) {
final int itemCount = collection.size();
final int positionStart;
synchronized (lock) {
positionStart = objects.size();
objects.addAll(collection);
}
notifyItemRangeInserted(positionStart, itemCount);
}
public void insert(@NonNull T object, int index) {
synchronized (lock) {
objects.add(index, object);
}
notifyItemInserted(index);
}
public void remove(@NonNull T object) {
final int position = objects.indexOf(object);
synchronized (lock) {
objects.remove(object);
}
notifyItemRemoved(position);
}
}
ArrayAdapter的なRecyclerView用Adapter
66. Header と Footer をつくる
public class SimpleAdapter2 extends RecyclerView.Adapter {
private static final int VIEW_TYPE_HEADER = 0;
private static final int VIEW_TYPE_FOOTER = 1;
private static final int VIEW_TYPE_ITEM = 2;
…
@Override
public int getItemCount() {
return data.size() + 2; // header + footer
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return VIEW_TYPE_HEADER;
}
if (position == getItemCount() - 1) {
return VIEW_TYPE_FOOTER;
}
return VIEW_TYPE_ITEM;
}
}
67. Header と Footer をつくる
public class SimpleAdapter2 extends RecyclerView.Adapter {
…
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case VIEW_TYPE_HEADER: {
return HeaderViewHolder.create(inflater, parent);
}
case VIEW_TYPE_FOOTER: {
return FooterViewHolder.create(inflater, parent);
}
case VIEW_TYPE_ITEM: {
final ViewHolder holder = ViewHolder.create(inflater, parent);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final int position = holder.getAdapterPosition();
final String text = data.get(position);
onItemClicked(text);
}
});
return holder;
}
}
return null;
}
68. Header と Footer をつくる
public class SimpleAdapter2 extends RecyclerView.Adapter {
…
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ViewHolder) {
final ViewHolder viewHolder = (ViewHolder) holder;
final String text = data.get(position);
viewHolder.textView.setText(text);
}
}