public void updateStickyView() { final View header = getHeader(); if (header != null) { mSticky = header.findViewWithTag("sticky"); } }
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (mSticky == null) { updateStickyView(); } if (mSticky != null) { final View headerView = getHeader(); if (headerView != null && headerView.getHeight() == 0) { headerView.layout(0, -headerView.getMeasuredHeight(), headerView.getMeasuredWidth(), 0); } } }
@Override protected void onMeasure(int widthSpec, int heightSpec) { super.onMeasure(widthSpec, heightSpec); if (mSticky != null) { measureChild(getHeader(), widthSpec, heightSpec); } }
@Override public void draw(Canvas canvas) { super.draw(canvas); if (mSticky != null) { final View headerView = getHeader(); final int saveCount = canvas.save(); // The view to draw when sticking to the top final View drawTarget = headerView != null ? headerView : mSticky; // The offset to draw the view at when sticky final int drawOffset = headerView != null ? mSticky.getTop() : 0; // Position of the draw target, relative to the outside of the scrollView final int drawTop = drawTarget.getTop(); if (drawTop + drawOffset < mStatusBarInset || !drawTarget.isShown()) { // RecyclerView does not translate the canvas, so we can simply draw at the top mStickyRect.set(0, -drawOffset + mStatusBarInset, drawTarget.getWidth(), drawTarget.getHeight() - drawOffset + mStatusBarInset); canvas.translate(0, mStickyRect.top); canvas.clipRect(0, 0, drawTarget.getWidth(), drawTarget.getHeight()); drawTarget.draw(canvas); } else { mStickyRect.setEmpty(); } canvas.restoreToCount(saveCount); } }
@Override public boolean dispatchTouchEvent(MotionEvent ev) { if (mStickyRect.contains(ev.getX(), ev.getY())) { ev.offsetLocation(-mStickyRect.left, -mStickyRect.top); return getHeader().dispatchTouchEvent(ev); } else { return super.dispatchTouchEvent(ev); } } }