Upgrade to Pro — share decks privately, control downloads, hide ads and more …

droidgirls RecyclerView

Avatar for Yuki Anzai Yuki Anzai
December 21, 2016

droidgirls RecyclerView

Avatar for Yuki Anzai

Yuki Anzai

December 21, 2016
Tweet

More Decks by Yuki Anzai

Other Decks in Technology

Transcript

  1. • blog : Y.A.M ͷࡶهா • y-anz-m.blogspot.com • twitter :

    @yanzm ʢ΍Μ͟Ήʣ • uPhyca Inc. (גࣜձࣾ΢ϑΟΧ) ͋Μ͍͟Ώ͖
  2. ListView vs RecyclerView ListView RecyclerView ۠੾Γઢ ⚪ ࣗ෼Ͱ࣮૷ listSelector ⚪

    º onItemClick ⚪ ࣗ෼Ͱ࣮૷ choiceMode ⚪ º BOESPJETVQQPSUWXJEHFU%JWJEFS*UFN%FDPSBUJPO͕Ͱ௥Ճ͞Ε·ͨ͠
  3. ListView vs RecyclerView ListView RecyclerView Filter ⚪ ࣗ෼Ͱ࣮૷ FadingEdge ⚪

    ࣗ෼Ͱ࣮૷ Header, Footer ⚪ ࣗ෼Ͱ࣮૷ StaggeredGrid º ⚪
  4. ListView vs RecyclerView ListView RecyclerView ௥Ճɾ࡟আͷ Ξχϝʔγϣϯ ࣗ෼Ͱ࣮૷ ⚪ Swipe

    to Dismiss ࣗ෼Ͱ࣮૷ ⚪ Drag & Drop ࣗ෼Ͱ࣮૷ ⚪ ԣεΫϩʔϧ഑ஔ º ⚪
  5. 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
  6. 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
  7. 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
  8. DividerItemDecoration • v25.0.0 Ͱ DividerItemDecoration ͕௥Ճ͞Εͨ ͷͰͦΕΛ࢖͏ͷ͕؆୯ • https://developer.android.com/reference/ android/support/v7/widget/

    DividerItemDecoration.html • Ұ൪࠷ޙͷΞΠςϜͷԼʹ΋ඳը͞Εͯ͠·͏ recyclerView.addItemDecoration( new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
  9. ΞΠςϜ༻ͷ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);
  10. ΞΠςϜ༻ͷ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);
  11. 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Λඳը
  12. @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Λඳը
  13. 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
  14. 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
  15. notify** • notifyItemChanged(int position) • positionͷҐஔͷΞΠςϜͷมߋ͞Εͨ • notifyItemInserted(int position) •

    posiitonͷҐஔʹΞΠςϜ͕௥Ճ͞Εͨ • notifyItemRemoved(int position) • positionͷҐஔͷΞΠςϜ͕࡟আ͞Εͨ
  16. notify** • notifyItemMoved(int fromPosition, int toPosition) • fromPositionʹ͋ͬͨΞΠςϜ͕toPositionʹҠಈͨ͠ • notifyItemRangeChanged(int

    positionStart, int itemCount) • positionStart͔ΒitemCountݸͷΞΠςϜ͕มߋ͞Εͨ • notifyItemRangeInserted(int positionStart, int itemCount) • positionStartʹitemCountݸͷΞΠςϜ͕௥Ճ͞Εͨ
  17. 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
  18. 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
  19. 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;
 }
 }
  20. 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;
 }
  21. 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);
 }
 }
  22. • γϯϓϧͳList, Grid → • ListView, GridView • RecyclerView •

    ListView, GridView Ͱ͸ແཧͳ഑ஔ → • RecyclerView ·ͱΊ