You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by gu...@apache.org on 2017/10/17 07:49:00 UTC

[2/6] incubator-weex git commit: sticky offset supported, keep position lost when insert data fix

sticky offset supported, keep position lost when insert data fix


Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/cb1df915
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/cb1df915
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/cb1df915

Branch: refs/heads/master
Commit: cb1df915b867e6f549266b51d3d28c32dbb44a31
Parents: 45ae6f6
Author: jianbai.gbj <ji...@alibaba-inc.com>
Authored: Mon Oct 16 13:59:17 2017 +0800
Committer: gurisxie <27...@qq.com>
Committed: Tue Oct 17 15:48:46 2017 +0800

----------------------------------------------------------------------
 .../java/com/taobao/weex/common/Constants.java  |   3 +
 .../ui/component/list/BasicListComponent.java   | 114 ++++++++++++++-----
 .../ui/component/list/StickyHeaderHelper.java   |  43 ++++++-
 .../taobao/weex/ui/component/list/WXCell.java   |  92 +++++++--------
 .../list/template/WXRecyclerTemplateList.java   |   2 +-
 5 files changed, 178 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cb1df915/android/sdk/src/main/java/com/taobao/weex/common/Constants.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/Constants.java b/android/sdk/src/main/java/com/taobao/weex/common/Constants.java
index e74e083..730ce84 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/Constants.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/Constants.java
@@ -182,6 +182,9 @@ public class Constants {
     String ARIA_LABEL = "ariaLabel";
     String ARIA_HIDDEN = "ariaHidden";
 
+    String STICKY_OFFSET = "stickyOffset";
+    String HAS_FIXED_SIZE = "hasFixedSize";
+    String KEEP_POSITION_LAYOUT_DELAY = "keepPositionLayoutDelay";
 
     interface  Recycler{
       String LIST_DATA = "listData";

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cb1df915/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
index 640a17e..5649832 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/BasicListComponent.java
@@ -150,6 +150,15 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
   private WXStickyHelper stickyHelper;
 
 
+
+  /**
+   * keep positon
+   * */
+  private  WXComponent keepPositionCell = null;
+  private  Runnable keepPositionCellRunnable = null;
+  private  long keepPositionLayoutDelay = 150;
+
+
   public BasicListComponent(WXSDKInstance instance, WXDomObject node, WXVContainer parent) {
     super(instance, node, parent);
     stickyHelper = new WXStickyHelper(this);
@@ -236,6 +245,9 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
     if (transforms != null) {
       bounceRecyclerView.getInnerView().addItemDecoration(RecyclerTransform.parseTransforms(getOrientation(), transforms));
     }
+    if(getDomObject().getAttrs().get(Constants.Name.KEEP_POSITION_LAYOUT_DELAY) != null){
+      keepPositionLayoutDelay = WXUtils.getNumberInt(getDomObject().getAttrs().get(Constants.Name.KEEP_POSITION_LAYOUT_DELAY), (int)keepPositionLayoutDelay);
+    }
 
     mItemAnimator=bounceRecyclerView.getInnerView().getItemAnimator();
 
@@ -245,6 +257,10 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
     bounceRecyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
     bounceRecyclerView.getInnerView().clearOnScrollListeners();
     bounceRecyclerView.getInnerView().addOnScrollListener(mViewOnScrollListener);
+    if(getDomObject().getAttrs().get(Constants.Name.HAS_FIXED_SIZE) != null){
+      boolean hasFixedSize = WXUtils.getBoolean(getDomObject().getAttrs().get(Constants.Name.HAS_FIXED_SIZE), false);
+      bounceRecyclerView.getInnerView().setHasFixedSize(hasFixedSize);
+    }
     bounceRecyclerView.getInnerView().addOnScrollListener(new RecyclerView.OnScrollListener() {
       @Override
       public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
@@ -485,53 +501,54 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
       if (stickyComponent != null && stickyComponent.getDomObject() != null
           && stickyComponent instanceof WXCell) {
 
-        WXCell cell = (WXCell) stickyComponent;
-        if (cell.getHostView() == null) {
-          return;
-        }
+          WXCell cell = (WXCell) stickyComponent;
+          if (cell.getHostView() == null) {
+            return;
+          }
+
+          int[] location = new int[2];
+          stickyComponent.getHostView().getLocationOnScreen(location);
+          int[] parentLocation = new int[2];
+          stickyComponent.getParentScroller().getView().getLocationOnScreen(parentLocation);
+          int top = location[1] - parentLocation[1];
+
 
           RecyclerView.LayoutManager layoutManager;
           boolean beforeFirstVisibleItem = false;
           boolean removeOldSticky = false;
           layoutManager = getHostView().getInnerView().getLayoutManager();
           if (layoutManager instanceof LinearLayoutManager || layoutManager instanceof GridLayoutManager) {
-            int fVisible = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
+            int firstVisiblePosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
+            int lastVisiblePosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
             int pos = mChildren.indexOf(cell);
             cell.setScrollPositon(pos);
-
-            if (pos <= fVisible) {
+            if (pos <= firstVisiblePosition
+                    || (cell.getStickyOffset() > 0 && firstVisiblePosition < pos && pos <= lastVisiblePosition  &&
+                    top <= cell.getStickyOffset())) {
               beforeFirstVisibleItem = true;
               if(pos > currentStickyPos) {
                 currentStickyPos = pos;
               }
-            }
-
-            if(pos > fVisible){
+            }else{
               removeOldSticky = true;
             }
           } else if(layoutManager instanceof StaggeredGridLayoutManager){
             int [] firstItems= new int[3];
-            int fVisible = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(firstItems)[0];
+            int firstVisiblePosition = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(firstItems)[0];
+            int lastVisiblePosition = ((StaggeredGridLayoutManager)  layoutManager).findLastVisibleItemPositions(firstItems)[0];
             int pos = mChildren.indexOf(cell);
 
-            if (pos <= fVisible) {
+            if (pos <= firstVisiblePosition || (cell.getStickyOffset() > 0 && firstVisiblePosition < pos && pos <= lastVisiblePosition  &&
+                    top <= cell.getStickyOffset())) {
               beforeFirstVisibleItem = true;
-            }
-
-            if(pos > fVisible){
+            }else{
               removeOldSticky = true;
             }
           }
 
-          int[] location = new int[2];
-          stickyComponent.getHostView().getLocationOnScreen(location);
-          int[] parentLocation = new int[2];
-          stickyComponent.getParentScroller().getView().getLocationOnScreen(parentLocation);
-
-          int top = location[1] - parentLocation[1];
 
-          boolean showSticky = beforeFirstVisibleItem && cell.getLocationFromStart() >= 0 && top <= 0 && dy >= 0;
-          boolean removeSticky = cell.getLocationFromStart() <= 0 && top > 0 && dy <= 0;
+          boolean showSticky = beforeFirstVisibleItem && cell.getLocationFromStart() >= 0 && top <= cell.getStickyOffset() && dy >= 0;
+          boolean removeSticky = cell.getLocationFromStart() <= cell.getStickyOffset() && top > cell.getStickyOffset() && dy <= 0;
           if (showSticky) {
             bounceRecyclerView.notifyStickyShow(cell);
           } else if (removeSticky || removeOldSticky) {
@@ -584,7 +601,6 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
   @Override
   public void addChild(WXComponent child, int index) {
     super.addChild(child, index);
-
     if (child == null || index < -1) {
       return;
     }
@@ -593,7 +609,7 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
     bindViewType(child);
 
     int adapterPosition = index == -1 ? mChildren.size() - 1 : index;
-    T view = getHostView();
+    final T view = getHostView();
     if (view != null) {
       boolean isAddAnimation = false;
       ImmutableDomObject domObject = child.getDomObject();
@@ -616,9 +632,52 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
         }
       }
       if (isKeepScrollPosition) {
-        int last=((LinearLayoutManager)view.getInnerView().getLayoutManager()).findLastVisibleItemPosition();
-        view.getInnerView().getLayoutManager().scrollToPosition(last);
+        if(view.getInnerView().getLayoutManager() instanceof  LinearLayoutManager){
+            if(!view.getInnerView().isLayoutFrozen()){ //frozen, prevent layout when scroll
+                view.getInnerView().setLayoutFrozen(true);
+            }
+            if(keepPositionCell == null){
+              int last=((LinearLayoutManager)view.getInnerView().getLayoutManager()).findLastCompletelyVisibleItemPosition();
+              ListBaseViewHolder holder = (ListBaseViewHolder) view.getInnerView().findViewHolderForAdapterPosition(last);
+              if(holder != null){
+                 keepPositionCell = holder.getComponent();
+              }
+              if(keepPositionCell != null) {
+                if(keepPositionCellRunnable != null){
+                  view.removeCallbacks(keepPositionCellRunnable);
+                }
+                keepPositionCellRunnable = new Runnable() {
+                  @Override
+                  public void run() {
+                    if(keepPositionCell != null){
+                      int keepPosition = indexOf(keepPositionCell);
+                      int offset = 0;
+                      if(keepPositionCell.getHostView() != null){
+                        offset = keepPositionCell.getHostView().getTop();
+                      }
+                      if(offset > 0) {
+                        ((LinearLayoutManager) view.getInnerView().getLayoutManager()).scrollToPositionWithOffset(keepPosition, offset);
+                      }else{
+                        view.getInnerView().getLayoutManager().scrollToPosition(keepPosition);
+
+                      }
+                      view.getInnerView().setLayoutFrozen(false);
+                      keepPositionCell = null;
+                      keepPositionCellRunnable = null;
+                    }
+                  }
+                };
+              }
+            }
+            if(keepPositionCellRunnable == null){
+               view.getInnerView().scrollToPosition(((LinearLayoutManager)view.getInnerView().getLayoutManager()).findLastVisibleItemPosition());
+            }
+        }
         view.getRecyclerViewBaseAdapter().notifyItemInserted(adapterPosition);
+        if(keepPositionCellRunnable != null){
+          view.removeCallbacks(keepPositionCellRunnable);
+          view.postDelayed(keepPositionCellRunnable, keepPositionLayoutDelay);
+        }
       } else {
         view.getRecyclerViewBaseAdapter().notifyItemChanged(adapterPosition);
       }
@@ -628,6 +687,7 @@ public abstract class BasicListComponent<T extends ViewGroup & ListComponentView
 
 
 
+
   private void relocateAppearanceHelper() {
     Iterator<Map.Entry<String, AppearanceHelper>> iterator = mAppearComponents.entrySet().iterator();
     while (iterator.hasNext()) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cb1df915/android/sdk/src/main/java/com/taobao/weex/ui/component/list/StickyHeaderHelper.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/StickyHeaderHelper.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/StickyHeaderHelper.java
index 1534013..cedd86c 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/StickyHeaderHelper.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/StickyHeaderHelper.java
@@ -21,6 +21,7 @@ package com.taobao.weex.ui.component.list;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.common.WXThread;
 import com.taobao.weex.utils.WXLogUtils;
 
@@ -87,12 +88,20 @@ public class StickyHeaderHelper {
         if ((existedParent = (ViewGroup) headerView.getParent()) != null) {
           existedParent.removeView(headerView);
         }
+        headerView.setTag(headComponent.getRef());
         mParent.addView(headerView);
+        headerView.setTag(this);
+        if(headComponent.getStickyOffset() > 0) {
+          ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) headerView.getLayoutParams();
+          if(headComponent.getStickyOffset() != params.topMargin) {
+            params.topMargin = headComponent.getStickyOffset();
+          }
+        }
         //recover translation, sometimes it will be changed on fling
         headerView.setTranslationX(translationX);
         headerView.setTranslationY(translationY);
-
       }
+      changeFrontStickyVisible();
       if (headComponent.getDomObject().getEvents().contains("sticky")) {
         headComponent.fireEvent("sticky");
       }
@@ -108,7 +117,8 @@ public class StickyHeaderHelper {
 
 
     if(component == null || headerView == null){
-      WXLogUtils.e(" sticky header to remove not found."+compToRemove.getRef());
+      if(WXEnvironment.isApkDebugable()) {
+      }
       return;
     }
     if(mCurrentStickyRef != null && mCurrentStickyRef.equals(compToRemove.getRef())){
@@ -118,7 +128,12 @@ public class StickyHeaderHelper {
       @Override
       public void run() {
         mParent.removeView(headerView);
+        if(headerView.getVisibility() != View.VISIBLE){
+           headerView.setVisibility(View.VISIBLE);
+        }
         component.recoverySticky();
+        changeFrontStickyVisible();
+
       }
     }));
     if (component.getDomObject().getEvents().contains("unsticky")) {
@@ -141,6 +156,7 @@ public class StickyHeaderHelper {
         View view = mHeaderViews.get(cell.getRef());
         if(view != null){
           view.bringToFront();
+          changeFrontStickyVisible();
         }
       }
     }
@@ -148,4 +164,27 @@ public class StickyHeaderHelper {
       notifyStickyRemove(cell);
     }
   }
+
+
+  private void changeFrontStickyVisible(){
+    if(mHeaderViews.size() <= 0){
+      return;
+    }
+    boolean  fontVisible = false;
+    for(int i=mParent.getChildCount()-1; i>=0; i--){
+         View view = mParent.getChildAt(i);
+         if(fontVisible && view.getTag() instanceof  StickyHeaderHelper){
+             if(view.getVisibility() != View.GONE){
+                  view.setVisibility(View.GONE);
+             }
+         }else{
+           if(view.getTag() instanceof  StickyHeaderHelper){
+               fontVisible = true;
+               if(view != null && view.getVisibility() != View.VISIBLE){
+                   view.setVisibility(View.VISIBLE);
+               }
+           }
+         }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cb1df915/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
index c329e99..ebf81b4 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/WXCell.java
@@ -37,6 +37,9 @@ import com.taobao.weex.ui.flat.WidgetContainer;
 import com.taobao.weex.ui.view.WXFrameLayout;
 import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXUtils;
+import com.taobao.weex.utils.WXViewUtils;
+
+import static com.taobao.weex.common.Constants.Name.STICKY_OFFSET;
 
 /**
  * Root component for components in {@link WXListComponent}
@@ -55,17 +58,14 @@ public class WXCell extends WidgetContainer<WXFrameLayout> {
     private int mScrollPositon = -1;
     private boolean mFlatUIEnabled = false;
 
+
     private Object  renderData;
 
     private boolean isSourceUsed = false;
 
     private boolean hasLayout = false;
 
-    private Object  renderData;
 
-    private boolean isSourceUsed = false;
-
-    private boolean hasLayout = false;
 
 
     @Deprecated
@@ -149,28 +149,41 @@ public class WXCell extends WidgetContainer<WXFrameLayout> {
     }
 
     public void removeSticky() {
-        mHeadView = getHostView().getChildAt(0);
-        int[] location = new int[2];
-        int[] parentLocation = new int[2];
-        getHostView().getLocationOnScreen(location);
-        getParentScroller().getView().getLocationOnScreen(parentLocation);
-        int headerViewOffsetX = location[0] - parentLocation[0];
-        int headerViewOffsetY = getParent().getHostView().getTop();
-        getHostView().removeView(mHeadView);
-        mRealView = (ViewGroup) mHeadView;
-        mTempStickyView = new FrameLayout(getContext());
-        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) getDomObject().getLayoutWidth(),
-                (int) getDomObject().getLayoutHeight());
-        getHostView().addView(mTempStickyView, lp);
-        mHeadView.setTranslationX(headerViewOffsetX);
-        mHeadView.setTranslationY(headerViewOffsetY);
+        if(getHostView().getChildCount() > 0) {
+            mHeadView = getHostView().getChildAt(0);
+            int[] location = new int[2];
+            int[] parentLocation = new int[2];
+            getHostView().getLocationOnScreen(location);
+            getParentScroller().getView().getLocationOnScreen(parentLocation);
+            int headerViewOffsetX = location[0] - parentLocation[0];
+            int headerViewOffsetY = getParent().getHostView().getTop();
+            getHostView().removeView(mHeadView);
+            mRealView = (ViewGroup) mHeadView;
+            mTempStickyView = new FrameLayout(getContext());
+            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) getDomObject().getLayoutWidth(),
+                    (int) getDomObject().getLayoutHeight());
+            getHostView().addView(mTempStickyView, lp);
+            mHeadView.setTranslationX(headerViewOffsetX);
+            mHeadView.setTranslationY(headerViewOffsetY);
+        }
     }
 
     public void recoverySticky() {
-        getHostView().removeView(mTempStickyView);
-        getHostView().addView(mHeadView);
-        mHeadView.setTranslationX(0);
-        mHeadView.setTranslationY(0);
+        if(mHeadView != null){
+            if(mHeadView.getLayoutParams() != null){
+                ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mHeadView.getLayoutParams();
+                if(params.topMargin > 0){
+                    params.topMargin = 0;
+                }
+            }
+            if(mHeadView.getVisibility() != View.VISIBLE){
+                mHeadView.setVisibility(View.VISIBLE);
+            }
+            getHostView().removeView(mTempStickyView);
+            getHostView().addView(mHeadView);
+            mHeadView.setTranslationX(0);
+            mHeadView.setTranslationY(0);
+        }
     }
 
     @Override
@@ -192,28 +205,16 @@ public class WXCell extends WidgetContainer<WXFrameLayout> {
         return getInstance().getFlatUIContext().isFlatUIEnabled(this) && WXCell.class.equals(getClass()) && !isSticky();
     }
 
-    public Object getRenderData() {
-        return renderData;
-    }
-
-    public void setRenderData(Object renderData) {
-        this.renderData = renderData;
-    }
-
-    public boolean isSourceUsed() {
-        return isSourceUsed;
-    }
-
-    public void setSourceUsed(boolean sourceUsed) {
-        isSourceUsed = sourceUsed;
-    }
-
-    public boolean isHasLayout() {
-        return hasLayout;
-    }
-
-    public void setHasLayout(boolean hasLayout) {
-        this.hasLayout = hasLayout;
+    public int getStickyOffset(){
+        if(getDomObject() == null){
+            return  0;
+        }
+        WXDomObject domObject = (WXDomObject) getDomObject();
+        if(domObject.getAttrs().get(STICKY_OFFSET) == null){
+            return 0;
+        }
+        float  offset = WXUtils.getFloat(domObject.getAttrs().get(STICKY_OFFSET));
+        return (int)(WXViewUtils.getRealPxByWidth(offset,domObject.getViewPortWidth()));
     }
 
     public Object getRenderData() {
@@ -239,5 +240,4 @@ public class WXCell extends WidgetContainer<WXFrameLayout> {
     public void setHasLayout(boolean hasLayout) {
         this.hasLayout = hasLayout;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/cb1df915/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
index 7e0746b..1918517 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/list/template/WXRecyclerTemplateList.java
@@ -1306,7 +1306,7 @@ public class WXRecyclerTemplateList extends WXVContainer<BounceRecyclerView> imp
                     continue;
                 }
                 TemplateViewHolder itemHolder = (TemplateViewHolder) recyclerView.findViewHolderForAdapterPosition(position);
-                if(itemHolder == null){
+                if(itemHolder == null || itemHolder.getComponent() == null){
                     break;
                 }
                 List<WXComponent> childListeners = findChildListByRef(itemHolder.getComponent(), helper.getAwareChild().getRef());