diff --git a/apps/samples/recyclerview.cc b/apps/samples/recyclerview.cc index 844135cb..ae44be67 100755 --- a/apps/samples/recyclerview.cc +++ b/apps/samples/recyclerview.cc @@ -36,6 +36,7 @@ public: TextView*textView = ((MyAdapter::ViewHolder&)holder).textView; textView->setText(item); textView->setId(position); + LOGD("%p:%d",textView,position); textView->setOnClickListener([position](View&v){ RecyclerView*rv = (RecyclerView*)v.getParent(); RecyclerView::LayoutManager*mgr = rv->getLayoutManager(); @@ -88,6 +89,7 @@ int main(int argc,const char*argv[]){ r=[&](){ adapter->remove(4); adapter->notifyItemRemoved(4); + w->postDelayed(r,3000); }; w->postDelayed(r,8000); app.exec(); diff --git a/src/gui/core/keyboard.cc b/src/gui/core/keyboard.cc index 4080ad67..17218ef1 100755 --- a/src/gui/core/keyboard.cc +++ b/src/gui/core/keyboard.cc @@ -32,12 +32,12 @@ Keyboard::Key::Key(void*parent,int x,int y,Context*context,const AttributeSet&at this->x = x; this->y = y; Keyboard::Row*row=(Keyboard::Row*)parent; - Keyboard*keyboard =row->parent; + Keyboard*keyboard = row->parent; width = getDimensionOrFraction(attrs,"keyWidth" , keyboard->mDisplayWidth, row->defaultWidth ); height= getDimensionOrFraction(attrs,"keyHeight", keyboard->mDisplayHeight, row->defaultHeight); gap = getDimensionOrFraction(attrs,"horizontalGap", keyboard->mDisplayWidth, row->defaultHorizontalGap); edgeFlags =row->rowEdgeFlags | attrs.getInt("keyEdgeFlags",edgeFlagKVS,0); - this->x+=gap; + this->x += gap; const std::string resicon=attrs.getString("keyIcon"); icon = resicon.empty()?nullptr:context->getDrawable(resicon); label = attrs.getString("keyLabel"); @@ -50,18 +50,19 @@ Keyboard::Key::Key(void*parent,int x,int y,Context*context,const AttributeSet&at std::wstring ws=TextUtils::utf8tounicode(label); codes.push_back(ws[0]); } + LOGV("Key[%x]%s(%d,%d,%d,%d) gap=%d",codes[0],label.c_str(),x,y,width,height,gap); } Keyboard::Key::Key(void*p){ - parent =p; - Row*row=(Row*)parent; - sticky =modifier=0; + parent = p; + Row*row= (Row*)parent; + sticky = modifier = 0; x= y = gap =0; - width = row->defaultWidth; - height = row->defaultHeight; - edgeFlags= row->rowEdgeFlags; + width = row->defaultWidth; + height = row->defaultHeight; + edgeFlags = row->rowEdgeFlags; on = false; - pressed=false; + pressed = false; } void Keyboard::Key::onPressed() { @@ -90,10 +91,10 @@ int Keyboard::Key::parseCSV(const std::string& value,std::vector& codes){ } bool Keyboard::Key::isInside(int x, int y) { - bool leftEdge = (edgeFlags & EDGE_LEFT) > 0; - bool rightEdge = (edgeFlags & EDGE_RIGHT) > 0; - bool topEdge = (edgeFlags & EDGE_TOP) > 0; - bool bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0; + const bool leftEdge = (edgeFlags & EDGE_LEFT) > 0; + const bool rightEdge = (edgeFlags & EDGE_RIGHT) > 0; + const bool topEdge = (edgeFlags & EDGE_TOP) > 0; + const bool bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0; if ((x >= this->x || (leftEdge && x <= this->x + this->width)) && (x < this->x + this->width || (rightEdge && x >= this->x)) && (y >= this->y || (topEdge && y <= this->y + this->height)) @@ -105,8 +106,8 @@ bool Keyboard::Key::isInside(int x, int y) { } int Keyboard::Key::squaredDistanceFrom(int x, int y){ - int xDist = this->x + width / 2 - x; - int yDist = this->y + height / 2 - y; + const int xDist = this->x + width / 2 - x; + const int yDist = this->y + height / 2 - y; return xDist * xDist + yDist * yDist; } @@ -255,7 +256,7 @@ static void endTag(void *userData, const XML_Char *name){ keyboard->getModifierKeys().push_back(key); } }else if(0==strcmp(name,"Row")){ - pd->y += row->defaultHeight+row->verticalGap; + pd->y += (row->defaultHeight + row->verticalGap); pd->minWidth = std::max(pd->x,pd->minWidth); pd->x = 0; if(row->mode == pd->keyboardMode) @@ -293,11 +294,11 @@ void Keyboard::loadKeyboard(Context*context,const std::string&resid){ } while(len!=0); } XML_ParserFree(parser); - mTotalHeight= pd.y-mDefaultVerticalGap; + mTotalHeight= pd.y - mDefaultVerticalGap; mTotalWidth = pd.minWidth; mProximityThreshold = mDefaultWidth*.6f;//SEARCH_DISTANCE; mProximityThreshold*= mProximityThreshold; - LOGD("%s endof loadkeyboard %d rows %d keys gaps=%d,%d parsed size=%dx%d display=%dx%d", + LOGD("%s endof loadkeyboard %d rows %d keys gaps=%d,%d parsed.Size=%dx%d display=%dx%d", resid.c_str(),rows.size(),mKeys.size(), getHorizontalGap(),getVerticalGap(), mTotalWidth,mTotalHeight,mDisplayWidth,mDisplayHeight); } @@ -435,7 +436,7 @@ void Keyboard::computeNearestNeighbors() { std::vector Keyboard::getNearestKeys(int x, int y){ if (mGridNeighbors.size() ==0) computeNearestNeighbors(); if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) { - int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth); + const int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth); if (index < GRID_SIZE) { return mGridNeighbors[index]; } diff --git a/src/gui/widget/keyboardview.cc b/src/gui/widget/keyboardview.cc index 1b947920..e7c1bc4d 100644 --- a/src/gui/widget/keyboardview.cc +++ b/src/gui/widget/keyboardview.cc @@ -4,6 +4,7 @@ #include #include #include +#include namespace cdroid{ @@ -680,13 +681,13 @@ void KeyboardView::SwipeTracker::addPoint(float x,float y,long time){ } void KeyboardView::SwipeTracker::computeCurrentVelocity(int units){ - //computeCurrentVelocity(units,FLT_MAX); + computeCurrentVelocity(units,FLT_MAX); } void KeyboardView::SwipeTracker::computeCurrentVelocity(int units,float maxVelocity){ - float oldestX = mPastX[0];//pastX[0]; - float oldestY = mPastY[0];//pastY[0]; - long oldestTime = mPastTime[0];//pastTime[0]; + float oldestX = mPastX[0]; + float oldestY = mPastY[0]; + long oldestTime = mPastTime[0]; float accumX = 0; float accumY = 0; int N=0; diff --git a/src/gui/widgetEx/recyclerview/adapterhelper.cc b/src/gui/widgetEx/recyclerview/adapterhelper.cc index 52983937..87da3d0c 100755 --- a/src/gui/widgetEx/recyclerview/adapterhelper.cc +++ b/src/gui/widgetEx/recyclerview/adapterhelper.cc @@ -9,7 +9,11 @@ AdapterHelper::AdapterHelper(Callback callback) AdapterHelper::AdapterHelper(Callback callback, bool disableRecycler) { mCallback = callback; mDisableRecycler = disableRecycler; - mOpReorderer = nullptr;//new OpReorderer(this); + OpReorderer::Callback cbk; + cbk.obtainUpdateOp = std::bind(&AdapterHelper::obtainUpdateOp,this,std::placeholders::_1, + std::placeholders::_2,std::placeholders::_3,std::placeholders::_4); + cbk.recycleUpdateOp= std::bind(&AdapterHelper::recycleUpdateOp,this,std::placeholders::_1); + mOpReorderer = new OpReorderer(cbk); mUpdateOpPool = new Pools::SimplePool(UpdateOp::POOL_SIZE); } @@ -19,7 +23,6 @@ AdapterHelper::~AdapterHelper(){ } AdapterHelper& AdapterHelper::addUpdateOp(const std::vector&ops) { - //Collections.addAll(mPendingUpdates, ops); mPendingUpdates.insert(mPendingUpdates.end(),ops.begin(),ops.end()); return *this; } @@ -164,19 +167,19 @@ void AdapterHelper::dispatchAndUpdateViewHolders(UpdateOp* op) { if (op->cmd == UpdateOp::ADD || op->cmd == UpdateOp::MOVE) { throw "should not dispatch add or move for pre layout"; } - /*if (_DEBUG) { - LOGD("dispatch (pre)" + op); - Log.d(TAG, "postponed state before:"); - for (UpdateOp updateOp : mPostponedList) { - Log.d(TAG, updateOp.toString()); + if (_DEBUG) { + LOGD("dispatch (pre)%p" ,op); + LOGD("postponed state before:"); + for (UpdateOp* updateOp : mPostponedList) { + LOGD("%s",updateOp->toString().c_str()); } - Log.d(TAG, "----"); - }*/ + LOGD("----"); + } // handle each pos 1 by 1 to ensure continuity. If it breaks, dispatch partial // TODO Since move ops are pushed to end, we should not need this anymore int tmpStart = updatePositionWithPostponed(op->positionStart, op->cmd); - LOGD_IF(_DEBUG,"pos:%d,updatedPos:%d",op->positionStart,tmpStart); + LOGD_IF(_DEBUG,"pos:%d,updatedPos:%d mPostponedList.size=%d",op->positionStart,tmpStart,mPostponedList.size()); int tmpCnt = 1; int offsetPositionForPartial = op->positionStart; int positionMultiplier; @@ -221,7 +224,7 @@ void AdapterHelper::dispatchAndUpdateViewHolders(UpdateOp* op) { LOGD("post dispatch"); LOGD("postponed state after:"); for (UpdateOp* updateOp : mPostponedList) { - //Log.d(TAG, updateOp.toString()); + LOGD("%s",updateOp->toString().c_str()); } LOGD("----"); } @@ -297,14 +300,14 @@ int AdapterHelper::updatePositionWithPostponed(int pos, int cmd) { } } } - /*if (_DEBUG) { - Log.d(TAG, "dispath (step" + i + ")"); - Log.d(TAG, "postponed state:" + i + ", pos:" + pos); + if (_DEBUG) { + LOGD("dispath (step %d)",i); + LOGD("postponed state:%d, pos:%d",i,pos); for (UpdateOp* updateOp : mPostponedList) { - Log.d(TAG, updateOp.toString()); + LOGD(updateOp->toString().c_str()); } - Log.d(TAG, "----"); - }*/ + LOGD("----"); + } } for (int i = mPostponedList.size() - 1; i >= 0; i--) { UpdateOp* op = mPostponedList.at(i); @@ -346,10 +349,8 @@ void AdapterHelper::applyAdd(UpdateOp* op) { } void AdapterHelper::postponeAndUpdateViewHolders(UpdateOp* op) { - if (_DEBUG) { - LOGD("postponing %d",op->cmd); - } mPostponedList.push_back(op);//add(op); + LOGD_IF(_DEBUG,"postponing op->%p:%d mPostponedList.size=%d",op,op->cmd,mPostponedList.size()); switch (op->cmd) { case UpdateOp::ADD: mCallback.offsetPositionsForAdd(op->positionStart, op->itemCount); @@ -560,9 +561,9 @@ void AdapterHelper::recycleUpdateOpsAndClearList(std::vector& ops) { /////////////////////////////////////////////////////////////////////////////////////////////////// AdapterHelper::UpdateOp::UpdateOp(){ - cmd =0; - itemCount=0; - payload =nullptr; + cmd = 0; + itemCount = 0; + payload = nullptr; } AdapterHelper::UpdateOp::UpdateOp(int cmd, int positionStart, int itemCount, Object* payload) { @@ -578,4 +579,13 @@ int AdapterHelper::UpdateOp::hashCode() { result = 31 * result + itemCount; return result; } + +const std::string AdapterHelper::UpdateOp::toString()const{ + std::ostringstream oss; + const char*cmds[]={"add","rm","up","mv"}; + const int idx = __builtin_clz(cmd); + oss< findViewHolder;//(int position) diff --git a/src/gui/widgetEx/recyclerview/defaultitemanimator.cc b/src/gui/widgetEx/recyclerview/defaultitemanimator.cc index 8aa17a98..77caacb0 100755 --- a/src/gui/widgetEx/recyclerview/defaultitemanimator.cc +++ b/src/gui/widgetEx/recyclerview/defaultitemanimator.cc @@ -149,24 +149,43 @@ bool DefaultItemAnimator::animateAdd(RecyclerView::ViewHolder& holder) { return true; } +void DefaultItemAnimator::onAddAnimationStart(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){ + dispatchAddStarting(*holder); +} +void DefaultItemAnimator::onAddAnimationCancel(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){ + holder->itemView->setAlpha(1); +} +void DefaultItemAnimator::onAddAnimationEnd(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){ + View* view = holder->itemView; + ViewPropertyAnimator& animation = view->animate(); + animation.setListener({}); + dispatchAddFinished(*holder); + auto it = std::find(mAddAnimations.begin(), mAddAnimations.end(),holder); + mAddAnimations.erase(it);//mAddAnimations.remove(holder); + dispatchFinishedWhenDone(); +} + void DefaultItemAnimator::animateAddImpl(RecyclerView::ViewHolder& holder) { View* view = holder.itemView; ViewPropertyAnimator& animation = view->animate(); mAddAnimations.push_back(&holder);//add(holder); Animator::AnimatorListener al; - al.onAnimationStart = [this,&holder](Animator&animator,bool isReverse){ + al.onAnimationStart = std::bind(&DefaultItemAnimator::onAddAnimationStart,this,&holder,std::placeholders::_1,std::placeholders::_2); + /*[this,&holder](Animator&animator,bool isReverse){ dispatchAddStarting(holder); - }; - al.onAnimationCancel=[&holder](Animator&){ + };*/ + //al.onAnimationCancel= std::bind(&DefaultItemAnimator::onAddAnimationCancel,this,&holder,std::placeholders::_1,std::placeholders::_2); + /*[&holder](Animator&){ holder.itemView->setAlpha(1); - }; - al.onAnimationEnd = [this,&holder,&animation](Animator& animator,bool isReverse){ + };*/ + al.onAnimationEnd = std::bind(&DefaultItemAnimator::onAddAnimationEnd,this,&holder,std::placeholders::_1,std::placeholders::_2); + /*[this,&holder,&animation](Animator& animator,bool isReverse){ animation.setListener({}); dispatchAddFinished(holder); auto it = std::find(mAddAnimations.begin(), mAddAnimations.end(),&holder); mAddAnimations.erase(it);//mAddAnimations.remove(holder); dispatchFinishedWhenDone(); - }; + };*/ animation.alpha(1).setDuration(getAddDuration()).setListener(al).start(); } diff --git a/src/gui/widgetEx/recyclerview/defaultitemanimator.h b/src/gui/widgetEx/recyclerview/defaultitemanimator.h index 244f6cb6..fa655de7 100755 --- a/src/gui/widgetEx/recyclerview/defaultitemanimator.h +++ b/src/gui/widgetEx/recyclerview/defaultitemanimator.h @@ -43,6 +43,9 @@ protected: int fromX, int fromY, int toX, int toY); }; protected: + void onAddAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); + void onAddAnimationCancel(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); + void onAddAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); void onRemoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); void onRemoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); void onMoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); diff --git a/src/gui/widgetEx/recyclerview/gridlayoutmanager.cc b/src/gui/widgetEx/recyclerview/gridlayoutmanager.cc index d14dd19c..83e9f65d 100755 --- a/src/gui/widgetEx/recyclerview/gridlayoutmanager.cc +++ b/src/gui/widgetEx/recyclerview/gridlayoutmanager.cc @@ -9,6 +9,7 @@ GridLayoutManager::GridLayoutManager(Context* context,const AttributeSet& attrs) mSpanSizeLookup = new DefaultSpanSizeLookup(); setSpanCount(properties->spanCount); delete properties; + mPendingSpanCountChange = false; } GridLayoutManager::GridLayoutManager(Context* context, int spanCount) diff --git a/src/gui/widgetEx/recyclerview/linearlayoutmanager.cc b/src/gui/widgetEx/recyclerview/linearlayoutmanager.cc index 35cdd124..6d43c921 100755 --- a/src/gui/widgetEx/recyclerview/linearlayoutmanager.cc +++ b/src/gui/widgetEx/recyclerview/linearlayoutmanager.cc @@ -14,6 +14,7 @@ LinearLayoutManager::LinearLayoutManager(Context* context,int orientation,bool r mLayoutState = nullptr; mOrientationHelper = nullptr; mLastStackFromEnd = false; + mStackFromEnd = false; mRecycleChildrenOnDetach = true; mAnchorInfo = new AnchorInfo(); mLayoutChunkResult = new LayoutChunkResult(); diff --git a/src/gui/widgetEx/recyclerview/linearlayoutmanager.h b/src/gui/widgetEx/recyclerview/linearlayoutmanager.h index afa2d572..3508a5c7 100755 --- a/src/gui/widgetEx/recyclerview/linearlayoutmanager.h +++ b/src/gui/widgetEx/recyclerview/linearlayoutmanager.h @@ -157,7 +157,7 @@ public: int findLastCompletelyVisibleItemPosition(); View* onFocusSearchFailed(View* focused, int focusDirection, RecyclerView::Recycler& recycler, RecyclerView::State& state); - bool supportsPredictiveItemAnimations(); + bool supportsPredictiveItemAnimations()override; void prepareForDrop(View* view,View* target, int x, int y); }; diff --git a/src/gui/widgetEx/recyclerview/recyclerview.cc b/src/gui/widgetEx/recyclerview/recyclerview.cc index 8bc1c463..83d4bf83 100755 --- a/src/gui/widgetEx/recyclerview/recyclerview.cc +++ b/src/gui/widgetEx/recyclerview/recyclerview.cc @@ -136,6 +136,7 @@ void RecyclerView::initRecyclerView(){ mDataSetHasChangedAfterLayout = false; mEatenAccessibilityChangeFlags =0; mInterceptRequestLayoutDepth = 0; + mAdapterUpdateDuringMeasure = false; mState = new State(); mAdapterHelper = nullptr; mViewInfoStore = new ViewInfoStore(); @@ -332,7 +333,7 @@ void RecyclerView::initChildrenHelper() { if (!vh->isTmpDetached() && !vh->shouldIgnore()) { LOGE("Called attach on a child which is not detached: %p",vh); } - LOGD_IF(_DEBUG,"reAttach %p",vh); + LOGD_IF(_DEBUG,"reAttach %p %p:%d",vh,vh->itemView,vh->itemView->getId()); vh->clearTmpDetachFlag(); } attachViewToParent(child, index, layoutParams); @@ -346,7 +347,7 @@ void RecyclerView::initChildrenHelper() { if (vh->isTmpDetached() && !vh->shouldIgnore()) { LOGE("called detach on an already detached child %p",vh); } - LOGD_IF(_DEBUG,"tmpDetach =%p",vh); + LOGD_IF(_DEBUG,"tmpDetach =%p %p:%d",vh,vh->itemView,vh->itemView->getId()); vh->addFlags(ViewHolder::FLAG_TMP_DETACHED); } } @@ -3795,7 +3796,24 @@ bool RecyclerView::Recycler::tryBindViewHolderByDeadline(ViewHolder& holder, int // abort - we have a deadline we can't meet return false; } + // Holders being bound should be either fully attached or fully detached. + // We don't want to bind with views that are temporarily detached, because that + // creates a situation in which they are unable to reason about their attach state + // properly. + // For example, isAttachedToWindow will return true, but the itemView will lack a + // parent. This breaks, among other possible issues, anything involving traversing + // the view tree, such as ViewTreeLifecycleOwner. + // Thus, we temporarily reattach any temp-detached holders for the bind operation. + // See https://issuetracker.google.com/265347515 for additional details on problems + // resulting from this + bool reattachedForBind = false; + if (holder.isTmpDetached()) { + mRV->attachViewToParent(holder.itemView, mRV->getChildCount(), holder.itemView->getLayoutParams()); + reattachedForBind = true; + } mRV->mAdapter->bindViewHolder(holder, offsetPosition); + if(reattachedForBind) + mRV->detachViewFromParent(holder.itemView); long endBindNs = mRV->getNanoTime(); mRecyclerPool->factorInBindTime(holder.getItemViewType(), endBindNs - startBindNs); attachAccessibilityDelegateOnBind(holder); @@ -4045,6 +4063,27 @@ void RecyclerView::Recycler::recycleView(View* view) { holder->clearReturnedFromScrapFlag(); } recycleViewHolderInternal(*holder); + // If the ViewHolder is running ItemAnimator, we want the recycleView() in scroll pass + // to stop the ItemAnimator and put ViewHolder back in cache or Pool. + // There are three situations: + // 1. If the custom Adapter clears ViewPropertyAnimator in view detach like the + // leanback (TV) app does, the ItemAnimator is likely to be stopped and + // recycleViewHolderInternal will succeed. + // 2. If the custom Adapter clears ViewPropertyAnimator, but the ItemAnimator uses + // "pending runnable" and ViewPropertyAnimator has not started yet, the ItemAnimator + // on the view will not be cleared. See b/73552923. + // 3. If the custom Adapter does not clear ViewPropertyAnimator in view detach, the + // ItemAnimator will not be cleared. + // Since both 2&3 lead to failure of recycleViewHolderInternal(), we just explicitly end + // the ItemAnimator, the callback of ItemAnimator.endAnimations() will recycle the View. + // + // Note the order: we must call endAnimation() after recycleViewHolderInternal() + // to avoid recycle twice. If ViewHolder isRecyclable is false, + // recycleViewHolderInternal() will not recycle it, endAnimation() will reset + // isRecyclable flag and recycle the view. + if (mRV->mItemAnimator && !holder->isRecyclable()) { + mRV->mItemAnimator->endAnimation(*holder); + } } void RecyclerView::Recycler::recycleViewInternal(View* view) { @@ -6253,10 +6292,10 @@ void RecyclerView::ViewHolder::setIsRecyclable(bool recyclable) { mIsRecyclableCount = recyclable ? mIsRecyclableCount - 1 : mIsRecyclableCount + 1; if (mIsRecyclableCount < 0) { mIsRecyclableCount = 0; - LOGE_IF(_DEBUG,"isRecyclable decremented below 0: " - "unmatched pair of setIsRecyable() calls for %p" , this); - LOGE("isRecyclable decremented below 0: " - "unmatched pair of setIsRecyable() calls for %p" , this); + LOGE_IF(_DEBUG,"isRecyclable decremented to %d is below 0: " + "unmatched pair of setIsRecyable() calls for %p" , mIsRecyclableCount,this); + LOGE("isRecyclable decremented to %d is below 0: " + "unmatched pair of setIsRecyable() calls for %p" ,mIsRecyclableCount, this); } else if (!recyclable && mIsRecyclableCount == 1) { mFlags |= FLAG_NOT_RECYCLABLE; } else if (recyclable && mIsRecyclableCount == 0) { @@ -7035,7 +7074,8 @@ bool RecyclerView::ItemAnimator::canReuseUpdatedViewHolder(ViewHolder& viewHolde void RecyclerView::ItemAnimator::dispatchAnimationsFinished() { const int count = mFinishedListeners.size(); for (int i = 0; i < count; ++i) { - mFinishedListeners.at(i)();//.onAnimationsFinished(); + auto ls = mFinishedListeners.at(i); + if(ls)ls();//.onAnimationsFinished(); } mFinishedListeners.clear(); } diff --git a/src/gui/widgetEx/recyclerview/staggeredgridlayoutmanager.cc b/src/gui/widgetEx/recyclerview/staggeredgridlayoutmanager.cc index b3493049..35d6105d 100755 --- a/src/gui/widgetEx/recyclerview/staggeredgridlayoutmanager.cc +++ b/src/gui/widgetEx/recyclerview/staggeredgridlayoutmanager.cc @@ -29,12 +29,12 @@ StaggeredGridLayoutManager::StaggeredGridLayoutManager(int spanCount, int orient StaggeredGridLayoutManager::~StaggeredGridLayoutManager(){ delete mPendingSavedState; - delete mPrimaryOrientation; - delete mSecondaryOrientation; - delete mRemainingSpans; - delete mAnchorInfo; - delete mLazySpanLookup; - delete mLayoutState; + delete mPrimaryOrientation; + delete mSecondaryOrientation; + delete mRemainingSpans; + delete mAnchorInfo; + delete mLazySpanLookup; + delete mLayoutState; } void StaggeredGridLayoutManager::initLayoutManager(){