From 298fcab43e92bfc8f510892bd711da7c921e8a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=AF=E6=AD=8C?= Date: Tue, 22 Mar 2022 16:50:31 +0800 Subject: [PATCH] add adapterviewanimator and animatorinflater --- apps/samples/tablayout.cc | 1 + apps/samples/viewpager1.cc | 1 + apps/samples/viewpager2.cc | 1 + apps/samples/viewpager3.cc | 1 + apps/uidemo/multimedia.cc | 25 +- src/gui/animation/animatorinflater.cc | 90 ++++ src/gui/animation/animatorinflater.h | 23 + src/gui/core/graphdevice.cc | 39 +- src/gui/core/graphdevice.h | 8 +- src/gui/drawables/drawablecontainer.cc | 2 +- src/gui/res/mipmap/clock_dial.png | Bin 48283 -> 0 bytes src/gui/res/mipmap/hour.png | Bin 4743 -> 0 bytes src/gui/res/mipmap/minute.png | Bin 5185 -> 0 bytes src/gui/res/mipmap/second.png | Bin 3296 -> 0 bytes src/gui/view/viewgroup.cc | 2 +- src/gui/widget/adapterviewanimator.cc | 584 +++++++++++++++++++++++++ src/gui/widget/adapterviewanimator.h | 141 ++++++ src/gui/widget/recyclebin.cc | 8 +- src/gui/widget/viewpager.cc | 4 - 19 files changed, 893 insertions(+), 37 deletions(-) create mode 100755 src/gui/animation/animatorinflater.cc create mode 100755 src/gui/animation/animatorinflater.h mode change 100644 => 100755 src/gui/core/graphdevice.cc mode change 100644 => 100755 src/gui/core/graphdevice.h delete mode 100755 src/gui/res/mipmap/clock_dial.png delete mode 100755 src/gui/res/mipmap/hour.png delete mode 100755 src/gui/res/mipmap/minute.png delete mode 100755 src/gui/res/mipmap/second.png mode change 100644 => 100755 src/gui/view/viewgroup.cc create mode 100755 src/gui/widget/adapterviewanimator.cc create mode 100755 src/gui/widget/adapterviewanimator.h mode change 100644 => 100755 src/gui/widget/recyclebin.cc diff --git a/apps/samples/tablayout.cc b/apps/samples/tablayout.cc index 7e4c1a24..3ba5e173 100755 --- a/apps/samples/tablayout.cc +++ b/apps/samples/tablayout.cc @@ -11,6 +11,7 @@ public: } void destroyItem(ViewGroup* container, int position,void* object)override{ container->removeView((View*)object); + delete (View*)object; } std::string getPageTitle(int position)override{ return std::string("Tab")+std::to_string(position); diff --git a/apps/samples/viewpager1.cc b/apps/samples/viewpager1.cc index bd63d5e8..dae37af9 100755 --- a/apps/samples/viewpager1.cc +++ b/apps/samples/viewpager1.cc @@ -21,6 +21,7 @@ public: } void destroyItem(ViewGroup* container, int position,void* object){ container->removeView((View*)object); + delete (View*)object; } float getPageWidth(int position){return 1.f;}//if returned calue <1 OffscreenPageLimit must be larger to workfine }; diff --git a/apps/samples/viewpager2.cc b/apps/samples/viewpager2.cc index 865f8655..5e21db4a 100755 --- a/apps/samples/viewpager2.cc +++ b/apps/samples/viewpager2.cc @@ -52,6 +52,7 @@ public: } void destroyItem(ViewGroup* container, int position,void* object){ container->removeView((View*)object); + delete (View*)object; } }; diff --git a/apps/samples/viewpager3.cc b/apps/samples/viewpager3.cc index c3c29d22..a6c98996 100755 --- a/apps/samples/viewpager3.cc +++ b/apps/samples/viewpager3.cc @@ -36,6 +36,7 @@ public: } void destroyItem(ViewGroup* container, int position,void* object)override{ container->removeView((View*)object); + delete (View*)object; } float getPageWidth(int position)override{return 1.f;} diff --git a/apps/uidemo/multimedia.cc b/apps/uidemo/multimedia.cc index 7c942e52..44b50eae 100755 --- a/apps/uidemo/multimedia.cc +++ b/apps/uidemo/multimedia.cc @@ -12,7 +12,14 @@ #include #include class FileTypeAdapter:public PagerAdapter{ +private: + FileAdapter*adapter1 = nullptr; + FileAdapter*adapter2 = nullptr; public: + ~FileTypeAdapter(){ + delete adapter1; + delete adapter2; + } int getCount()override{return 5;} bool isViewFromObject(View* view, void*object)override{ return view==object;} void* instantiateItem(ViewGroup* container, int position)override{ @@ -36,13 +43,13 @@ public: ListView*lv=new ListView(800,480); lv->setDivider(new ColorDrawable(0x80224422)); lv->setDividerHeight(1); - //lv->setFastScrollEnabled(true); + lv->setFastScrollEnabled(true); lv->setSelector(new ColorDrawable(0x8800FF00)); lv->setVerticalScrollBarEnabled(true); lv->setOverScrollMode(View::OVER_SCROLL_ALWAYS); - FileAdapter*adapter=new FileAdapter("@layout/fileitem.xml"); - adapter->loadFiles("/"); - lv->setAdapter(adapter); + adapter1=new FileAdapter("@layout/fileitem.xml"); + adapter1->loadFiles("/"); + lv->setAdapter(adapter1); lv->setBackgroundColor(0xFF000000|(0xFF<addView(lv).setId(12345); lv->setOnItemClickListener([](AdapterView&lv,View&v,int pos,long id){ @@ -60,7 +67,7 @@ public: } case 1:{LOGD("===========1111"); GridView*gv=new GridView(800,480); - FileAdapter*adapter=new FileAdapter("@layout/fileitem2.xml"); + adapter2=new FileAdapter("@layout/fileitem2.xml"); gv->setOnItemClickListener([](AdapterView&lv,View&v,int pos,long id){ FileAdapter*adp=(FileAdapter*)lv.getAdapter(); FileItem f=adp->getItemAt(pos); @@ -74,12 +81,12 @@ public: gv->setVerticalScrollBarEnabled(true); gv->setScrollbarFadingEnabled(false); gv->setNumColumns(2); - gv->setAdapter(adapter); + gv->setAdapter(adapter2); gv->setHorizontalSpacing(2); gv->setVerticalSpacing(2); container->addView(gv).setId(12345); - adapter->loadFiles("/"); - adapter->notifyDataSetChanged(); + adapter2->loadFiles("/"); + adapter2->notifyDataSetChanged(); return gv; } } @@ -87,6 +94,7 @@ public: void destroyItem(ViewGroup* container, int position,void* object)override{ container->removeView((View*)object); LOGV("destroyItem[%d]: %p",position,object); + delete (View*)object; } std::string getPageTitle(int position)override{ return std::string("Tab")+std::to_string(position); @@ -108,6 +116,7 @@ protected: public: MediaWindow(int x,int y,int w,int h); ~MediaWindow(){ + delete mAdapter; player=nullptr; } diff --git a/src/gui/animation/animatorinflater.cc b/src/gui/animation/animatorinflater.cc new file mode 100755 index 00000000..392dd839 --- /dev/null +++ b/src/gui/animation/animatorinflater.cc @@ -0,0 +1,90 @@ +#include +#include +#include + +namespace cdroid{ + +Animator* AnimatorInflater::loadAnimator(Context* context,const std::string&resid){ + return createAnimatorFromXml(context,resid); +} + +StateListAnimator* AnimatorInflater::loadStateListAnimator(Context* context,const std::string&resid){ + return createStateListAnimatorFromXml(context,resid); +} + +typedef struct{ + Context*context; + std::vectoranimators; + std::string package; + Animator*result; + std::functionfnObject; + std::functionfnAnimator; +}ParseData; + +static void startElement(void *userData, const XML_Char *name, const XML_Char **satts){ + ParseData*pd =(ParseData*)userData; + AttributeSet atts; + atts.setContext(pd->context,pd->package); + atts.set(satts); + Animator*anim = nullptr; + if(strcmp(name,"objectAnimator")==0){ + anim = pd->fnObject(pd->context,atts); + }else if(strcmp(name,"animator")==0){ + anim = pd->fnAnimator(pd->context,atts,nullptr); + }else if(strcmp(name,"set")==0){ + anim = new AnimatorSet(); + }else if(strcmp(name,"propertyValuesHolder")==0){ + }else{ + LOGE("Unknown animator name:%s",name); + } + if(pd->animators.empty()) + pd->result = anim; + pd->animators.push_back(anim); +} + +static void endElement(void *userData, const XML_Char *name){ + ParseData*pd =(ParseData*)userData; + +} + +Animator* AnimatorInflater::createAnimatorFromXml(Context*ctx,const std::string&resid){ + ParseData pd; + int len; + char buf[128]; + XML_Parser parser=XML_ParserCreateNS(nullptr,' '); + pd.context = ctx; + pd.result = nullptr; + pd.fnObject = AnimatorInflater::loadObjectAnimator; + pd.fnAnimator= AnimatorInflater::loadValueAnimator; + std::unique_ptrstream=ctx->getInputStream(resid,&pd.package); + XML_SetUserData(parser,&pd); + XML_SetElementHandler(parser, startElement, endElement); + do { + stream->read(buf,sizeof(buf)); + len=stream->gcount(); + if (XML_Parse(parser, buf,len,len==0) == XML_STATUS_ERROR) { + const char*es=XML_ErrorString(XML_GetErrorCode(parser)); + LOGE("%s at line %ld",es, XML_GetCurrentLineNumber(parser)); + XML_ParserFree(parser); + return nullptr; + } + } while(len!=0); + XML_ParserFree(parser); + return pd.result; +} + +StateListAnimator* AnimatorInflater::createStateListAnimatorFromXml(Context*ctx,const std::string&resid){ + return nullptr; +} + +ObjectAnimator* AnimatorInflater::loadObjectAnimator(Context*ctx,const AttributeSet& attrs){ + ObjectAnimator*anim = new ObjectAnimator(); + return anim; +} + +ValueAnimator* AnimatorInflater::loadValueAnimator(Context*context,const AttributeSet& attrs, ValueAnimator*anim){ + anim = new ValueAnimator(); + return anim; +} + +} diff --git a/src/gui/animation/animatorinflater.h b/src/gui/animation/animatorinflater.h new file mode 100755 index 00000000..230edb33 --- /dev/null +++ b/src/gui/animation/animatorinflater.h @@ -0,0 +1,23 @@ +#ifndef __ANIMATOR_INFLATER_H__ +#define __ANIMATOR_INFLATER_H__ +#include +#include +namespace cdroid{ +class AnimatorInflater{ +private: + static constexpr int VALUE_TYPE_FLOAT = 0; + static constexpr int VALUE_TYPE_INT = 1; + static constexpr int VALUE_TYPE_PATH = 2; + static constexpr int VALUE_TYPE_COLOR = 3; + static constexpr int VALUE_TYPE_UNDEFINED = 4; +private: + static Animator* createAnimatorFromXml(Context*ctx,const std::string&resid); + static StateListAnimator* createStateListAnimatorFromXml(Context*ctx,const std::string&resid); + static ObjectAnimator* loadObjectAnimator(Context*ctx,const AttributeSet& attrs); + static ValueAnimator* loadValueAnimator(Context*context,const AttributeSet& attrs, ValueAnimator*anim); +public: + static Animator* loadAnimator(Context* context,const std::string&resid); + static StateListAnimator* loadStateListAnimator(Context* context,const std::string&resid); +}; +}//endof namespace +#endif diff --git a/src/gui/core/graphdevice.cc b/src/gui/core/graphdevice.cc old mode 100644 new mode 100755 index 632847b4..c7711b97 --- a/src/gui/core/graphdevice.cc +++ b/src/gui/core/graphdevice.cc @@ -36,12 +36,15 @@ GraphDevice::GraphDevice(int fmt){ GFXGetScreenSize((UINT*)&mScreenWidth,(UINT*)&mScreenHeight); mFormat = fmt<0?GPF_ARGB:fmt; - GFXCreateSurface(&primarySurface,mScreenWidth,mScreenHeight,mFormat,1); - GFXLockSurface(primarySurface,(void**)&buffer,&pitch); + GFXCreateSurface(&mPrimarySurface,mScreenWidth,mScreenHeight,mFormat,1); + GFXLockSurface(mPrimarySurface,(void**)&buffer,&pitch); + + GFXCreateSurface(&mBannerSurface,200,40,mFormat,0); + mLastComposeTime = SystemClock::uptimeMillis(); - LOGD("primarySurface=%p size=%dx%d",primarySurface,mScreenWidth,mScreenHeight); + LOGD("PrimarySurface=%p size=%dx%d",mPrimarySurface,mScreenWidth,mScreenHeight); RefPtrsurf=ImageSurface::create(buffer,Surface::Format::ARGB32,mScreenWidth,mScreenHeight,pitch); - primaryContext = new Canvas(surf); + mPrimaryContext = new Canvas(surf); mInvalidateRgn = Region::create(); mComposing = 0; mQuitFlag = false; @@ -53,13 +56,17 @@ GraphDevice::~GraphDevice(){ mQuitFlag = true; mCV.notify_all(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); - delete primaryContext; - GFXDestroySurface(primarySurface); - primarySurface = nullptr; - primaryContext = nullptr; + delete mPrimaryContext; + GFXDestroySurface(mPrimarySurface); + mPrimarySurface = nullptr; + mPrimaryContext = nullptr; LOGD("%p Destroied",this); } +HANDLE GraphDevice::getPrimarySurface()const{ + return mPrimarySurface; +} + void GraphDevice::invalidate(const Rect&r){ mInvalidateRgn->do_union((const RectangleInt&)r); } @@ -107,7 +114,7 @@ bool GraphDevice::needCompose(){ } Canvas*GraphDevice::getPrimaryContext(){ - return primaryContext; + return mPrimaryContext; } void GraphDevice::doCompose(){ @@ -170,7 +177,7 @@ void GraphDevice::composeSurfaces(){ return false; }); computeVisibleRegion(wins,winVisibleRgns); - primaryContext->set_operator(Cairo::Context::Operator::SOURCE); + mPrimaryContext->set_operator(Cairo::Context::Operator::SOURCE); for(int i=0;i rgn = winVisibleRgns[i]; @@ -185,23 +192,23 @@ void GraphDevice::composeSurfaces(){ rcc.intersect(0,0,mScreenWidth,mScreenHeight); if(rcc.empty())continue; - if(hdlSurface)GFXBlit(primarySurface , rcw.left+rc.x , rcw.top+rc.y , hdlSurface,(const GFXRect*)&rc); - else primaryContext->rectangle(rcw.left+rc.x , rcw.top+rc.y, rc.width , rc.height); + if(hdlSurface)GFXBlit(mPrimarySurface , rcw.left+rc.x , rcw.top+rc.y , hdlSurface,(const GFXRect*)&rc); + else mPrimaryContext->rectangle(rcw.left+rc.x , rcw.top+rc.y, rc.width , rc.height); } if(hdlSurface==nullptr){ - primaryContext->set_source(wSurfaces[i]->get_target(),rcw.left,rcw.top); - primaryContext->fill(); + mPrimaryContext->set_source(wSurfaces[i]->get_target(),rcw.left,rcw.top); + mPrimaryContext->fill(); } } const RectangleInt rectScreen={0,0,mScreenWidth,mScreenHeight}; mInvalidateRgn->intersect(rectScreen); for(int i=0;iget_num_rectangles();i++){ RectangleInt r=mInvalidateRgn->get_rectangle(i); - GFXFillRect(primarySurface,(const GFXRect*)&r,0); + GFXFillRect(mPrimarySurface,(const GFXRect*)&r,0); LOGV("%d:(%d,%d,%d,%d)",i,r.x,r.y,r.width,r.height); } mInvalidateRgn->do_xor(mInvalidateRgn); - GFXFlip(primarySurface); + GFXFlip(mPrimarySurface); t2=SystemClock::uptimeMillis(); mLastComposeTime = SystemClock::uptimeMillis(); mPendingCompose = 0; diff --git a/src/gui/core/graphdevice.h b/src/gui/core/graphdevice.h old mode 100644 new mode 100755 index cd25025f..60981cca --- a/src/gui/core/graphdevice.h +++ b/src/gui/core/graphdevice.h @@ -22,8 +22,10 @@ private: uint64_t mFpsNumFrames; std::mutex mMutex; std::condition_variable mCV; - class Canvas*primaryContext;// - HANDLE primarySurface; + HANDLE mPrimarySurface; + HANDLE mBannerSurface; + class Canvas*mPrimaryContext; + Canvas *mBannerContext; RefPtrmInvalidateRgn; static GraphDevice*mInst; GraphDevice(int format=-1); @@ -44,7 +46,7 @@ public: bool needCompose(); Canvas*getPrimaryContext(); void invalidate(const Rect&); - HANDLE getPrimarySurface(){return primarySurface;} + HANDLE getPrimarySurface()const; }; } #endif diff --git a/src/gui/drawables/drawablecontainer.cc b/src/gui/drawables/drawablecontainer.cc index 5ca6f3c7..63bb4052 100755 --- a/src/gui/drawables/drawablecontainer.cc +++ b/src/gui/drawables/drawablecontainer.cc @@ -18,7 +18,7 @@ public: } void invalidateDrawable(Drawable& who)override{ - // Ignore invalidation. + // Ignore invalidation. } void scheduleDrawable(Drawable& who,Runnable what, long when)override{ diff --git a/src/gui/res/mipmap/clock_dial.png b/src/gui/res/mipmap/clock_dial.png deleted file mode 100755 index f3871b0f1e3d37f959fbac1200a098647d6afa50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48283 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 diff --git a/src/gui/res/mipmap/second.png b/src/gui/res/mipmap/second.png deleted file mode 100755 index efbd98cf6661abe0aa9a41ea9519e5d9150d0b2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3296 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 e1pom5{{sLl96zKLR$*BH0000r%Dh2 diff --git a/src/gui/view/viewgroup.cc b/src/gui/view/viewgroup.cc old mode 100644 new mode 100755 index dd3fba34..e3e76cfa --- a/src/gui/view/viewgroup.cc +++ b/src/gui/view/viewgroup.cc @@ -1068,7 +1068,7 @@ View& ViewGroup::addViewInner(View* child, int index,LayoutParams* params,bool p } else { child->mParent = this; } - //if (child->hasUnhandledKeyListener()) incrementChildUnhandledKeyListeners(); + if (child->hasUnhandledKeyListener()) incrementChildUnhandledKeyListeners(); bool childHasFocus = child->hasFocus(); if (childHasFocus) requestChildFocus(child, child->findFocus()); diff --git a/src/gui/widget/adapterviewanimator.cc b/src/gui/widget/adapterviewanimator.cc new file mode 100755 index 00000000..623f58bd --- /dev/null +++ b/src/gui/widget/adapterviewanimator.cc @@ -0,0 +1,584 @@ +#include +#include +namespace cdroid{ + +DECLARE_WIDGET(AdapterViewAnimator) + +AdapterViewAnimator::AdapterViewAnimator(Context* context,const AttributeSet& attrs) + :AdapterView(context,attrs){ + initViewAnimator(); + std::string res = attrs.getString("inAnimation"); + if(res.empty()) + setInAnimation(getDefaultInAnimation()); + res = attrs.getString("outAnimation"); + + if(res.empty()) + setOutAnimation(getDefaultOutAnimation()); + + const bool flag = attrs.getBoolean("animateFirstView",true); + setAnimateFirstView(flag); + mLoopViews = attrs.getBoolean("loopViews",false); +} + +AdapterViewAnimator::~AdapterViewAnimator(){ + delete mInAnimation; + delete mOutAnimation; + for(auto v:mViewsMap) + delete v.second; + mViewsMap.clear(); + if(mDataSetObserver){ + mAdapter->unregisterDataSetObserver(mDataSetObserver); + delete mDataSetObserver; + } +} + +AdapterViewAnimator::ViewAndMetaData::ViewAndMetaData(View* view, int relativeIndex, int adapterPosition, long itemId) { + this->view = view; + this->relativeIndex = relativeIndex; + this->adapterPosition = adapterPosition; + this->itemId = itemId; +} + +void AdapterViewAnimator::initViewAnimator(){ + mInAnimation = nullptr; + mOutAnimation= nullptr; + mDataSetObserver = nullptr; + mPendingCheckForTap = [this](){ + if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) { + View* v = getCurrentView(); + showTapFeedback(v); + } + }; +} + +void AdapterViewAnimator::configureViewAnimator(int numVisibleViews, int activeOffset){ + if (activeOffset > numVisibleViews - 1) { + // Throw an exception here. + } + mMaxNumActiveViews = numVisibleViews; + mActiveOffset = activeOffset; + mPreviousViews.clear(); + for(auto v:mViewsMap) + delete v.second; + mViewsMap.clear(); + removeAllViewsInLayout(); + mCurrentWindowStart = 0; + mCurrentWindowEnd = -1; +} + +void AdapterViewAnimator::transformViewForTransition(int fromIndex, int toIndex, View* view, bool animate) { + if (fromIndex == -1) { + mInAnimation->setTarget(view); + mInAnimation->start(); + } else if (toIndex == -1) { + mOutAnimation->setTarget(view); + mOutAnimation->start(); + } +} + +ObjectAnimator* AdapterViewAnimator::getDefaultInAnimation() { + ObjectAnimator* anim = ObjectAnimator::ofFloat(nullptr, "alpha",{0.0f, 1.0f}); + anim->setDuration(DEFAULT_ANIMATION_DURATION); + return anim; +} + +ObjectAnimator* AdapterViewAnimator::getDefaultOutAnimation() { + ObjectAnimator* anim = ObjectAnimator::ofFloat(nullptr, "alpha",{1.0f, 0.0f}); + anim->setDuration(DEFAULT_ANIMATION_DURATION); + return anim; +} + +void AdapterViewAnimator::setDisplayedChild(int whichChild){ + setDisplayedChild(whichChild, true); +} + +void AdapterViewAnimator::setDisplayedChild(int whichChild, bool animate) { + if (mAdapter != nullptr) { + mWhichChild = whichChild; + if (whichChild >= getWindowSize()) { + mWhichChild = mLoopViews ? 0 : getWindowSize() - 1; + } else if (whichChild < 0) { + mWhichChild = mLoopViews ? getWindowSize() - 1 : 0; + } + + const bool hasFocus = getFocusedChild() != nullptr; + // This will clear old focus if we had it + showOnly(mWhichChild, animate); + if (hasFocus) { + // Try to retake focus if we had it + requestFocus(FOCUS_FORWARD); + } + } +} + +void AdapterViewAnimator::applyTransformForChildAtIndex(View* child, int relativeIndex) { + //NOTHING +} + + +int AdapterViewAnimator::getDisplayedChild() { + return mWhichChild; +} + +void AdapterViewAnimator::showNext(){ + setDisplayedChild(mWhichChild + 1); +} + +void AdapterViewAnimator::showPrevious(){ + setDisplayedChild(mWhichChild - 1); +} + +int AdapterViewAnimator::modulo(int pos, int size) { + if (size > 0) { + return (size + (pos % size)) % size; + } else { + return 0; + } +} + +View* AdapterViewAnimator::getViewAtRelativeIndex(int relativeIndex){ + if (relativeIndex >= 0 && relativeIndex <= getNumActiveViews() - 1 && mAdapter != nullptr) { + int i = modulo(mCurrentWindowStartUnbounded + relativeIndex, getWindowSize()); + auto it=mViewsMap.find(i); + if (it!=mViewsMap.end()) { + return it->second->view; + } + } + return nullptr; +} + +int AdapterViewAnimator::getNumActiveViews() { + if (mAdapter != nullptr) { + return std::min(getCount() + 1, mMaxNumActiveViews); + } else { + return mMaxNumActiveViews; + } +} + +int AdapterViewAnimator::getWindowSize() { + if (mAdapter != nullptr) { + const int adapterCount = getCount(); + if (adapterCount <= getNumActiveViews() && mLoopViews) { + return adapterCount*mMaxNumActiveViews; + } else { + return adapterCount; + } + } else { + return 0; + } +} + +AdapterViewAnimator::ViewAndMetaData* AdapterViewAnimator::getMetaDataForChild(View* child){ + for (auto it= mViewsMap.begin();it!=mViewsMap.end();it++) { + if (it->second->view == child) { + return it->second; + } + } + return nullptr; +} + +LayoutParams* AdapterViewAnimator::createOrReuseLayoutParams(View* v) { + LayoutParams* currentLp = v->getLayoutParams(); + if (currentLp != nullptr) { + return currentLp; + } + return new LayoutParams(0, 0); +} + +void AdapterViewAnimator::refreshChildren() { + if (mAdapter == nullptr) return; + for (int i = mCurrentWindowStart; i <= mCurrentWindowEnd; i++) { + int index = modulo(i, getWindowSize()); + + int adapterCount = getCount(); + // get the fresh child from the adapter + View* updatedChild = mAdapter->getView(modulo(i, adapterCount), nullptr, this); + + /*if (updatedChild->getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + updatedChild->setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); + }*/ + auto it = mViewsMap.find(index); + if (mViewsMap.end()!=it) { + FrameLayout* fl = (FrameLayout*) it->second->view; + // add the new child to the frame, if it exists + if (updatedChild != nullptr) { + // flush out the old child + fl->removeAllViewsInLayout(); + fl->addView(updatedChild); + } + } + } +} + +FrameLayout* AdapterViewAnimator::getFrameForChild() { + return new FrameLayout(mContext,AttributeSet()); +} + +void AdapterViewAnimator::showOnly(int childIndex, bool animate) { + if (mAdapter == nullptr) return; + const int adapterCount = getCount(); + if (adapterCount == 0) return; + + for (int i = 0; i < mPreviousViews.size(); i++) { + auto it = mViewsMap.find(mPreviousViews.at(i)); + View* viewToRemove = it->second->view; + mViewsMap.erase(it); + delete it->second; + viewToRemove->clearAnimation(); + if (dynamic_cast(viewToRemove)) { + ViewGroup* vg = (ViewGroup*) viewToRemove; + vg->removeAllViewsInLayout(); + } + // applyTransformForChildAtIndex here just allows for any cleanup + // associated with this view that may need to be done by a subclass + applyTransformForChildAtIndex(viewToRemove, -1); + + removeViewInLayout(viewToRemove); + } + mPreviousViews.clear(); + int newWindowStartUnbounded = childIndex - mActiveOffset; + int newWindowEndUnbounded = newWindowStartUnbounded + getNumActiveViews() - 1; + int newWindowStart = std::max(0, newWindowStartUnbounded); + int newWindowEnd = std::min(adapterCount - 1, newWindowEndUnbounded); + + if (mLoopViews) { + newWindowStart = newWindowStartUnbounded; + newWindowEnd = newWindowEndUnbounded; + } + int rangeStart = modulo(newWindowStart, getWindowSize()); + int rangeEnd = modulo(newWindowEnd, getWindowSize()); + + bool wrap = false; + if (rangeStart > rangeEnd) { + wrap = true; + } + + // This section clears out any items that are in our active views list + // but are outside the effective bounds of our window (this is becomes an issue + // at the extremities of the list, eg. where newWindowStartUnbounded < 0 or + // newWindowEndUnbounded > adapterCount - 1 + for (auto vm : mViewsMap) { + int index=vm.first; + bool remove = false; + if (!wrap && (index < rangeStart || index > rangeEnd)) { + remove = true; + } else if (wrap && (index > rangeEnd && index < rangeStart)) { + remove = true; + } + + if (remove) { + View* previousView = vm.second->view; + int oldRelativeIndex = vm.second->relativeIndex; + + mPreviousViews.push_back(index); + transformViewForTransition(oldRelativeIndex, -1, previousView, animate); + } + } + + // If the window has changed + if (!(newWindowStart == mCurrentWindowStart && newWindowEnd == mCurrentWindowEnd && + newWindowStartUnbounded == mCurrentWindowStartUnbounded)) { + // Run through the indices in the new range + for (int i = newWindowStart; i <= newWindowEnd; i++) { + + int index = modulo(i, getWindowSize()); + int oldRelativeIndex; + auto it=mViewsMap.find(index); + if (it!=mViewsMap.end()) { + oldRelativeIndex = it->second->relativeIndex; + } else { + oldRelativeIndex = -1; + } + int newRelativeIndex = i - newWindowStartUnbounded; + + // If this item is in the current window, great, we just need to apply + // the transform for it's new relative position in the window, and animate + // between it's current and new relative positions + bool inOldRange = it!=mViewsMap.end()&& std::find(mPreviousViews.begin(), + mPreviousViews.end(),index)==mPreviousViews.end(); + + if (inOldRange) { + View* view = it->second->view; + it->second->relativeIndex = newRelativeIndex; + applyTransformForChildAtIndex(view, newRelativeIndex); + transformViewForTransition(oldRelativeIndex, newRelativeIndex, view, animate); + + // Otherwise this view is new to the window + } else { + // Get the new view from the adapter, add it and apply any transform / animation + const int adapterPosition = modulo(i, adapterCount); + View* newView = mAdapter->getView(adapterPosition, nullptr, this); + long itemId = mAdapter->getItemId(adapterPosition); + + // We wrap the new view in a FrameLayout so as to respect the contract + // with the adapter, that is, that we don't modify this view directly + FrameLayout* fl = getFrameForChild(); + + // If the view from the adapter is null, we still keep an empty frame in place + if (newView != nullptr) { + fl->addView(newView); + } + mViewsMap.insert(std::pair(index, new ViewAndMetaData(fl, newRelativeIndex, + adapterPosition, itemId))); + addChild(fl); + applyTransformForChildAtIndex(fl, newRelativeIndex); + transformViewForTransition(-1, newRelativeIndex, fl, animate); + } + mViewsMap[index]->view->bringToFront(); + } + mCurrentWindowStart = newWindowStart; + mCurrentWindowEnd = newWindowEnd; + mCurrentWindowStartUnbounded = newWindowStartUnbounded; + /*if (mRemoteViewsAdapter != nullptr) { + int adapterStart = modulo(mCurrentWindowStart, adapterCount); + int adapterEnd = modulo(mCurrentWindowEnd, adapterCount); + mRemoteViewsAdapter.setVisibleRangeHint(adapterStart, adapterEnd); + }*/ + } + requestLayout(); + invalidate(); +} + +void AdapterViewAnimator::addChild(View* child) { + addViewInLayout(child, -1, createOrReuseLayoutParams(child)); + + // This code is used to obtain a reference width and height of a child in case we need + // to decide our own size. TODO: Do we want to update the size of the child that we're + // using for reference size? If so, when? + if (mReferenceChildWidth == -1 || mReferenceChildHeight == -1) { + const int measureSpec = MeasureSpec::makeMeasureSpec(0, MeasureSpec::UNSPECIFIED); + child->measure(measureSpec, measureSpec); + mReferenceChildWidth = child->getMeasuredWidth(); + mReferenceChildHeight = child->getMeasuredHeight(); + } +} + +void AdapterViewAnimator::showTapFeedback(View* v) { + v->setPressed(true); +} + +void AdapterViewAnimator::hideTapFeedback(View* v) { + v->setPressed(false); +} + +void AdapterViewAnimator::cancelHandleClick() { + View* v = getCurrentView(); + if (v != nullptr) { + hideTapFeedback(v); + } + mTouchMode = TOUCH_MODE_NONE; +} + +bool AdapterViewAnimator::onTouchEvent(MotionEvent& ev){ + int action = ev.getAction(); + bool handled = false; + View*v =nullptr; + switch (action) { + case MotionEvent::ACTION_DOWN: + if (v=getCurrentView()) { + if (isTransformedTouchPointInView(ev.getX(), ev.getY(), *v, nullptr)) { + mTouchMode = TOUCH_MODE_DOWN_IN_CURRENT_VIEW; + postDelayed(mPendingCheckForTap, ViewConfiguration::getTapTimeout()); + } + } + break; + case MotionEvent::ACTION_MOVE: break; + case MotionEvent::ACTION_POINTER_UP: break; + case MotionEvent::ACTION_UP: + if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) { + v = getCurrentView(); + ViewAndMetaData* viewData = getMetaDataForChild(v); + if (v != nullptr) { + if (isTransformedTouchPointInView(ev.getX(), ev.getY(), *v, nullptr)) { + removeCallbacks(mPendingCheckForTap); + showTapFeedback(v); + postDelayed([this,viewData,v](){ + if (viewData != nullptr) + performItemClick(v, viewData->adapterPosition,viewData->itemId); + else performItemClick(v, 0, 0); + },ViewConfiguration::getPressedStateDuration()); + handled = true; + } + } + } + mTouchMode = TOUCH_MODE_NONE; + break; + case MotionEvent::ACTION_CANCEL: + v = getCurrentView(); + if (v != nullptr) { + hideTapFeedback(v); + } + mTouchMode = TOUCH_MODE_NONE; + } + return handled; +} + +void AdapterViewAnimator::measureChildren() { + const int count = getChildCount(); + int childWidth = getMeasuredWidth() - mPaddingLeft - mPaddingRight; + int childHeight = getMeasuredHeight() - mPaddingTop - mPaddingBottom; + + for (int i = 0; i < count; i++) { + View* child = getChildAt(i); + child->measure(MeasureSpec::makeMeasureSpec(childWidth, MeasureSpec::EXACTLY), + MeasureSpec::makeMeasureSpec(childHeight, MeasureSpec::EXACTLY)); + } +} + +void AdapterViewAnimator::onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSpecSize = MeasureSpec::getSize(widthMeasureSpec); + int heightSpecSize = MeasureSpec::getSize(heightMeasureSpec); + int widthSpecMode = MeasureSpec::getMode(widthMeasureSpec); + int heightSpecMode = MeasureSpec::getMode(heightMeasureSpec); + + bool haveChildRefSize = (mReferenceChildWidth != -1 && mReferenceChildHeight != -1); + + // We need to deal with the case where our parent hasn't told us how + // big we should be. In this case we try to use the desired size of the first + // child added. + if (heightSpecMode == MeasureSpec::UNSPECIFIED) { + heightSpecSize = haveChildRefSize ? mReferenceChildHeight + mPaddingTop + + mPaddingBottom : 0; + } else if (heightSpecMode == MeasureSpec::AT_MOST) { + if (haveChildRefSize) { + int height = mReferenceChildHeight + mPaddingTop + mPaddingBottom; + if (height > heightSpecSize) { + heightSpecSize |= MEASURED_STATE_TOO_SMALL; + } else { + heightSpecSize = height; + } + } + } + + if (widthSpecMode == MeasureSpec::UNSPECIFIED) { + widthSpecSize = haveChildRefSize ? mReferenceChildWidth + mPaddingLeft + + mPaddingRight : 0; + } else if (heightSpecMode == MeasureSpec::AT_MOST) { + if (haveChildRefSize) { + int width = mReferenceChildWidth + mPaddingLeft + mPaddingRight; + if (width > widthSpecSize) { + widthSpecSize |= MEASURED_STATE_TOO_SMALL; + } else { + widthSpecSize = width; + } + } + } + + setMeasuredDimension(widthSpecSize, heightSpecSize); + measureChildren(); +} + +void AdapterViewAnimator::checkForAndHandleDataChanged() { + bool dataChanged = mDataChanged; + if (dataChanged) { + post([this](){ + handleDataChanged(); + // if the data changes, mWhichChild might be out of the bounds of the adapter + // in this case, we reset mWhichChild to the beginning + if (mWhichChild >= getWindowSize()) { + mWhichChild = 0; + + showOnly(mWhichChild, false); + } else if (mOldItemCount != getCount()) { + showOnly(mWhichChild, false); + } + refreshChildren(); + requestLayout(); + }); + } + mDataChanged = false; +} + +void AdapterViewAnimator::onLayout(bool changed, int left, int top, int width, int height) { + checkForAndHandleDataChanged(); + + const int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View* child = getChildAt(i); + + const int childWidth = child->getMeasuredWidth(); + const int childHeight= child->getMeasuredHeight(); + + child->layout(mPaddingLeft, mPaddingTop, childWidth, childHeight); + } +} + +View* AdapterViewAnimator::getCurrentView(){ + return getViewAtRelativeIndex(mActiveOffset); +} + +ObjectAnimator* AdapterViewAnimator::getInAnimation() { + return mInAnimation; +} + +ObjectAnimator* AdapterViewAnimator::getOutAnimation() { + return mOutAnimation; +} + +void AdapterViewAnimator::setInAnimation(ObjectAnimator* inAnimation) { + mInAnimation=inAnimation; +} + +void AdapterViewAnimator::setOutAnimation(ObjectAnimator* outAnimation) { + mInAnimation=outAnimation; +} + +void AdapterViewAnimator::setInAnimation(Context* context, const std::string&resourceID) { + setInAnimation((ObjectAnimator*) AnimatorInflater::loadAnimator(context, resourceID)); +} + +void AdapterViewAnimator::setOutAnimation(Context* context, const std::string&resourceID) { + setOutAnimation((ObjectAnimator*) AnimatorInflater::loadAnimator(context, resourceID)); +} + +void AdapterViewAnimator::setAnimateFirstView(bool animate) { + mAnimateFirstTime = animate; +} + +int AdapterViewAnimator::getBaseline() { + return getCurrentView() ? getCurrentView()->getBaseline() : AdapterView::getBaseline(); +} + +Adapter* AdapterViewAnimator::getAdapter() { + return mAdapter; +} + +void AdapterViewAnimator::setAdapter(Adapter* adapter) { + if (mAdapter != nullptr && mDataSetObserver != nullptr) { + mAdapter->unregisterDataSetObserver(mDataSetObserver); + delete mDataSetObserver; + } + + mAdapter = adapter; + checkFocus(); + + if (mAdapter != nullptr) { + mDataSetObserver = new AdapterDataSetObserver(this); + mAdapter->registerDataSetObserver(mDataSetObserver); + mItemCount = mAdapter->getCount(); + } + setFocusable(true); + mWhichChild = 0; + showOnly(mWhichChild, false); +} + +void AdapterViewAnimator::setSelection(int position) { + setDisplayedChild(position); +} + +View* AdapterViewAnimator::getSelectedView() { + return getViewAtRelativeIndex(mActiveOffset); +} + +/** +* This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not +* connected yet.*/ +void AdapterViewAnimator::deferNotifyDataSetChanged() { + mDeferNotifyDataSetChanged = true; +} + +void AdapterViewAnimator::advance() { + showNext(); +} + +}//endof namespace diff --git a/src/gui/widget/adapterviewanimator.h b/src/gui/widget/adapterviewanimator.h new file mode 100755 index 00000000..740d84cd --- /dev/null +++ b/src/gui/widget/adapterviewanimator.h @@ -0,0 +1,141 @@ +#ifndef __ADAPTERVIEW_ANIMATOR_H__ +#define __ADAPTERVIEW_ANIMATOR_H__ +#include +#include + +namespace cdroid{ + +class AdapterViewAnimator:public AdapterView{ +private: + static constexpr int DEFAULT_ANIMATION_DURATION = 200; + /* Private touch states.*/ + static constexpr int TOUCH_MODE_NONE = 0; + static constexpr int TOUCH_MODE_DOWN_IN_CURRENT_VIEW = 1; + static constexpr int TOUCH_MODE_HANDLED = 2; + int mRestoreWhichChild = -1; + /* Current touch state.*/ + Runnable mPendingCheckForTap; + int mTouchMode = TOUCH_MODE_NONE; + + class ViewAndMetaData { + public: + View* view; + int relativeIndex; + int adapterPosition; + long itemId; + public: + ViewAndMetaData(View* view, int relativeIndex, int adapterPosition, long itemId); + }; +protected: + int mWhichChild = 0; + + /* The index of the child to restore after the asynchronous connection from the + * RemoteViewsAdapter has been. */ + + /* Whether or not the first view(s) should be animated in*/ + bool mAnimateFirstTime = true; + + /* Represents where the in the current window of + * views the current mDisplayedChild sits */ + int mActiveOffset = 0; + + /**The number of views that the {@link AdapterViewAnimator} keeps as children at any + * given time (not counting views that are pending removal, see {@link #mPreviousViews}). */ + int mMaxNumActiveViews = 1; + + /* Map of the children of the {@link AdapterViewAnimator}.*/ + std::map mViewsMap; + + /* List of views pending removal from the {@link AdapterViewAnimator}*/ + std::vector mPreviousViews; + + /* The index, relative to the adapter, of the beginning of the window of views */ + int mCurrentWindowStart = 0; + + /* The index, relative to the adapter, of the end of the window of views */ + int mCurrentWindowEnd = -1; + + /* The same as {@link #mCurrentWindowStart}, except when the we have bounded + * {@link #mCurrentWindowStart} to be non-negative */ + int mCurrentWindowStartUnbounded = 0; + + /* Listens for data changes from the adapter */ + DataSetObserver* mDataSetObserver; + + /* The {@link Adapter} for this {@link AdapterViewAnimator} */ + Adapter* mAdapter; + + /* The {@link RemoteViewsAdapter} for this {@link AdapterViewAnimator}*/ + //RemoteViewsAdapter mRemoteViewsAdapter; + + /* The remote adapter containing the data to be displayed by this view to be set */ + bool mDeferNotifyDataSetChanged = false; + + /* Specifies whether this is the first time the animator is showing views */ + bool mFirstTime = true; + + /* Specifies if the animator should wrap from 0 to the end and vice versa + * or have hard boundaries at the beginning and end */ + bool mLoopViews = true; + + /* The width and height of some child, used as a size reference in-case our + * dimensions are unspecified by the parent. */ + int mReferenceChildWidth = -1; + int mReferenceChildHeight = -1; + + /* In and out animations. */ + ObjectAnimator* mInAnimation; + ObjectAnimator* mOutAnimation; +private: + void initViewAnimator(); + void setDisplayedChild(int whichChild, bool animate); + ViewAndMetaData* getMetaDataForChild(View* child); + void addChild(View* child); + void measureChildren(); +protected: + void configureViewAnimator(int numVisibleViews, int activeOffset); + void transformViewForTransition(int fromIndex, int toIndex, View* view, bool animate); + ObjectAnimator* getDefaultInAnimation(); + ObjectAnimator* getDefaultOutAnimation(); + void applyTransformForChildAtIndex(View* child, int relativeIndex); + int modulo(int pos, int size); + View* getViewAtRelativeIndex(int relativeIndex); + int getNumActiveViews(); + int getWindowSize(); + LayoutParams* createOrReuseLayoutParams(View* v); + void refreshChildren(); + FrameLayout* getFrameForChild(); + void showOnly(int childIndex, bool animate); + void showTapFeedback(View* v); + void hideTapFeedback(View* v); + void cancelHandleClick(); + void onMeasure(int widthMeasureSpec, int heightMeasureSpec)override; + void checkForAndHandleDataChanged(); + void onLayout(bool changed, int left, int top, int width, int height)override; +public: + AdapterViewAnimator(Context* context,const AttributeSet& attrs); + ~AdapterViewAnimator()override; + void setDisplayedChild(int whichChild); + int getDisplayedChild(); + void showNext(); + void showPrevious(); + bool onTouchEvent(MotionEvent& ev)override; + View* getCurrentView(); + ObjectAnimator* getInAnimation(); + void setInAnimation(ObjectAnimator* inAnimation); + ObjectAnimator* getOutAnimation(); + void setOutAnimation(ObjectAnimator* outAnimation); + void setInAnimation(Context* context,const std::string& resourceID); + void setOutAnimation(Context* context,const std::string& resourceID); + void setAnimateFirstView(bool animate); + int getBaseline()override; + Adapter* getAdapter()override; + void setAdapter(Adapter* adapter)override; + void setSelection(int position)override; + View* getSelectedView()override; + void deferNotifyDataSetChanged(); + void advance(); +}; + +}//namepace +#endif diff --git a/src/gui/widget/recyclebin.cc b/src/gui/widget/recyclebin.cc old mode 100644 new mode 100755 index f56d2a5c..2a526850 --- a/src/gui/widget/recyclebin.cc +++ b/src/gui/widget/recyclebin.cc @@ -352,9 +352,9 @@ View* RecycleBin::retrieveFromScrap(std::vector& scrapViews, int position if (LV->mAdapterHasStableIds) { long id = getAdapter()->getItemId(position); if (id == params->itemId) { - View*scrap=scrapViews[i]; + View*scrap=scrapViews[i]; scrapViews.erase(scrapViews.begin()+i);//remove(i); - return scrap; + return scrap; } } else if (params->scrappedFromPosition == position) { View* scrap = scrapViews[i]; @@ -375,8 +375,8 @@ View* RecycleBin::retrieveFromScrap(std::vector& scrapViews, int position void RecycleBin::clearScrap(std::vector& scrap) { int scrapCount = scrap.size(); for (int j = 0; j < scrapCount; j++) { - View*v=scrap[scrapCount - 1 - j]; - scrap.erase(scrap.begin()+scrapCount - 1 - j); + View*v=scrap[scrapCount - 1 - j]; + scrap.erase(scrap.begin()+scrapCount - 1 - j); removeDetachedView(v, false); } } diff --git a/src/gui/widget/viewpager.cc b/src/gui/widget/viewpager.cc index 801c37ce..ef7bbe08 100755 --- a/src/gui/widget/viewpager.cc +++ b/src/gui/widget/viewpager.cc @@ -111,7 +111,6 @@ void ViewPager::setAdapter(PagerAdapter* adapter){ for (int i = 0; i < mItems.size(); i++) { ItemInfo* ii = mItems[i]; mAdapter->destroyItem(this, ii->position, ii->object); - delete (View*)ii->object;//added by zhhou } mAdapter->finishUpdate(this); mItems.clear(); @@ -474,7 +473,6 @@ void ViewPager::dataSetChanged(){ } mAdapter->destroyItem(this, ii->position, ii->object); - delete (View*)ii->object;//added by zhhou needPopulate = true; if (mCurItem == ii->position) { // Keep the current item in the valid range @@ -583,7 +581,6 @@ void ViewPager::populate(int newCurrentItem){ if (pos == ii->position && !ii->scrolling) { mItems.erase(mItems.begin()+itemIndex); mAdapter->destroyItem(this, pos, ii->object); - delete (View*)ii->object;//added by zhhou LOGD("destroyItem() with pos:%d/%d view:%p curitem=%d/%d",pos,ii->position,ii->object,mCurItem,mItems.size()); itemIndex--; curIndex--; @@ -615,7 +612,6 @@ void ViewPager::populate(int newCurrentItem){ if (pos == ii->position && !ii->scrolling) { mItems.erase(mItems.begin()+itemIndex); mAdapter->destroyItem(this, pos, ii->object); - delete (View*)ii->object;//added by zhhou ii = itemIndex < mItems.size() ? mItems[itemIndex] : nullptr; } } else if (ii != nullptr && pos == ii->position) {