mirror of
https://gitee.com/houstudio/Cdroid.git
synced 2024-12-02 04:07:42 +08:00
add adapterviewanimator and animatorinflater
This commit is contained in:
parent
fd9b4fa7af
commit
298fcab43e
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
}
|
||||
void destroyItem(ViewGroup* container, int position,void* object){
|
||||
container->removeView((View*)object);
|
||||
delete (View*)object;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;}
|
||||
|
||||
|
@ -12,7 +12,14 @@
|
||||
#include <fileadapter.h>
|
||||
#include <R.h>
|
||||
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<<position*8));
|
||||
container->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;
|
||||
}
|
||||
|
||||
|
90
src/gui/animation/animatorinflater.cc
Executable file
90
src/gui/animation/animatorinflater.cc
Executable file
@ -0,0 +1,90 @@
|
||||
#include <animation/animatorset.h>
|
||||
#include <animation/animatorinflater.h>
|
||||
#include <expat.h>
|
||||
|
||||
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::vector<Animator*>animators;
|
||||
std::string package;
|
||||
Animator*result;
|
||||
std::function<ObjectAnimator*(Context*,const AttributeSet&)>fnObject;
|
||||
std::function<ValueAnimator*(Context*,const AttributeSet&,ValueAnimator*)>fnAnimator;
|
||||
}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_ptr<std::istream>stream=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;
|
||||
}
|
||||
|
||||
}
|
23
src/gui/animation/animatorinflater.h
Executable file
23
src/gui/animation/animatorinflater.h
Executable file
@ -0,0 +1,23 @@
|
||||
#ifndef __ANIMATOR_INFLATER_H__
|
||||
#define __ANIMATOR_INFLATER_H__
|
||||
#include <animation/objectanimator.h>
|
||||
#include <animation/statelistanimator.h>
|
||||
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
|
39
src/gui/core/graphdevice.cc
Normal file → Executable file
39
src/gui/core/graphdevice.cc
Normal file → Executable file
@ -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);
|
||||
RefPtr<Surface>surf=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<wSurfaces.size();i++){
|
||||
Rect rcw = wBounds[i];
|
||||
RefPtr<Region> 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;i<mInvalidateRgn->get_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;
|
||||
|
8
src/gui/core/graphdevice.h
Normal file → Executable file
8
src/gui/core/graphdevice.h
Normal file → Executable file
@ -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;
|
||||
RefPtr<Region>mInvalidateRgn;
|
||||
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
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
}
|
||||
|
||||
void invalidateDrawable(Drawable& who)override{
|
||||
// Ignore invalidation.
|
||||
// Ignore invalidation.
|
||||
}
|
||||
|
||||
void scheduleDrawable(Drawable& who,Runnable what, long when)override{
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 47 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.2 KiB |
2
src/gui/view/viewgroup.cc
Normal file → Executable file
2
src/gui/view/viewgroup.cc
Normal file → Executable file
@ -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());
|
||||
|
584
src/gui/widget/adapterviewanimator.cc
Executable file
584
src/gui/widget/adapterviewanimator.cc
Executable file
@ -0,0 +1,584 @@
|
||||
#include <widget/adapterviewanimator.h>
|
||||
#include <animation/animatorinflater.h>
|
||||
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<ViewGroup*>(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<int,ViewAndMetaData*>(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
|
141
src/gui/widget/adapterviewanimator.h
Executable file
141
src/gui/widget/adapterviewanimator.h
Executable file
@ -0,0 +1,141 @@
|
||||
#ifndef __ADAPTERVIEW_ANIMATOR_H__
|
||||
#define __ADAPTERVIEW_ANIMATOR_H__
|
||||
#include <widget/adapterview.h>
|
||||
#include <widget/framelayout.h>
|
||||
|
||||
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 <code>mDisplayedChild</code> 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<int, ViewAndMetaData*> mViewsMap;
|
||||
|
||||
/* List of views pending removal from the {@link AdapterViewAnimator}*/
|
||||
std::vector<int> 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
|
8
src/gui/widget/recyclebin.cc
Normal file → Executable file
8
src/gui/widget/recyclebin.cc
Normal file → Executable file
@ -352,9 +352,9 @@ View* RecycleBin::retrieveFromScrap(std::vector<View*>& 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<View*>& scrapViews, int position
|
||||
void RecycleBin::clearScrap(std::vector<View*>& 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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user