Share
Embed
RecyclerView
第2回 droid girls meetup 「RecyclerView」
https://droidgirls.connpass.com/event/46233/
Yuki Anzai
December 21, 2016
Transcript
70 slides
-
• blog : Y.A.M ͷࡶهா • y-anz-m.blogspot.com • twitter :
@yanzm ʢΜ͟Ήʣ • uPhyca Inc. (גࣜձࣾϑΟΧ) ͋Μ͍͟Ώ͖ -
RecyclerView A flexible view for providing a limited window into
a large data set. -
ListViewͷߏ RecyclerView LayoutManager Adapter ࢠϏϡʔஔ ࢠϏϡʔ ʢViewHolderʣ ʹσʔλඥ Recycler ViewHolderΛ࠶ར༻
࠶ར༻͢Δ ViewHolder ListView ListAdapter -
ListViewͷߏ ListView = RecyclerView + LayoutManager + Recycler + ͦͷଞΖΖͷػೳ
ListAdapter = Adapter + ViewHolder -
ListViewͷߏ ListView = RecyclerView + LayoutManager + Recycler + ͦͷଞΖΖͷػೳ
ListAdapter = Adapter + ViewHolder -
ListView vs RecyclerView ListView RecyclerView ۠Γઢ ⚪ ࣗͰ࣮ listSelector ⚪
º onItemClick ⚪ ࣗͰ࣮ choiceMode ⚪ º BOESPJETVQQPSUWXJEHFU%JWJEFS*UFN%FDPSBUJPO͕ͰՃ͞Ε·ͨ͠ -
ListView vs RecyclerView ListView RecyclerView Filter ⚪ ࣗͰ࣮ FadingEdge ⚪
ࣗͰ࣮ Header, Footer ⚪ ࣗͰ࣮ StaggeredGrid º ⚪ -
ListView vs RecyclerView ListView RecyclerView Ճɾআͷ Ξχϝʔγϣϯ ࣗͰ࣮ ⚪ Swipe
to Dismiss ࣗͰ࣮ ⚪ Drag & Drop ࣗͰ࣮ ⚪ ԣεΫϩʔϧஔ º ⚪ -
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 -
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 -
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 -
orientation • σϑΥϧτLinearLayoutManager.VERTICAL <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.RecyclerView … android:orientation="horizontal" app:layoutManager="LinearLayoutManager"
/> new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); PS PS -
spanCount • ྻɺσϑΥϧτ1 <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.RecyclerView … app:layoutManager="GridLayoutManager" app:spanCount="2"
/> new GridLayoutManager(this, 2); layoutManager.setSpanCount(2); PS PS -
DividerItemDecoration • v25.0.0 Ͱ DividerItemDecoration ͕Ճ͞Εͨ ͷͰͦΕΛ͏ͷ͕؆୯ • https://developer.android.com/reference/ android/support/v7/widget/
DividerItemDecoration.html • Ұ൪࠷ޙͷΞΠςϜͷԼʹඳը͞Εͯ͠·͏ recyclerView.addItemDecoration( new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); -
ΞΠςϜ༻ͷ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); -
ΞΠςϜ༻ͷ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); -
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Λඳը -
@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Λඳը -
public class SimpleAdapter extends RecyclerView.Adapter<ViewHolder> { … protected
void onItemClicked(String text) { } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 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; } … } OnItemClick -
public class MainActivity extends AppCompatActivity { @Override protected void
onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); … final SimpleAdapter adapter = new SimpleAdapter(data) { @Override protected void onItemClicked(String text) { super.onItemClicked(text); Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show(); } }; recyclerView.setAdapter(adapter); OnItemClick -
notify** • notifyItemChanged(int position) • positionͷҐஔͷΞΠςϜͷมߋ͞Εͨ • notifyItemInserted(int position) •
posiitonͷҐஔʹΞΠςϜ͕Ճ͞Εͨ • notifyItemRemoved(int position) • positionͷҐஔͷΞΠςϜ͕আ͞Εͨ -
notify** • notifyItemMoved(int fromPosition, int toPosition) • fromPositionʹ͋ͬͨΞΠςϜ͕toPositionʹҠಈͨ͠ • notifyItemRangeChanged(int
positionStart, int itemCount) • positionStart͔ΒitemCountݸͷΞΠςϜ͕มߋ͞Εͨ • notifyItemRangeInserted(int positionStart, int itemCount) • positionStartʹitemCountݸͷΞΠςϜ͕Ճ͞Εͨ -
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 -
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 -
Header ͱ Footer Λͭ͘Δ • ϨΠΞτͷछྨʢViewHolder ͷछྨʣʹԠͯ͡ผͷ Λฦ͢Α͏ʹ͢Δ • σʔλͷछྨͰͳ͍
• ಉ͡ itemViewType Ͱ ViewHolder ͕࠶ར༻͞ΕΔ -
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; } } -
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; } -
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); } } -
• γϯϓϧͳList, Grid → • ListView, GridView • RecyclerView •
ListView, GridView Ͱແཧͳஔ → • RecyclerView ·ͱΊ