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

Advanced RecyclerView Techniques

Joshua Jamison
February 18, 2016

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