From e484414e258e9668afc174e56b4ed40616d73637 Mon Sep 17 00:00:00 2001 From: longerian Date: Sun, 14 May 2017 14:42:47 +0800 Subject: [PATCH] fix #63 #57 provide default handler to layoutHelper background --- .../vlayout/layout/BaseLayoutHelper.java | 85 ++++++++++++++++++- .../vlayout/layout/RangeGridLayoutHelper.java | 5 ++ .../android/vlayout/layout/RangeStyle.java | 14 ++- vlayout/src/main/res/values/ids.xml | 4 + 4 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 vlayout/src/main/res/values/ids.xml diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java index 1a47497f..28eb8c33 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java @@ -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; @@ -89,6 +90,7 @@ public int getItemCount() { return mItemCount; } + @Override public void setItemCount(int itemCount) { this.mItemCount = itemCount; } @@ -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; } @@ -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); } } @@ -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; } @@ -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; @@ -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(); diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java index dd75a60b..559d2ce4 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java @@ -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); diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java index f5ffa031..88ba8764 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java @@ -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; @@ -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; } @@ -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; } @@ -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; } diff --git a/vlayout/src/main/res/values/ids.xml b/vlayout/src/main/res/values/ids.xml new file mode 100644 index 00000000..38a76141 --- /dev/null +++ b/vlayout/src/main/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file