Skip to content

Commit

Permalink
Merge pull request h6ah4i#138 from h6ah4i/fix_issue_131
Browse files Browse the repository at this point in the history
Fix padding handling while dragging
  • Loading branch information
h6ah4i committed Oct 26, 2015
2 parents 6c41421 + f2edbc2 commit bd344ff
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class DraggingItemDecorator extends BaseDraggableItemDecorator {

private int mTranslationX;
private int mTranslationY;
private int mRecyclerViewPaddingLeft;
private Bitmap mDraggingItemImage;
private int mTranslationLeftLimit;
private int mTranslationRightLimit;
Expand Down Expand Up @@ -120,7 +119,7 @@ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
// However, if the RecyclerView has any other decorations or RecyclerView is in scrolling state,
// need to draw it to avoid visual corruptions.
if (mDraggingItemImage != null) {
final float left = mTranslationX + /*mRecyclerViewPaddingLeft*/ + mDraggingItemInfo.margins.left - mShadowPadding.left;
final float left = mTranslationX + mDraggingItemInfo.margins.left - mShadowPadding.left;
final float top = /*mDraggingItemMargins.top +*/ mTranslationY - mShadowPadding.top;
c.drawBitmap(mDraggingItemImage, left, top, null);
}
Expand All @@ -138,7 +137,6 @@ public void start(MotionEvent e, DraggingItemInfo draggingItemInfo) {

mTranslationLeftLimit = mRecyclerView.getPaddingLeft();
mTranslationTopLimit = mRecyclerView.getPaddingTop();
mRecyclerViewPaddingLeft = mRecyclerView.getPaddingLeft();
mLayoutOrientation = CustomRecyclerViewUtils.getOrientation(mRecyclerView);

// hide
Expand Down Expand Up @@ -186,7 +184,6 @@ public void finish(boolean animate) {
mTranslationRightLimit = 0;
mTranslationTopLimit = 0;
mTranslationBottomLimit = 0;
mRecyclerViewPaddingLeft = 0;
mTouchPositionX = 0;
mTouchPositionY = 0;
mStarted = false;
Expand Down Expand Up @@ -224,42 +221,55 @@ public int getDraggingItemTranslationX() {
private void updateTranslationOffset() {
final RecyclerView rv = mRecyclerView;
final int childCount = rv.getChildCount();

if (childCount > 0) {
mTranslationLeftLimit = rv.getPaddingLeft();
mTranslationRightLimit = Math.max(0, (rv.getWidth() - rv.getPaddingLeft() - mDraggingItemInfo.width));
mTranslationLeftLimit = 0;
mTranslationRightLimit = rv.getWidth() - mDraggingItemInfo.width;

mTranslationTopLimit = rv.getPaddingTop();
mTranslationBottomLimit = Math.max(0, (rv.getHeight() - rv.getPaddingBottom() - mDraggingItemInfo.height));
mTranslationTopLimit = 0;
mTranslationBottomLimit = rv.getHeight() - mDraggingItemInfo.height;

if (!mIsScrolling) {
final int firstVisiblePosition = CustomRecyclerViewUtils.findFirstVisibleItemPosition(rv);
final int lastVisiblePosition = CustomRecyclerViewUtils.findLastVisibleItemPosition(rv);
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: {
final View topChild = findRangeFirstItem(rv, mRange, firstVisiblePosition, lastVisiblePosition);
final View bottomChild = findRangeLastItem(rv, mRange, firstVisiblePosition, lastVisiblePosition);

if (topChild != null) {
mTranslationTopLimit = Math.min(mTranslationBottomLimit, topChild.getTop());
if (firstChild != null) {
mTranslationTopLimit = Math.min(mTranslationBottomLimit, firstChild.getTop());
}

if (bottomChild != null) {
mTranslationBottomLimit = Math.min(mTranslationBottomLimit, bottomChild.getTop());
if (lastChild != null) {
mTranslationBottomLimit = Math.min(mTranslationBottomLimit, lastChild.getTop());
}
break;
}
case CustomRecyclerViewUtils.ORIENTATION_HORIZONTAL: {
final View leftChild = findRangeFirstItem(rv, mRange, firstVisiblePosition, lastVisiblePosition);
final View rightChild = findRangeLastItem(rv, mRange, firstVisiblePosition, lastVisiblePosition);

if (leftChild != null) {
mTranslationLeftLimit = Math.min(mTranslationLeftLimit, leftChild.getLeft());
if (firstChild != null) {
mTranslationLeftLimit = Math.min(mTranslationLeftLimit, firstChild.getLeft());
}

if (rightChild != null) {
mTranslationRightLimit = Math.min(mTranslationRightLimit, rightChild.getLeft());
if (lastChild != null) {
mTranslationRightLimit = Math.min(mTranslationRightLimit, lastChild.getLeft());
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1306,25 +1306,27 @@ static RecyclerView.ViewHolder findSwapTargetItem(
DraggingItemInfo draggingItemInfo, int overlayItemLeft, int overlayItemTop, ItemDraggableRange range) {
RecyclerView.ViewHolder swapTargetHolder = null;

overlayItemLeft = Math.max(overlayItemLeft, rv.getPaddingLeft());
overlayItemLeft = Math.min(overlayItemLeft, Math.max(0, rv.getWidth() - rv.getPaddingRight() - draggingItemInfo.width));

overlayItemTop = Math.max(overlayItemTop, rv.getPaddingTop());
overlayItemTop = Math.min(overlayItemTop, Math.max(0, rv.getHeight() - rv.getPaddingBottom() - draggingItemInfo.height));


if ((draggingItem == null) || (
draggingItem.getAdapterPosition() != RecyclerView.NO_POSITION &&
draggingItem.getItemId() == draggingItemInfo.id)) {

final int layoutType = CustomRecyclerViewUtils.getLayoutType(rv);
final boolean isVerticalLayout =
(CustomRecyclerViewUtils.extractOrientation(layoutType) == CustomRecyclerViewUtils.ORIENTATION_VERTICAL);

if (isVerticalLayout) {
overlayItemLeft = Math.max(overlayItemLeft, rv.getPaddingLeft());
overlayItemLeft = Math.min(overlayItemLeft, Math.max(0, rv.getWidth() - rv.getPaddingRight() - draggingItemInfo.width));
} else {
overlayItemTop = Math.max(overlayItemTop, rv.getPaddingTop());
overlayItemTop = Math.min(overlayItemTop, Math.max(0, rv.getHeight() - rv.getPaddingBottom() - draggingItemInfo.height));
}

switch (layoutType) {
case CustomRecyclerViewUtils.LAYOUT_TYPE_GRID_HORIZONTAL:
case CustomRecyclerViewUtils.LAYOUT_TYPE_GRID_VERTICAL:
swapTargetHolder = findSwapTargetItemForGridLayoutManager(
rv, draggingItem, draggingItemInfo, overlayItemLeft, overlayItemTop, range,
(layoutType == CustomRecyclerViewUtils.LAYOUT_TYPE_GRID_VERTICAL));
rv, draggingItem, draggingItemInfo, overlayItemLeft, overlayItemTop, range, isVerticalLayout);
break;
case CustomRecyclerViewUtils.LAYOUT_TYPE_LINEAR_HORIZONTAL:
swapTargetHolder = findSwapTargetItemForLinearLayoutManagerHorizontal(rv, draggingItem, draggingItemInfo, overlayItemLeft, overlayItemTop, range);
Expand Down Expand Up @@ -1364,10 +1366,10 @@ private static RecyclerView.ViewHolder findSwapTargetItemForGridLayoutManager(
int spanCount = CustomRecyclerViewUtils.getSpanCount(rv);
int height = rv.getHeight();
int width = rv.getWidth();
int paddingLeft = rv.getPaddingLeft();
int paddingTop = rv.getPaddingTop();
int paddingRight = rv.getPaddingRight();
int paddingBottom = rv.getPaddingBottom();
int paddingLeft = (vertical) ? rv.getPaddingLeft() : 0;
int paddingTop = (!vertical) ? rv.getPaddingTop() : 0;
int paddingRight = (vertical) ? rv.getPaddingRight() : 0;
int paddingBottom = (!vertical) ? rv.getPaddingBottom() : 0;
int columnWidth = (width - paddingLeft - paddingRight) / spanCount;
int rowHeight = (height - paddingTop - paddingBottom) / spanCount;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ public static int getLayoutType(@NonNull RecyclerView rv) {
return getLayoutType(rv.getLayoutManager());
}

public static int extractOrientation(int layoutType) {
switch (layoutType) {
case LAYOUT_TYPE_UNKNOWN:
return ORIENTATION_UNKNOWN;
case LAYOUT_TYPE_LINEAR_HORIZONTAL:
case LAYOUT_TYPE_GRID_HORIZONTAL:
case LAYOUT_TYPE_STAGGERED_GRID_HORIZONTAL:
return ORIENTATION_HORIZONTAL;
case LAYOUT_TYPE_LINEAR_VERTICAL:
case LAYOUT_TYPE_GRID_VERTICAL:
case LAYOUT_TYPE_STAGGERED_GRID_VERTICAL:
return ORIENTATION_VERTICAL;
default:
throw new IllegalArgumentException("Unknown layout type (= " + layoutType + ")");
}
}

public static int getLayoutType(@Nullable RecyclerView.LayoutManager layoutManager) {
if (layoutManager instanceof GridLayoutManager) {
if (((GridLayoutManager) layoutManager).getOrientation() == GridLayoutManager.HORIZONTAL) {
Expand Down Expand Up @@ -124,21 +141,29 @@ public static Rect getViewBounds(@NonNull View v, @NonNull Rect outBounds) {
}


public static int findFirstVisibleItemPosition(@NonNull RecyclerView rv) {
public static int findFirstVisibleItemPosition(@NonNull RecyclerView rv, boolean includesPadding) {
RecyclerView.LayoutManager layoutManager = rv.getLayoutManager();

if (layoutManager instanceof LinearLayoutManager) {
return (((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition());
if (includesPadding) {
return findFirstVisibleItemPositionIncludesPadding((LinearLayoutManager) layoutManager);
} else {
return (((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition());
}
} else {
return RecyclerView.NO_POSITION;
}
}

public static int findLastVisibleItemPosition(@NonNull RecyclerView rv) {
public static int findLastVisibleItemPosition(@NonNull RecyclerView rv, boolean includesPadding) {
RecyclerView.LayoutManager layoutManager = rv.getLayoutManager();

if (layoutManager instanceof LinearLayoutManager) {
return (((LinearLayoutManager) layoutManager).findLastVisibleItemPosition());
if (includesPadding) {
return findLastVisibleItemPositionIncludesPadding((LinearLayoutManager) layoutManager);
} else {
return (((LinearLayoutManager) layoutManager).findLastVisibleItemPosition());
}
} else {
return RecyclerView.NO_POSITION;
}
Expand Down Expand Up @@ -199,4 +224,42 @@ public static int getOrientation(@NonNull RecyclerView rv) {
return ORIENTATION_UNKNOWN;
}
}

private static int findFirstVisibleItemPositionIncludesPadding(LinearLayoutManager lm) {
final View child = findOneVisibleChildIncludesPadding(lm, 0, lm.getChildCount(), false, true);
return child == null ? RecyclerView.NO_POSITION : lm.getPosition(child);
}

private static int findLastVisibleItemPositionIncludesPadding(LinearLayoutManager lm) {
final View child = findOneVisibleChildIncludesPadding(lm, lm.getChildCount() - 1, -1, false, true);
return child == null ? RecyclerView.NO_POSITION : lm.getPosition(child);
}

// This method is a modified version of the LinearLayoutManager.findOneVisibleChild().
private static View findOneVisibleChildIncludesPadding(
LinearLayoutManager lm, int fromIndex, int toIndex,
boolean completelyVisible, boolean acceptPartiallyVisible) {
boolean isVertical = (lm.getOrientation() == LinearLayoutManager.VERTICAL);
final int start = 0;
final int end = (isVertical) ? lm.getHeight() : lm.getWidth();
final int next = toIndex > fromIndex ? 1 : -1;
View partiallyVisible = null;
for (int i = fromIndex; i != toIndex; i += next) {
final View child = lm.getChildAt(i);
final int childStart = (isVertical) ? child.getTop() : child.getLeft();
final int childEnd = (isVertical) ? child.getBottom() : child.getRight();
if (childStart < end && childEnd > start) {
if (completelyVisible) {
if (childStart >= start && childEnd <= end) {
return child;
} else if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
} else {
return child;
}
}
}
return partiallyVisible;
}
}

0 comments on commit bd344ff

Please sign in to comment.