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

Advanced RecyclerView Techniques

Advanced RecyclerView Techniques

Slides from DroidKaigi 2016

Joshua Jamison

February 18, 2016
Tweet

More Decks by Joshua Jamison

Other Decks in Technology

Transcript

  1. OLD SCHOOL LISTVIEWS ▸ Simple to setup ▸ Limited layout

    options 
 (only vertical unless hacked) ▸ Limited grouping support ▸ Required fake injected data or complicated view manipulation
  2. OLD SCHOOL IS LISTVIEW DEAD? ▸ ListView is very alive

    ▸ If it’s not broke then don’t fix it ▸ ListView should still be used for: ▸ Simple flat data (no grouping) ▸ Statically displayed content (no animation) ▸ Content displayed vertically
  3. IMPLEMENTATION ITEM DECORATIONS public class MyDecoration extends RecyclerView.ItemDecoration {
 


    } @Override
 public void onDraw(Canvas c, RecyclerView parent, State state) {
 }
 @Override public void onDrawOver(Canvas c, RecyclerView parent, State state) {
 }
 @Override
 public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
 }
  4. @Override
 public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {


    final int childCount = parent.getChildCount();
 final int left = parent.getPaddingLeft();
 final int right = parent.getWidth() - parent.getPaddingRight();
 
 for (int i = 0; i < childCount - 1; i++) {
 View view = parent.getChildAt(i);
 float top = view.getTop() - dividerHeightPx;
 float bottom = view.getTop();
 c.drawRect(left, top, right, bottom, dividerPaint);
 }
 } CODE EXAMPLES SIMPLE DIVIDER @Override
 public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
 super.getItemOffsets(outRect, view, parent, state);
 outRect.bottom = dividerHeightPx;
 }
  5. CODE EXAMPLES OVERLAYS @Override
 public void onDrawOver(Canvas c, RecyclerView parent,

    RecyclerView.State state) {
 super.onDrawOver(c, parent, state);
 
 
 } final int childCount = parent.getChildCount();
 
 for (int i = 0; i < childCount; i++) {
 View child = parent.getChildAt(i);
 int childPos = parent.getChildAdapterPosition(child); 
 } boolean isLeft = childPos % 2 == 0; float top = child.getTop();
 float bottom = child.getBottom();
 if (isLeft) {
 float left = child.getLeft();
 float right = left + indentWidthPx;
 c.drawRect(left, top, right, bottom, indentPaintLeft);
 } else {
 float right = child.getRight();
 float left = right - indentWidthPx;
 c.drawRect(left, top, right, bottom, indentPaintRight);
 }
  6. CODE EXAMPLES COMBINED! ▸ zomg ▸ no wai ▸ wow

    recyclerView.addItemDecoration(new Simple1Decoration(this)); 
 recyclerView.addItemDecoration(new Simple2Decoration(this));
  7. new ComplexDecoration(this, new ComplexDecoration.Callback() {
 @Override
 public long getGroupId(int position)

    {
 return Character.toUpperCase( data.get(position).title.charAt(0));
 }
 
 @Override
 public String getGroupFirstLine(int position) {
 return data.get(position).title .substring(0, 1).toUpperCase();
 }
 }); CODE EXAMPLES COMPLEX DECORATION
  8. @Override
 public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
 RecyclerView.State

    state) {
 super.getItemOffsets(outRect, view, parent, state);
 
 int pos = parent.getChildAdapterPosition(view);
 long groupId = callback.getGroupId(pos);
 if (groupId < 0) return;
 
 outRect.left = leftGap;
 outRect.right = rightGap;
 
 if (pos == 0 || isFirstInGroup(pos)) {
 outRect.top = topGap;
 } else {
 outRect.top = 0;
 }
 } CODE EXAMPLES COMPLEX DECORATION
  9. CODE EXAMPLES COMPLEX DECORATION @Override
 public void onDrawOver(Canvas c, RecyclerView

    parent, RecyclerView.State state) {
 super.onDrawOver(c, parent, state); … 
 // draw text
 c.drawText(textLine, left, textY, textPaint); }
  10. DECORATIONS WRAP UP ITEMDECORATIONS CAVEATS ▸ Much more complicated logic

    required when using different LayoutManager types ▸ Combining ItemDecorations can lead to unexpected results (especially for offsets)
  11. ANIMATION ITEM ANIMATORS ▸ Custom Implementation is extremely time consuming

    ▸ DefaultItemAnimator applied automatically ▸ Already follows Material animation patterns
  12. ANIMATION ITEM ANIMATORS IMPLEMENTATION ▸ Read the source code ▸

    DefaultItemAnimator ▸ SimpleItemAnimator ▸ RecyclerView.ItemAnimator ▸ Probably should extend SimpleItemAnimator
  13. ANIMATION ITEM ANIMATORS IMPLEMENTATION ▸ Override primary animate methods ▸

    public boolean animateAdd(final ViewHolder holder) ▸ public boolean animateRemove(final ViewHolder holder) ▸ public boolean animateMove(final ViewHolder holder, int fromX, int fromY, int toX, int toY) ▸ public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
 int fromX, int fromY, int toX, int toY) ▸ Collect pending animations ▸ Execute all animations simultaneously ▸ public void runPendingAnimations()
  14. ANIMATION ITEM ANIMATORS CONCLUSION ▸ Just use the DefaultItemAnimator or…

    ▸ Use @wasabeef’s library: RecyclerView Animators ▸ https://github.com/wasabeef/recyclerview-animators