Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for item margin #15

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ private void addAndMeasureChild(final View child, int viewPos) {
* @param child The child.
*/
private void measureChild(View child) {
ViewGroup.LayoutParams childLayoutParams = getLayoutParams(child);
LayoutParams childLayoutParams = getLayoutParams(child);
int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, getPaddingTop() + getPaddingBottom(), childLayoutParams.height);

int childWidthSpec;
Expand All @@ -494,16 +494,27 @@ private void measureChild(View child) {
}

/** Gets a child's layout parameters, defaults if not available. */
private ViewGroup.LayoutParams getLayoutParams(View child) {
ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
private LayoutParams getLayoutParams(View child) {
LayoutParams layoutParams = child.getLayoutParams();
if (layoutParams == null) {
// Since this is a horizontal list view default to matching the parents height, and wrapping the width
layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
}

return layoutParams;
}

/**
* Gets a child's margin layout parameters, null if not available
*/
private MarginLayoutParams getMarginLayoutParams(View view) {
MarginLayoutParams params = null;
if (view != null && getLayoutParams(view) instanceof MarginLayoutParams) {
params = (MarginLayoutParams) getLayoutParams(view);
}
return params;
}

@SuppressLint("WrongCall")
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Expand Down Expand Up @@ -667,6 +678,10 @@ private boolean determineMaxX() {

// Determine the maximum x position
mMaxX = mCurrentX + (rightView.getRight() - getPaddingLeft()) - getRenderWidth();
MarginLayoutParams params = getMarginLayoutParams(rightView);
if (params != null) {
mMaxX += params.rightMargin;
}

// Handle the case where the views do not fill at least 1 screen
if (mMaxX < 0) {
Expand All @@ -684,11 +699,16 @@ private boolean determineMaxX() {

/** Adds children views to the left and right of the current views until the screen is full */
private void fillList(final int dx) {
MarginLayoutParams params;
// Get the rightmost child and determine its right edge
int edge = 0;
View child = getRightmostChild();
if (child != null) {
edge = child.getRight();
params = getMarginLayoutParams(child);
if (params != null) {
edge -= params.rightMargin;
}
}

// Add new children views to the right, until past the edge of the screen
Expand All @@ -699,21 +719,33 @@ private void fillList(final int dx) {
child = getLeftmostChild();
if (child != null) {
edge = child.getLeft();
params = getMarginLayoutParams(child);
if (params != null) {
edge -= params.leftMargin;
}
}

// Add new children views to the left, until past the edge of the screen
fillListLeft(edge, dx);
}

private void removeNonVisibleChildren(final int dx) {
int rightMargin = 0;
View child = getLeftmostChild();
MarginLayoutParams params = getMarginLayoutParams(child);
if (params != null) {
rightMargin = params.rightMargin;
}

// Loop removing the leftmost child, until that child is on the screen
while (child != null && child.getRight() + dx <= 0) {
while (child != null && child.getRight() + rightMargin + dx <= 0) {
// The child is being completely removed so remove its width from the display offset and its divider if it has one.
// To remove add the size of the child and its divider (if it has one) to the offset.
// You need to add since its being removed from the left side, i.e. shifting the offset to the right.
mDisplayOffset += isLastItemInAdapter(mLeftViewAdapterIndex) ? child.getMeasuredWidth() : mDividerWidth + child.getMeasuredWidth();
if (params != null) {
mDisplayOffset += params.rightMargin;
}

// Add the removed view to the cache
recycleView(mLeftViewAdapterIndex, child);
Expand All @@ -726,6 +758,10 @@ private void removeNonVisibleChildren(final int dx) {

// Get the new leftmost child
child = getLeftmostChild();
params = getMarginLayoutParams(child);
if (params != null) {
mDisplayOffset += params.leftMargin;
}
}

child = getRightmostChild();
Expand Down Expand Up @@ -766,13 +802,17 @@ private void fillListLeft(int leftEdge, final int dx) {
while (leftEdge + dx - mDividerWidth > 0 && mLeftViewAdapterIndex >= 1) {
mLeftViewAdapterIndex--;
View child = mAdapter.getView(mLeftViewAdapterIndex, getRecycledView(mLeftViewAdapterIndex), this);
MarginLayoutParams params = getMarginLayoutParams(child);
addAndMeasureChild(child, INSERT_AT_START_OF_LIST);

// If first view, then no divider to the left of it
leftEdge -= mLeftViewAdapterIndex == 0 ? child.getMeasuredWidth() : mDividerWidth + child.getMeasuredWidth();

// If on a clean edge then just remove the child, otherwise remove the divider as well
mDisplayOffset -= leftEdge + dx == 0 ? child.getMeasuredWidth() : mDividerWidth + child.getMeasuredWidth();
if (params != null) {
mDisplayOffset -= (params.leftMargin + params.rightMargin);
}
}
}

Expand All @@ -786,17 +826,31 @@ private void positionChildren(final int dx) {

// Loop each child view
for (int i = 0; i < childCount; i++) {
int left;
int top;
int right;
int bottom;
View child = getChildAt(i);
int left = leftOffset + getPaddingLeft();
int top = getPaddingTop();
int right = left + child.getMeasuredWidth();
int bottom = top + child.getMeasuredHeight();

left = leftOffset + child.getPaddingLeft();
top = child.getPaddingTop();
MarginLayoutParams params = getMarginLayoutParams(child);
if (params != null) {
left += params.leftMargin;
top += params.topMargin;
}
right = left + child.getMeasuredWidth();
bottom = top + child.getMeasuredHeight();

// Layout the child
child.layout(left, top, right, bottom);

// Increment our offset by added child's size and divider width
leftOffset += child.getMeasuredWidth() + mDividerWidth;
if (params != null) {
leftOffset += child.getMeasuredWidth() + mDividerWidth + params.leftMargin + params.rightMargin;
} else {
leftOffset += child.getMeasuredWidth() + mDividerWidth;
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Notice you set the `dividerWidth` via the XML namespace you just defined as it i
## Contributors

- [Bill Donahue](https://github.com/bdonahue)
- [Peter Siegmund](https://github.com/mars3142)

## Licenses

Expand Down