@Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { boolean needsInvalidate = false; if (mTopGlow != null && !mTopGlow.isFinished()) { final int restore = c.save(); if (getClipToPadding(parent)) { c.translate(parent.getPaddingLeft(), parent.getPaddingTop()); } //noinspection ConstantConditions needsInvalidate |= mTopGlow.draw(c); c.restoreToCount(restore); } if (mBottomGlow != null && !mBottomGlow.isFinished()) { final int restore = c.save(); c.rotate(180); if (getClipToPadding(parent)) { c.translate( -parent.getWidth() + parent.getPaddingRight(), -parent.getHeight() + parent.getPaddingBottom()); } else { c.translate(-parent.getWidth(), -parent.getHeight()); } needsInvalidate |= mBottomGlow.draw(c); c.restoreToCount(restore); } if (needsInvalidate) { ViewCompat.postInvalidateOnAnimation(parent); } }
@Override protected Rect getDividerBound(int position, RecyclerView parent, View child) { Rect bounds = new Rect(0, 0, 0, 0); int transitionX = (int) ViewCompat.getTranslationX(child); int transitionY = (int) ViewCompat.getTranslationY(child); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); bounds.top = parent.getPaddingTop() + mMarginProvider.dividerTopMargin(position, parent) + transitionY; bounds.bottom = parent.getHeight() - parent.getPaddingBottom() - mMarginProvider.dividerBottomMargin(position, parent) + transitionY; int dividerSize = getDividerSize(position, parent); if (mDividerType == DividerType.DRAWABLE) { bounds.left = child.getRight() + params.leftMargin + transitionX; bounds.right = bounds.left + dividerSize; } else { bounds.left = child.getRight() + params.leftMargin + dividerSize / 2 + transitionX; bounds.right = bounds.left; } return bounds; }
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (dy == 0 || recyclerView.getChildCount() <= 0) return; LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); int firstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition(); int lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); int visibleItemCount = lastVisibleItem - firstVisibleItem; int totalItemCount = recyclerView.getAdapter().getItemCount(); NewsListRecyclerAdapter adapter = (NewsListRecyclerAdapter) recyclerView.getAdapter(); // Set the item at top to read ViewHolder vh = (ViewHolder) recyclerView.findViewHolderForLayoutPosition(firstVisibleItem); if (vh != null && !vh.shouldStayUnread()) { adapter.ChangeReadStateOfItem(vh, true); } // Check if Listview is scrolled to bottom if (lastVisibleItem == (totalItemCount - 1) && recyclerView.getChildAt(visibleItemCount).getBottom() <= recyclerView.getHeight()) { for (int i = firstVisibleItem + 1; i <= lastVisibleItem; i++) { vh = (ViewHolder) recyclerView.findViewHolderForLayoutPosition(i); if (vh != null && !vh.shouldStayUnread()) { adapter.ChangeReadStateOfItem(vh, true); } } } }
@Override public View getHeader(RecyclerView parent, int position) { long headerId = mAdapter.getHeaderId(position); View header = mHeaderViews.get(headerId); if (header == null) { // TODO - recycle views RecyclerView.ViewHolder viewHolder = mAdapter.onCreateHeaderViewHolder(parent); mAdapter.onBindHeaderViewHolder(viewHolder, position); header = viewHolder.itemView; if (header.getLayoutParams() == null) { header.setLayoutParams( new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } int widthSpec; int heightSpec; if (mOrientationProvider.getOrientation(parent) == LinearLayoutManager.VERTICAL) { widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY); heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED); } else { widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.UNSPECIFIED); heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.EXACTLY); } int childWidth = ViewGroup.getChildMeasureSpec( widthSpec, parent.getPaddingLeft() + parent.getPaddingRight(), header.getLayoutParams().width); int childHeight = ViewGroup.getChildMeasureSpec( heightSpec, parent.getPaddingTop() + parent.getPaddingBottom(), header.getLayoutParams().height); header.measure(childWidth, childHeight); header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight()); mHeaderViews.put(headerId, header); } return header; }
@Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { debugLog("onTouchEvent"); if ((e.getAction() == MotionEvent.ACTION_UP) || (e.getAction() == MotionEvent.ACTION_CANCEL)) { if ((e.getAction() == MotionEvent.ACTION_UP) && selectedDragItemPos != -1) { int newPos = getNewPostion(rv); if (moveInterface != null) moveInterface.onItemMoved(selectedDragItemPos, newPos); } setIsDragging(false); selectedDragItemPos = -1; floatingItem = null; rv.invalidateItemDecorations(); return; } fingerY = (int) e.getY(); if (floatingItem != null) { floatingItemBounds.top = fingerY - fingerOffsetInViewY; if (floatingItemBounds.top < -floatingItemStatingBounds.height() / 2) // Allow half the view out the top floatingItemBounds.top = -floatingItemStatingBounds.height() / 2; floatingItemBounds.bottom = floatingItemBounds.top + floatingItemStatingBounds.height(); floatingItem.setBounds(floatingItemBounds); } // Do auto scrolling at end of list float scrollAmount = 0; if (fingerY > (rv.getHeight() * (1 - autoScrollWindow))) { scrollAmount = (fingerY - (rv.getHeight() * (1 - autoScrollWindow))); } else if (fingerY < (rv.getHeight() * autoScrollWindow)) { scrollAmount = (fingerY - (rv.getHeight() * autoScrollWindow)); } debugLog("Scroll: " + scrollAmount); scrollAmount *= autoScrollSpeed; rv.scrollBy(0, (int) scrollAmount); rv.invalidateItemDecorations(); // Redraw }
@Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { if (mDivider == null) { super.onDrawOver(c, parent, state); return; } // Initialization needed to avoid compiler warning int left = 0, right = 0, top = 0, bottom = 0, size; int orientation = mOrientation != -1 ? mOrientation : getOrientation(parent); int childCount = parent.getChildCount(); if (orientation == LinearLayoutManager.VERTICAL) { size = mDivider.getIntrinsicHeight(); left = parent.getPaddingLeft(); right = parent.getWidth() - parent.getPaddingRight(); } else { // horizontal size = mDivider.getIntrinsicWidth(); top = parent.getPaddingTop(); bottom = parent.getHeight() - parent.getPaddingBottom(); } for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getTop() - params.topMargin - size; bottom = top + size; } else { // horizontal left = child.getLeft() - params.leftMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } // show last divider if (mShowLastDivider && childCount > 0) { View child = parent.getChildAt(childCount - 1); if (parent.getChildAdapterPosition(child) == (state.getItemCount() - 1)) { RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getBottom() + params.bottomMargin; bottom = top + size; } else { // horizontal left = child.getRight() + params.rightMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } }
public void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } }
/** * 绘制垂直方向的分割线 * * @param c * @param parent */ private void drawVDeraction(Canvas c, RecyclerView parent) { int top = parent.getPaddingTop(); int bottom = parent.getHeight() - parent.getPaddingBottom(); int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); int left = child.getRight() + layoutParams.rightMargin; int right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } }
private void drawHorizontal(Canvas canvas, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 1; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int size = mDivider.getIntrinsicWidth(); final int left = child.getLeft() - params.leftMargin; final int right = left + size; mDivider.setBounds(left, top, right, bottom); mDivider.draw(canvas); } }
public static boolean isChildInCenterY(RecyclerView recyclerView, View view) { int childCount = recyclerView.getChildCount(); int[] rvLocationOnScreen = new int[2]; int[] vLocationOnScreen = new int[2]; recyclerView.getLocationOnScreen(rvLocationOnScreen); int middleY = (int) (rvLocationOnScreen[1] + recyclerView.getHeight() * recyclerView.getScaleY() / 2); if (childCount > 0) { view.getLocationOnScreen(vLocationOnScreen); if (vLocationOnScreen[1] <= middleY && vLocationOnScreen[1] + view.getHeight() * view.getScaleY() >= middleY) { return true; } } return false; }
public void drawHorizontal(@NonNull Canvas c, @NonNull RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); IntStream.range(0, childCount) .forEach( i -> { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); }); }
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (isVideoFullScreen()) return; // get our facts straight int recyclerHeight = recyclerView.getHeight(); Optional<Integer> scrollEstimate = estimateRecyclerViewScrollY(recyclerView); boolean viewerVisible = scrollEstimate.isPresent(); int scrollY = scrollEstimate.or(viewer.getHeight()); int viewerHeight = viewer.getHeight(); boolean doFancyScroll = viewerHeight < recyclerHeight; ScrollHideToolbarListener toolbar = activity.getScrollHideToolbarListener(); if (!doFancyScroll || dy < 0 || scrollY > toolbar.getToolbarHeight()) { toolbar.onScrolled(dy); } float scroll = doFancyScroll ? 0.7f * scrollY : scrollY; if (doFancyScroll) { int clipTop = (int) (scroll + 0.5f); int clipBottom = viewer.getHeight() - (int) (scrollY - scroll + 0.5f); if (clipTop < clipBottom) { viewer.setClipBoundsCompat(new Rect(0, clipTop, viewer.getRight(), clipBottom)); } else { viewerVisible = false; } } else { // reset bounds. we might have set some previously and want // to clear those bounds now. viewer.setClipBoundsCompat(null); } offsetMediaView(viewerVisible, scroll); // position the vote indicator float remaining = viewerHeight - scrollY; int tbVisibleHeight = toolbar.getVisibleHeight(); float voteIndicatorY = Math.min((remaining - tbVisibleHeight) / 2, (recyclerHeight - tbVisibleHeight) / 2) + tbVisibleHeight; voteAnimationIndicator.setTranslationY(voteIndicatorY); }
@Override public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int top = parent.getPaddingTop(); int bottom = parent.getHeight() - parent.getPaddingBottom(); int orientation = getOrientation(parent); int childCount = parent.getChildCount(); for (int i = showFirstDivider ? 0 : 1; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getTop() - params.topMargin; bottom = top - (size / 2); canvas.drawLine(left, bottom, right, bottom, paint); } else { left = child.getLeft() - params.leftMargin; right = left - (size / 2); canvas.drawLine(right, top, right, bottom, paint); } } if (showLastDivider && childCount > 0) { View child = parent.getChildAt(childCount - 1); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getBottom() + params.bottomMargin; bottom = top + size; canvas.drawLine(left, bottom, right, bottom, paint); } else { left = child.getRight() + params.rightMargin; right = left + (size / 2); canvas.drawLine(right, top, right, bottom, paint); } } }
void handleDragScroll(RecyclerView rv, DragInfo dragInfo) { if (rv.getLayoutManager().canScrollHorizontally()) { if (rv.canScrollHorizontally(-1) && dragInfo.shouldScrollLeft()) { rv.scrollBy(-SCROLL_AMOUNT, 0); dragManager.clearNextMove(); } else if (rv.canScrollHorizontally(1) && dragInfo.shouldScrollRight(rv.getWidth())) { rv.scrollBy(SCROLL_AMOUNT, 0); dragManager.clearNextMove(); } } else if (rv.getLayoutManager().canScrollVertically()) { if (rv.canScrollVertically(-1) && dragInfo.shouldScrollUp()) { rv.scrollBy(0, -SCROLL_AMOUNT); dragManager.clearNextMove(); } else if (rv.canScrollVertically(1) && dragInfo.shouldScrollDown(rv.getHeight())) { rv.scrollBy(0, SCROLL_AMOUNT); dragManager.clearNextMove(); } } }
public static boolean canRecyclerViewScroll(RecyclerView view) { if (view == null || view.getAdapter() == null || view.getLayoutManager() == null) return false; final RecyclerView.LayoutManager lm = view.getLayoutManager(); final int count = view.getAdapter().getItemCount(); int lastVisible; if (lm instanceof LinearLayoutManager) { LinearLayoutManager llm = (LinearLayoutManager) lm; lastVisible = llm.findLastVisibleItemPosition(); } else { throw new MaterialDialog.NotImplementedException( "Material Dialogs currently only supports LinearLayoutManager. Please report any new layout managers."); } if (lastVisible == -1) return false; /* We scroll if the last item is not visible */ final boolean lastItemVisible = lastVisible == count - 1; return !lastItemVisible || (view.getChildCount() > 0 && view.getChildAt(view.getChildCount() - 1).getBottom() > view.getHeight() - view.getPaddingBottom()); }
private void updateTranslationOffset() { final RecyclerView rv = mRecyclerView; final int childCount = rv.getChildCount(); if (childCount > 0) { mTranslationLeftLimit = 0; mTranslationRightLimit = rv.getWidth() - mDraggingItemInfo.width; mTranslationTopLimit = 0; mTranslationBottomLimit = rv.getHeight() - mDraggingItemInfo.height; switch (mLayoutOrientation) { case CustomRecyclerViewUtils.ORIENTATION_VERTICAL: { mTranslationLeftLimit += rv.getPaddingLeft(); mTranslationRightLimit -= rv.getPaddingRight(); break; } case CustomRecyclerViewUtils.ORIENTATION_HORIZONTAL: { mTranslationTopLimit += rv.getPaddingTop(); mTranslationBottomLimit -= rv.getPaddingBottom(); break; } } mTranslationRightLimit = Math.max(mTranslationLeftLimit, mTranslationRightLimit); mTranslationBottomLimit = Math.max(mTranslationTopLimit, mTranslationBottomLimit); if (!mIsScrolling) { final int firstVisiblePosition = CustomRecyclerViewUtils.findFirstVisibleItemPosition(rv, true); final int lastVisiblePosition = CustomRecyclerViewUtils.findLastVisibleItemPosition(rv, true); final View firstChild = findRangeFirstItem(rv, mRange, firstVisiblePosition, lastVisiblePosition); final View lastChild = findRangeLastItem(rv, mRange, firstVisiblePosition, lastVisiblePosition); switch (mLayoutOrientation) { case CustomRecyclerViewUtils.ORIENTATION_VERTICAL: { if (firstChild != null) { mTranslationTopLimit = Math.min(mTranslationBottomLimit, firstChild.getTop()); } if (lastChild != null) { mTranslationBottomLimit = Math.min(mTranslationBottomLimit, lastChild.getTop()); } break; } case CustomRecyclerViewUtils.ORIENTATION_HORIZONTAL: { if (firstChild != null) { mTranslationLeftLimit = Math.min(mTranslationLeftLimit, firstChild.getLeft()); } if (lastChild != null) { mTranslationRightLimit = Math.min(mTranslationRightLimit, lastChild.getLeft()); } break; } } } } else { mTranslationRightLimit = mTranslationLeftLimit = rv.getPaddingLeft(); mTranslationBottomLimit = mTranslationTopLimit = rv.getPaddingTop(); } mTranslationX = mTouchPositionX - mDraggingItemInfo.grabbedPositionX; mTranslationY = mTouchPositionY - mDraggingItemInfo.grabbedPositionY; mTranslationX = clip(mTranslationX, mTranslationLeftLimit, mTranslationRightLimit); mTranslationY = clip(mTranslationY, mTranslationTopLimit, mTranslationBottomLimit); }