public static final int TYPE_VIEW_HEADER = Integer.MAX_VALUE; private int sizeDiff = 1; @Override public final int getItemViewType(final int position) { if (position == 0 && enableHeader) return TYPE_VIEW_HEADER; return getMainItemType(position - sizeDiff); } protected abstract int getMainItemType(int position);
@Override public final RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) { if (viewType == TYPE_VIEW_HEADER) return onCreateHeaderViewHolder(parent); return onCreateMainViewHolder(parent, viewType); } protected abstract HeaderHolder onCreateHeaderViewHolder(final ViewGroup parent); protected abstract VH onCreateMainViewHolder(final ViewGroup parent, final int viewType); @Override public final void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { if (holder.getItemViewType() == TYPE_VIEW_HEADER) { onBindHeaderViewHolder((HeaderHolder) holder); return; } onBindMainViewHolder((VH) holder, position - sizeDiff); } protected abstract <HH extends HeaderHolder> void onBindHeaderViewHolder(final HH holder); protected abstract void onBindMainViewHolder(final VH holder, final int position); protected static class HeaderHolder extends RecyclerView.ViewHolder { public HeaderHolder(final View itemView) { super(itemView); } }
private static class CustomWrapper extends FrameLayout { private int offset; public CustomWrapper(Context context) { super(context); } @Override protected void dispatchDraw(Canvas canvas) { canvas.clipRect(new Rect(getLeft(), getTop(), getRight(), getBottom() + offset)); super.dispatchDraw(canvas); } public void setYOffset(int offset) { this.offset = offset; invalidate(); } }
protected static class HeaderHolder extends RecyclerView.ViewHolder { public HeaderHolder(final View itemView) { super(new CustomWrapper(itemView.getContext())); final ViewGroup parent = (ViewGroup) itemView.getParent(); if (parent != null) parent.removeView(itemView); ((CustomWrapper) this.itemView).addView(itemView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); this.itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } }
private class ScrollListener extends RecyclerView.OnScrollListener { @Override public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) { totalScroll += dy; if (customWrapper != null && !headerOutOfVisibleRange()) { doParallaxWithHeader(totalScroll); } changeVisibilityHeader(); } private void changeVisibilityHeader() { if (customWrapper != null) { customWrapper.setVisibility(headerOutOfVisibleRange() ? View.INVISIBLE : View.VISIBLE); } } private boolean headerOutOfVisibleRange() { return totalScroll > getHeaderHeight(); } }
private void doParallaxWithHeader(float offset) { float parallaxOffset = offset * SCROLL_SPEED; moveHeaderToOffset(parallaxOffset); if (parallaxListener != null && enableHeader) parallaxListener.onParallaxScroll(left); customWrapper.setYOffset(Math.round(parallaxOffset)); notifyHeaderChanged(); } private void moveHeaderToOffset(final float parallaxOffset) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { customWrapper.setTranslationY(parallaxOffset); } else { TranslateAnimation anim = createTranslateAnimation(parallaxOffset); customWrapper.startAnimation(anim); } } private TranslateAnimation createTranslateAnimation(final float parallaxOffset) { TranslateAnimation anim = new TranslateAnimation(0, 0, parallaxOffset, parallaxOffset); anim.setFillAfter(true); anim.setDuration(0); return anim; } public final void notifyHeaderChanged() { notifyItemChanged(0); } public final void notifyMainItemChanged(final int position) { notifyItemChanged(position + sizeDiff); }
Source: https://habr.com/ru/post/250689/
All Articles