Slide 1

Slide 1 text

ADVANCED RECYCLERVIEW TECHNIQUES JOSHUA JAMISON

Slide 2

Slide 2 text

OLD SCHOOL LISTVIEWS ▸ Simple to setup ▸ Limited layout options 
 (only vertical unless hacked) ▸ Limited grouping support ▸ Required fake injected data or complicated view manipulation

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

BASICS ITEM DECORATIONS

Slide 5

Slide 5 text

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) {
 }

Slide 6

Slide 6 text

@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;
 }

Slide 7

Slide 7 text

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);
 }

Slide 8

Slide 8 text

CODE EXAMPLES COMBINED! ▸ zomg ▸ no wai ▸ wow recyclerView.addItemDecoration(new Simple1Decoration(this)); 
 recyclerView.addItemDecoration(new Simple2Decoration(this));

Slide 9

Slide 9 text

public interface Callback {
 long getGroupId(int position);
 
 String getGroupFirstLine(int position);
 } CODE EXAMPLES COMPLEX DECORATION

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

@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

Slide 12

Slide 12 text

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); }

Slide 13

Slide 13 text

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)

Slide 14

Slide 14 text

ANIMATION ITEM ANIMATORS ▸ Custom Implementation is extremely time consuming ▸ DefaultItemAnimator applied automatically ▸ Already follows Material animation patterns

Slide 15

Slide 15 text

ANIMATION ITEM ANIMATORS IMPLEMENTATION ▸ Read the source code ▸ DefaultItemAnimator ▸ SimpleItemAnimator ▸ RecyclerView.ItemAnimator ▸ Probably should extend SimpleItemAnimator

Slide 16

Slide 16 text

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()

Slide 17

Slide 17 text

ANIMATION ITEM ANIMATORS CONCLUSION ▸ Just use the DefaultItemAnimator or… ▸ Use @wasabeef’s library: RecyclerView Animators ▸ https://github.com/wasabeef/recyclerview-animators

Slide 18

Slide 18 text

THANKS! https://github.com/cephus/AdvancedRecyclerView Joshua Jamison +JoshuaJamison @cephus