/** * Check last Sticky after scrollTo * * @param position scroll to position */ public void checkLastSticky(final int position) { bounceRecyclerView.clearSticky(); for (int i = 0; i <= position; i++) { WXComponent component = getChild(i); if (component.isSticky() && component instanceof WXCell) { if (component.getHostView() == null) { return; } bounceRecyclerView.notifyStickyShow((WXCell) component); } } }
private void setAppearanceWatch(WXComponent component, int event, boolean enable) { AppearanceHelper item = mAppearComponents.get(component.getRef()); if (item != null) { item.setWatchEvent(event, enable); } else if (!enable) { // Do nothing if disable target not exist. } else { WXComponent dChild = findDirectListChild(component); int index = mChildren.indexOf(dChild); if (index != -1) { item = new AppearanceHelper(component, index); item.setWatchEvent(event, true); mAppearComponents.put(component.getRef(), item); } } }
/** * Update the specified component's dom and mark it as old. * * @param component the component to be updated */ private void updateDomObj(WXComponent component) { if (component == null) { return; } WXDomObject domObject = mRegistry.get(component.getRef()); if (domObject == null) { return; } domObject.old(); component.updateDom(domObject.clone()); if (component instanceof WXVContainer) { WXVContainer container = (WXVContainer) component; int count = container.childCount(); for (int i = 0; i < count; ++i) { updateDomObj(container.getChild(i)); } } }
@Override public void notifyAppearStateChange( int firstVisible, int lastVisible, int directionX, int directionY) { // notify appear state Iterator<AppearanceHelper> it = mAppearComponents.values().iterator(); String direction = directionY > 0 ? "up" : "down"; if (getOrientation() == Constants.Orientation.HORIZONTAL) { direction = directionX > 0 ? "left" : "right"; } while (it.hasNext()) { AppearanceHelper item = it.next(); WXComponent component = item.getAwareChild(); if (!item.isWatch()) { continue; } boolean outOfVisibleRange = item.getCellPositionINScollable() < firstVisible || item.getCellPositionINScollable() > lastVisible; View view = component.getHostView(); if (view == null) { continue; } boolean visible = (!outOfVisibleRange) && item.isViewVisible(); int result = item.setAppearStatus(visible); if (WXEnvironment.isApkDebugable()) { WXLogUtils.d("appear", "item " + item.getCellPositionINScollable() + " result " + result); } if (result == AppearanceHelper.RESULT_NO_CHANGE) { continue; } component.notifyAppearStateChange( result == AppearanceHelper.RESULT_APPEAR ? Constants.Event.APPEAR : Constants.Event.DISAPPEAR, direction); } }
@Override public void onBeforeScroll(int dx, int dy) { if (mStickyMap == null) { return; } HashMap<String, WXComponent> stickyMap = mStickyMap.get(getRef()); if (stickyMap == null) { return; } Iterator<Map.Entry<String, WXComponent>> iterator = stickyMap.entrySet().iterator(); Map.Entry<String, WXComponent> entry; WXComponent stickyComponent; while (iterator.hasNext()) { entry = iterator.next(); stickyComponent = entry.getValue(); if (stickyComponent != null && stickyComponent.getDomObject() != null && stickyComponent instanceof WXCell) { if (stickyComponent.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]; boolean showSticky = ((WXCell) stickyComponent).lastLocationY > 0 && top <= 0 && dy > 0; boolean removeSticky = ((WXCell) stickyComponent).lastLocationY <= 0 && top > 0 && dy < 0; if (showSticky) { bounceRecyclerView.notifyStickyShow((WXCell) stickyComponent); } else if (removeSticky) { bounceRecyclerView.notifyStickyRemove((WXCell) stickyComponent); } ((WXCell) stickyComponent).lastLocationY = top; } } }
private @Nullable WXComponent findDirectListChild(WXComponent comp) { WXComponent parent; if (comp == null || (parent = comp.getParent()) == null) { return null; } if (parent instanceof WXListComponent) { return comp; } return findDirectListChild(parent); }
@Override public void scrollTo(WXComponent component, final int offset) { if (bounceRecyclerView == null) { return; } WXComponent parent = component; WXCell cell = null; while (parent != null) { if (parent instanceof WXCell) { cell = (WXCell) parent; break; } parent = parent.getParent(); } if (cell != null) { int pos = mChildren.indexOf(cell); final WXRecyclerView view = bounceRecyclerView.getInnerView(); view.scrollToPosition(pos); final WXComponent cellComp = cell; // scroll cell to top view.postDelayed( new Runnable() { @Override public void run() { if (getOrientation() == Constants.Orientation.VERTICAL) { int scrollY = cellComp.getHostView().getTop() + offset; view.smoothScrollBy(0, scrollY); } else { int scrollX = cellComp.getHostView().getLeft() + offset; view.smoothScrollBy(scrollX, 0); } } }, 50); onPostScrollToPosition(pos); } }
/** @param loading should be {@link WXRefreshView} */ public void setFooterView(WXComponent loading) { setLoadmoreEnable(true); if (swipeLayout != null) { if (swipeLayout.getFooterView() != null) { swipeLayout.setLoadingHeight((int) loading.getDomObject().getLayoutHeight()); String colorStr = (String) loading.getDomObject().getStyles().get(Constants.Name.BACKGROUND_COLOR); String bgColor = WXUtils.getString(colorStr, null); if (bgColor != null) { if (!TextUtils.isEmpty(bgColor)) { int colorInt = WXResourceUtils.getColor(bgColor); if (!(colorInt == Color.TRANSPARENT)) { swipeLayout.setLoadingBgColor(colorInt); } } } swipeLayout.getFooterView().setRefreshView(loading.getHostView()); } } }
/** * Bind the component of the position to the holder. Then flush the view. * * @param holder viewHolder, which holds reference to the view * @param position position of component in WXListComponent */ @Override public void onBindViewHolder(ListBaseViewHolder holder, int position) { if (holder == null) return; holder.setComponentUsing(true); WXComponent component = getChild(position); if (component == null || (component instanceof WXRefresh) || (component instanceof WXLoading) || (component.getDomObject() != null && component.getDomObject().isFixed())) { if (WXEnvironment.isApkDebugable()) { WXLogUtils.d(TAG, "Bind WXRefresh & WXLoading " + holder); } return; } if (component != null && holder.getComponent() != null && holder.getComponent() instanceof WXCell) { holder.getComponent().bindData(component); // holder.getComponent().refreshData(component); } }
/** * generate viewtype by component * * @param component * @return */ private int generateViewType(WXComponent component) { long id; try { id = Integer.parseInt(component.getDomObject().getRef()); String type = component.getDomObject().getAttrs().getScope(); if (!TextUtils.isEmpty(type)) { if (mRefToViewType == null) { mRefToViewType = new ArrayMap<>(); } if (!mRefToViewType.containsKey(type)) { mRefToViewType.put(type, id); } id = mRefToViewType.get(type); } } catch (RuntimeException e) { WXLogUtils.eTag(TAG, e); id = RecyclerView.NO_ID; WXLogUtils.e( TAG, "getItemViewType: NO ID, this will crash the whole render system of WXListRecyclerView"); } return (int) id; }
@Override public void remove(WXComponent child, boolean destroy) { int index = mChildren.indexOf(child); if (destroy) { child.detachViewAndClearPreInfo(); } unBindViewType(child); BounceRecyclerView view = getHostView(); if (view == null) { return; } view.getAdapter().notifyItemRemoved(index); if (WXEnvironment.isApkDebugable()) { WXLogUtils.d(TAG, "removeChild child at " + index); } super.remove(child, destroy); }
/** * Create an instance of {@link ListBaseViewHolder} for the given viewType (not for the given * index). This method will look up for the first component that fits the viewType requirement and * doesn't be used. Then create the certain type of view, detach the view f[rom the component. * * @param parent the ViewGroup into which the new view will be inserted * @param viewType the type of the new view * @return the created view holder. */ @Override public ListBaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mChildren != null) { if (mViewTypes == null) return createVHForFakeComponent(viewType); ArrayList<WXComponent> mTypes = mViewTypes.get(viewType); checkRecycledViewPool(viewType); if (mTypes == null) return createVHForFakeComponent(viewType); for (int i = 0; i < mTypes.size(); i++) { WXComponent component = mTypes.get(i); if (component == null || component.isUsing()) { continue; } if (component.getDomObject() != null && component.getDomObject().isFixed()) { return createVHForFakeComponent(viewType); } else { if (component instanceof WXCell) { if (component.getRealView() != null) { return new ListBaseViewHolder(component, viewType); } else { component.lazy(false); component.createView(this, -1); component.applyLayoutAndEvent(component); return new ListBaseViewHolder(component, viewType); } } else { WXLogUtils.e( TAG, "List cannot include element except cell、header、fixed、refresh and loading"); return createVHForFakeComponent(viewType); } } } } if (WXEnvironment.isApkDebugable()) { WXLogUtils.e(TAG, "Cannot find request viewType: " + viewType); } return createVHForFakeComponent(viewType); }