Skip to content
This repository has been archived by the owner on Jul 14, 2021. It is now read-only.

Commit

Permalink
Merge branch 'feature/range_grid_layout_helper' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
longerian committed May 14, 2017
2 parents b6233c5 + 3abeb46 commit de4e996
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 41 deletions.
7 changes: 5 additions & 2 deletions README-ch.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,11 @@ recycler.setAdapter(myAdapter);

```
-keepattributes InnerClasses
-keep class com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx {
*;
-keep class com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx { *; }
-keep class android.support.v7.widget.RecyclerView$LayoutParams { *; }
-keep class android.support.v7.widget.RecyclerView$ViewHolder { *; }
-keep class android.support.v7.widget.ChildHelper { *; }
-keep class android.support.v7.widget.RecyclerView$LayoutManager { *; }
```

# Demo
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,11 @@ Add following configs in your proguard file if your app is released with proguar

```
-keepattributes InnerClasses
-keep class com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx {
*;
-keep class com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx { *; }
-keep class android.support.v7.widget.RecyclerView$LayoutParams { *; }
-keep class android.support.v7.widget.RecyclerView$ViewHolder { *; }
-keep class android.support.v7.widget.ChildHelper { *; }
-keep class android.support.v7.widget.RecyclerView$LayoutManager { *; }
```

# Demo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.alibaba.android.vlayout.layout;

import com.alibaba.android.vlayout.LayoutManagerHelper;
import com.alibaba.android.vlayout.R;
import com.alibaba.android.vlayout.VirtualLayoutManager;
import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutStateWrapper;

Expand Down Expand Up @@ -89,6 +90,7 @@ public int getItemCount() {
return mItemCount;
}

@Override
public void setItemCount(int itemCount) {
this.mItemCount = itemCount;
}
Expand Down Expand Up @@ -138,6 +140,9 @@ public void beforeLayout(RecyclerView.Recycler recycler, RecyclerView.State stat
} else {
// if no layoutView is required, remove it
if (mLayoutView != null) {
if (mLayoutViewUnBindListener != null) {
mLayoutViewUnBindListener.onUnbind(mLayoutView, this);
}
helper.removeChildView(mLayoutView);
mLayoutView = null;
}
Expand Down Expand Up @@ -173,9 +178,9 @@ public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state

if (!mLayoutRegion.isEmpty()) {
if (isValidScrolled(scrolled)) {
if (helper.getOrientation() == VirtualLayoutManager.VERTICAL)
if (helper.getOrientation() == VirtualLayoutManager.VERTICAL) {
mLayoutRegion.offset(0, -scrolled);
else {
} else {
mLayoutRegion.offset(-scrolled, 0);
}
}
Expand Down Expand Up @@ -230,6 +235,9 @@ public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state
public final void clear(LayoutManagerHelper helper) {
// remove LayoutViews if there is one
if (mLayoutView != null) {
if (mLayoutViewUnBindListener != null) {
mLayoutViewUnBindListener.onUnbind(mLayoutView, this);
}
helper.removeChildView(mLayoutView);
mLayoutView = null;
}
Expand Down Expand Up @@ -309,14 +317,83 @@ public interface LayoutViewUnBindListener {
void onUnbind(View layoutView, BaseLayoutHelper baseLayoutHelper);
}


public interface LayoutViewHelper {

/**
* Implement it by maintaining a map between layoutView and image url or setting a unique tag to view. It's up to your choice.
* @param layoutView view ready to be binded with an image
* * @param id layoutView's identifier
*/
void onBindViewSuccess(View layoutView, String id);
}

private LayoutViewUnBindListener mLayoutViewUnBindListener;

private LayoutViewBindListener mLayoutViewBindListener;

/**
* Helper to decide whether call {@link LayoutViewBindListener#onBind(View, BaseLayoutHelper)}.
* Here is a performance issue: {@link LayoutViewBindListener#onBind(View, BaseLayoutHelper)} is called during layout phase,
* when binding image to it would cause view tree to relayout, then the same {@link LayoutViewBindListener#onBind(View, BaseLayoutHelper)} would be called.
* User should provide enough information to tell LayoutHelper whether image has been bind success.
* If image has been successfully binded , no more dead loop happens.
*
* Of course you can handle this logic by yourself and ignore this helper.
*/
public static class DefaultLayoutViewHelper implements LayoutViewBindListener, LayoutViewUnBindListener, LayoutViewHelper {

private final LayoutViewBindListener mLayoutViewBindListener;

private final LayoutViewUnBindListener mLayoutViewUnBindListener;

public DefaultLayoutViewHelper(
LayoutViewBindListener layoutViewBindListener,
LayoutViewUnBindListener layoutViewUnBindListener) {
mLayoutViewBindListener = layoutViewBindListener;
mLayoutViewUnBindListener = layoutViewUnBindListener;
}

@Override
public void onBindViewSuccess(View layoutView, String id) {
layoutView.setTag(R.id.tag_layout_helper_bg, id);
}

@Override
public void onBind(View layoutView, BaseLayoutHelper baseLayoutHelper) {
if (layoutView.getTag(R.id.tag_layout_helper_bg) == null) {
if (mLayoutViewBindListener != null) {
mLayoutViewBindListener.onBind(layoutView, baseLayoutHelper);
}
}
}

@Override
public void onUnbind(View layoutView, BaseLayoutHelper baseLayoutHelper) {
if (mLayoutViewUnBindListener != null) {
mLayoutViewUnBindListener.onUnbind(layoutView, baseLayoutHelper);
}
layoutView.setTag(R.id.tag_layout_helper_bg, null);
}
}

public void setLayoutViewHelper(DefaultLayoutViewHelper layoutViewHelper) {
mLayoutViewBindListener = layoutViewHelper;
mLayoutViewUnBindListener = layoutViewHelper;
}

/**
* Better to use {@link #setLayoutViewHelper(DefaultLayoutViewHelper)}
* @param bindListener
*/
public void setLayoutViewBindListener(LayoutViewBindListener bindListener) {
mLayoutViewBindListener = bindListener;
}

/**
* Better to use {@link #setLayoutViewHelper(DefaultLayoutViewHelper)}
* @param layoutViewUnBindListener
*/
public void setLayoutViewUnBindListener(
LayoutViewUnBindListener layoutViewUnBindListener) {
mLayoutViewUnBindListener = layoutViewUnBindListener;
Expand All @@ -338,7 +415,9 @@ public void bindLayoutView(@NonNull final View layoutView) {
}

protected void handleStateOnResult(LayoutChunkResult result, View view) {
if (view == null) return;
if (view == null) {
return;
}

RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
* @since 1.0.0
*/
public class RangeGridLayoutHelper extends BaseLayoutHelper {
private static final String TAG = "RangeGridLayoutHelper";
private static final String TAG = "RGLayoutHelper";

@SuppressWarnings("FieldCanBeLocal")
private static boolean DEBUG = false;
Expand Down Expand Up @@ -189,6 +189,11 @@ public void setBgColor(int bgColor) {
mRangeStyle.setBgColor(bgColor);
}

@Override
public void setLayoutViewHelper(DefaultLayoutViewHelper layoutViewHelper) {
mRangeStyle.setLayoutViewHelper(layoutViewHelper);
}

@Override
public void setLayoutViewBindListener(LayoutViewBindListener bindListener) {
mRangeStyle.setLayoutViewBindListener(bindListener);
Expand Down Expand Up @@ -532,12 +537,12 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state
if (isSecondStartLine) {
consumedGap = (layoutInVertical ? rangeStyle.mParent.mVGap : rangeStyle.mParent.mHGap);
if (DEBUG) {
Log.d(TAG, "--> " + currentPosition + " 1 " + consumedGap + " gap");
Log.d(TAG, " " + currentPosition + " 1 " + consumedGap + " gap");
}
} else {
consumedGap = (layoutInVertical ? rangeStyle.mVGap : rangeStyle.mHGap);
if (DEBUG) {
Log.d(TAG, "--> " + currentPosition + " 2 " + consumedGap + " gap");
Log.d(TAG, " " + currentPosition + " 2 " + consumedGap + " gap");
}
}
}
Expand All @@ -546,12 +551,12 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state
if (isSecondEndLine) {
consumedGap = (layoutInVertical ? rangeStyle.mParent.mVGap : rangeStyle.mParent.mHGap);
if (DEBUG) {
Log.d(TAG, "--> " + currentPosition + " 3 " + consumedGap + " gap");
Log.d(TAG, " " + currentPosition + " 3 " + consumedGap + " gap");
}
} else {
consumedGap = (layoutInVertical ? rangeStyle.mVGap : rangeStyle.mHGap);
if (DEBUG) {
Log.d(TAG, "--> " + currentPosition + " 4 " + consumedGap + " gap");
Log.d(TAG, " " + currentPosition + " 4 " + consumedGap + " gap");
}
}
}
Expand All @@ -560,35 +565,47 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state
result.mConsumed += consumedGap;

int lastUnconsumedSpace = 0;
if (layoutStart) {
int lastLinePosition = currentPosition + 1;
if (!isOutOfRange(lastLinePosition)) {
RangeStyle<GridRangeStyle> neighbourRange = mRangeStyle.findRangeStyleByPosition(lastLinePosition);
if (neighbourRange.isFirstPosition(lastLinePosition)) {
lastUnconsumedSpace = layoutInVertical ? neighbourRange.getMarginTop() + neighbourRange.getPaddingTop()
: neighbourRange.getMarginLeft() + neighbourRange.getPaddingLeft();
if (DEBUG) {
Log.d(TAG, "--> " + currentPosition + " 1 " + lastUnconsumedSpace);
/** layoutView() may be triggered by layoutManager's scrollInternalBy() or onFocusSearchFailed() or onLayoutChildren()
*
* In case of scrollInternalBy() or onFocusSearchFailed(), layoutState.isRefreshLayout() == false, and layoutState.mOffset = ChildClosestToExpose + alignOffset,
* see {@link com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx#updateLayoutStateExpose(int, int, boolean, State)},
* this means last line's layout padding or margin is not really consumed, so considering it before layout new line.
*
* In case of onLayoutChildren(), layoutState.isRefreshLayout() == true, and layoutState.mOffset = anchorInfo.mCoordinate = anchorChild.start + alignOffset,
* see {@link com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx#updateAnchorInfoForLayoutExpose(State, AnchorInfo)},
* this means last line's layout padding or margin is consumed.
**/
if (!layoutState.isRefreshLayout()) {
if (layoutStart) {
int lastLinePosition = currentPosition + 1;
if (!isOutOfRange(lastLinePosition)) {
RangeStyle<GridRangeStyle> neighbourRange = mRangeStyle.findRangeStyleByPosition(lastLinePosition);
if (neighbourRange.isFirstPosition(lastLinePosition)) {
lastUnconsumedSpace = layoutInVertical ? neighbourRange.getMarginTop() + neighbourRange.getPaddingTop()
: neighbourRange.getMarginLeft() + neighbourRange.getPaddingLeft();
if (DEBUG) {
Log.d(TAG, "⬆ " + currentPosition + " 1 " + lastUnconsumedSpace + " last");
}
}
}
}
} else {
int lastLinePosition = currentPosition - 1;
if (!isOutOfRange(lastLinePosition)) {
RangeStyle<GridRangeStyle> neighbourRange = mRangeStyle.findRangeStyleByPosition(lastLinePosition);
if (neighbourRange.isLastPosition(lastLinePosition)) {
lastUnconsumedSpace = layoutInVertical ? neighbourRange.getMarginBottom() + neighbourRange.getPaddingBottom()
: neighbourRange.getMarginRight() + neighbourRange.getPaddingRight();
if (DEBUG) {
Log.d(TAG, "--> " + currentPosition + " 2 " + lastUnconsumedSpace);
} else {
int lastLinePosition = currentPosition - 1;
if (!isOutOfRange(lastLinePosition)) {
RangeStyle<GridRangeStyle> neighbourRange = mRangeStyle.findRangeStyleByPosition(lastLinePosition);
if (neighbourRange.isLastPosition(lastLinePosition)) {
lastUnconsumedSpace = layoutInVertical ? neighbourRange.getMarginBottom() + neighbourRange.getPaddingBottom()
: neighbourRange.getMarginRight() + neighbourRange.getPaddingRight();
if (DEBUG) {
Log.d(TAG, "⬇ " + currentPosition + " 2 " + lastUnconsumedSpace + " last");
}
}
}
}
}

if (DEBUG) {
Log.d(TAG,
"--> " + currentPosition + " consumed " + result.mConsumed + " startSpace " + startSpace + " endSpace "
(layoutStart ? "⬆ " : "⬇ ") + currentPosition + " consumed " + result.mConsumed + " startSpace " + startSpace + " endSpace "
+ endSpace + " secondStartSpace " + secondStartSpace + " secondEndSpace " + secondEndSpace + " lastUnconsumedSpace " + lastUnconsumedSpace);
}

Expand All @@ -603,10 +620,10 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state
}
} else {
if (layoutStart) {
right = layoutState.getOffset() - endSpace - (consumedGap);
right = layoutState.getOffset() - endSpace - (consumedGap) - lastUnconsumedSpace;
left = right - maxSize;
} else {
left = layoutState.getOffset() + startSpace + (consumedGap);
left = layoutState.getOffset() + startSpace + (consumedGap) + lastUnconsumedSpace;
right = left + maxSize;
}
}
Expand Down Expand Up @@ -676,14 +693,13 @@ public void afterLayout(Recycler recycler, State state, int startPosition, int e
@Override
public int computeAlignOffset(int offset, boolean isLayoutEnd, boolean useAnchor, LayoutManagerHelper helper) {
final boolean layoutInVertical = helper.getOrientation() == VERTICAL;

if (isLayoutEnd) {
if (offset == getItemCount() - 1) {
return mRangeStyle.computeEndAlignOffset(layoutInVertical);
return mRangeStyle.computeEndAlignOffset(layoutInVertical, isLayoutEnd, useAnchor, helper);
}
} else {
if (offset == 0) {
return mRangeStyle.computeStartAlignOffset(layoutInVertical);
return mRangeStyle.computeStartAlignOffset(layoutInVertical, isLayoutEnd, useAnchor, helper);
}
}

Expand Down Expand Up @@ -902,7 +918,7 @@ public void onInvalidateSpanIndexCache() {
}

//TODO compute align itr
public int computeEndAlignOffset(boolean layoutInVertical) {
public int computeEndAlignOffset(boolean layoutInVertical, boolean isLayoutEnd, boolean useAnchor, LayoutManagerHelper helper) {
int offset = layoutInVertical ? mMarginBottom + mPaddingBottom : mMarginRight + mPaddingRight;
int endPosition = mRange.getUpper().intValue();
for (int i = 0, size = mChildren.size(); i < size; i++) {
Expand All @@ -917,7 +933,7 @@ public int computeEndAlignOffset(boolean layoutInVertical) {
}

//TODO compute align itr
public int computeStartAlignOffset(boolean layoutInVertical) {
public int computeStartAlignOffset(boolean layoutInVertical, boolean isLayoutEnd, boolean useAnchor, LayoutManagerHelper helper) {
int offset = layoutInVertical ? -mMarginTop - mPaddingTop : -mMarginLeft - mPaddingLeft;
int startPosition = mRange.getLower().intValue();
for (int i = 0, size = mChildren.size(); i < size; i++) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package com.alibaba.android.vlayout.layout;

import java.lang.reflect.Array;
import java.util.Arrays;

import com.alibaba.android.vlayout.LayoutManagerHelper;
import com.alibaba.android.vlayout.Range;
import com.alibaba.android.vlayout.VirtualLayoutManager;
import com.alibaba.android.vlayout.layout.BaseLayoutHelper.DefaultLayoutViewHelper;
import com.alibaba.android.vlayout.layout.BaseLayoutHelper.LayoutViewBindListener;
import com.alibaba.android.vlayout.layout.BaseLayoutHelper.LayoutViewUnBindListener;

import android.graphics.Rect;
import android.os.Parcelable.ClassLoaderCreator;
import android.support.annotation.NonNull;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.SimpleArrayMap;
Expand Down Expand Up @@ -379,6 +378,9 @@ public void beforeLayout(RecyclerView.Recycler recycler, RecyclerView.State stat
} else {
// if no layoutView is required, remove it
if (mLayoutView != null) {
if (mLayoutViewUnBindListener != null) {
mLayoutViewUnBindListener.onUnbind(mLayoutView, getLayoutHelper());
}
helper.removeChildView(mLayoutView);
mLayoutView = null;
}
Expand Down Expand Up @@ -515,6 +517,11 @@ public void bindLayoutView(@NonNull final View layoutView) {
mLayoutRegion.set(0, 0, 0, 0);
}

public void setLayoutViewHelper(DefaultLayoutViewHelper layoutViewHelper) {
mLayoutViewBindListener = layoutViewHelper;
mLayoutViewUnBindListener = layoutViewHelper;
}

public void setLayoutViewBindListener(LayoutViewBindListener bindListener) {
mLayoutViewBindListener = bindListener;
}
Expand All @@ -530,6 +537,9 @@ public void setBgColor(int bgColor) {

public void onClear(LayoutManagerHelper helper) {
if (mLayoutView != null) {
if (mLayoutViewUnBindListener != null) {
mLayoutViewUnBindListener.onUnbind(mLayoutView, getLayoutHelper());
}
helper.removeChildView(mLayoutView);
mLayoutView = null;
}
Expand Down
4 changes: 4 additions & 0 deletions vlayout/src/main/res/values/ids.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="tag_layout_helper_bg" type="id" />
</resources>

0 comments on commit de4e996

Please sign in to comment.