itemanimator can working with some bugs

This commit is contained in:
侯歌 2024-05-15 17:13:49 +08:00
parent 3318715899
commit ff09f2829b
3 changed files with 69 additions and 69 deletions

View File

@ -25,8 +25,8 @@ public:
TextView* view = new TextView("",200,64);
view->setBackgroundColor(0xff234567);
view->setGravity(Gravity::CENTER);
//view->setLayoutParams(new LayoutParams(LayoutParams::MATCH_PARENT,80));//LayoutParams::WRAP_CONTENT));
view->setLayoutParams(new LayoutParams(120,LayoutParams::MATCH_PARENT));//LayoutParams::WRAP_CONTENT));
view->setLayoutParams(new LayoutParams(LayoutParams::MATCH_PARENT,80));//LayoutParams::WRAP_CONTENT));
//view->setLayoutParams(new LayoutParams(120,LayoutParams::MATCH_PARENT));//LayoutParams::WRAP_CONTENT));
//view->setLayoutParams(new LayoutParams(640,LayoutParams::MATCH_PARENT));
return new ViewHolder(view);
}
@ -44,6 +44,9 @@ public:
LOGD("click item positon=%d holder lp",position,lp);
});
}
void remove(int idx){
items.erase(items.begin()+idx);
}
void add(const std::string&str){
items.push_back(str);
}
@ -65,32 +68,6 @@ int main(int argc,const char*argv[]){
RecyclerView*rv=new RecyclerView(800,480);
auto ps = new LinearSnapHelper();//PagerSnapHelper();
ps->attachToRecyclerView(rv);
CarouselLayoutManager*carousel=new CarouselLayoutManager(CarouselLayoutManager::HORIZONTAL);//VERTICAL);//HORIZONTAL);
//rv->setLayoutManager(carousel);
((LinearLayoutManager*)rv->getLayoutManager())->setOrientation(LinearLayoutManager::HORIZONTAL);
carousel->setPostLayoutListener([carousel](View& child,CarouselLayoutManager::ItemTransformation&ti,float itemPositionToCenterDiff,int orientation,int itemPositionInAdapter)->bool{
const float mScaleMultiplier =0.1f;
const float scale = 1.f - mScaleMultiplier*std::abs(itemPositionToCenterDiff);
// because scaling will make view smaller in its center, then we should move this item to the top or bottom to make it visible
float translateY,translateX,translateGeneral;
float sig = itemPositionToCenterDiff>0.f?1.f:-1.f;
if (CarouselLayoutManager::VERTICAL == orientation) {
translateGeneral = child.getMeasuredHeight() * (1.f - scale) / 2.f;
translateY = sig * translateGeneral;
translateX = 0;
} else {
translateGeneral = child.getMeasuredHeight()*itemPositionToCenterDiff* (1.f-scale);
translateX = translateGeneral;
translateY = 0;//(child.getMeasuredHeight()*(1.f-scale))/2.f;
}
ti.mScaleX = ti.mScaleY = scale;
ti.mTranslationX = translateX;
ti.mTranslationY = translateY;
//LOGD("orientation=%d centeritem=%d itemdiff=%.f translateGeneral=%.f scale=%f X=%d transX/Y=%.f,%.f",
// orientation,carousel->getCenterItemPosition(),itemPositionToCenterDiff,translateGeneral,scale,child.getLeft(),translateX,translateY);
return true;
});
MyAdapter*adapter=new MyAdapter();
rv->setHasFixedSize(true);
rv->getRecycledViewPool().setMaxRecycledViews(0,64);
@ -98,20 +75,20 @@ int main(int argc,const char*argv[]){
rv->setOverScrollMode(View::OVER_SCROLL_ALWAYS);
rv->setAdapter(adapter);
DividerItemDecoration* decoration = new DividerItemDecoration(&app, LinearLayout::VERTICAL);
auto anim=rv->getItemAnimator();
anim->setRemoveDuration(200);
anim->setAddDuration(200);
anim->setMoveDuration(200);
anim->setChangeDuration(200);
rv->getLayoutManager()->requestSimpleAnimationsInNextLayout();
for(int i=0;i<100;i++){
adapter->add(std::string("string ")+std::to_string(i));
//adapter->notifyItemInserted(i);//Notice:call notifyItemInserted before layout will cause memleak.
}
decoration->setDrawable(new ColorDrawable(0xFFFF0000));
rv->addItemDecoration(decoration);
w->addView(rv);
w->requestLayout();
Runnable r;
r=[&](){
adapter->remove(4);
adapter->notifyItemRemoved(4);
};
w->postDelayed(r,8000);
app.exec();
}

View File

@ -41,7 +41,7 @@ void DefaultItemAnimator::runPendingAnimations() {
// Next, move stuff
if (movesPending) {
mMovesList.push_back(mPendingMoves);
std::vector<MoveInfo*>&moves=mMovesList.back();
std::vector<MoveInfo*>&moves = mMovesList.back();
mPendingMoves.clear();
Runnable mover;
mover=[this,&moves]() {
@ -84,7 +84,7 @@ void DefaultItemAnimator::runPendingAnimations() {
// Next, add stuff
if (additionsPending) {
mAdditionsList.push_back(mPendingAdditions);
std::vector<RecyclerView::ViewHolder*>& additions=mAdditionsList.back();
std::vector<RecyclerView::ViewHolder*>& additions = mAdditionsList.back();
mPendingAdditions.clear();
Runnable adder;
adder = [this,&additions]() {
@ -114,6 +114,22 @@ bool DefaultItemAnimator::animateRemove(RecyclerView::ViewHolder& holder) {
return true;
}
void DefaultItemAnimator::onRemoveAnimationStart(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
dispatchRemoveStarting(*holder);
}
void DefaultItemAnimator::onRemoveAnimationEnd(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
ViewPropertyAnimator& animation = holder->itemView->animate();
animation.setListener({});
holder->itemView->setAlpha(1);
dispatchRemoveFinished(*holder);
auto it = std::find(mRemoveAnimations.begin(),mRemoveAnimations.end(),holder);
if(it!=mRemoveAnimations.end())mRemoveAnimations.erase(it);//mRemoveAnimations.remove(holder);
else LOGE("not found.....");
dispatchFinishedWhenDone();
}
void DefaultItemAnimator::animateRemoveImpl(RecyclerView::ViewHolder& holder) {
View* view = holder.itemView;
@ -121,18 +137,8 @@ void DefaultItemAnimator::animateRemoveImpl(RecyclerView::ViewHolder& holder) {
mRemoveAnimations.push_back(&holder);//add(holder);
//AnimatorListenerAdapter
Animator::AnimatorListener al;
al.onAnimationStart=[this,&holder](Animator&animator,bool isReverse){
dispatchRemoveStarting(holder);
};
al.onAnimationEnd=[this,&animation,&holder](Animator& animator,bool isReverse){
animation.setListener({});
holder.itemView->setAlpha(1);
dispatchRemoveFinished(holder);
auto it = std::find(mRemoveAnimations.begin(),mRemoveAnimations.end(),&holder);
if(it!=mRemoveAnimations.end())mRemoveAnimations.erase(it);//mRemoveAnimations.remove(holder);
else LOGE("not found.....");
dispatchFinishedWhenDone();
};
al.onAnimationStart=std::bind(&DefaultItemAnimator::onRemoveAnimationStart,this,&holder,std::placeholders::_1,std::placeholders::_2);
al.onAnimationEnd = std::bind(&DefaultItemAnimator::onRemoveAnimationEnd,this,&holder,std::placeholders::_1,std::placeholders::_2);
animation.setDuration(getRemoveDuration()).alpha(0).setListener(al).start();
}
@ -185,10 +191,30 @@ bool DefaultItemAnimator::animateMove(RecyclerView::ViewHolder& holder, int from
return true;
}
void DefaultItemAnimator::onMoveAnimationStart(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
dispatchMoveStarting(*holder);
}
void DefaultItemAnimator::onMoveAnimationCancel(int deltaX,int deltaY,RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
if (deltaX != 0) {
holder->itemView->setTranslationX(0);
}
if (deltaY != 0) {
holder->itemView->setTranslationY(0);
}
}
void DefaultItemAnimator::onMoveAnimationEnd(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
ViewPropertyAnimator& animation = holder->itemView->animate();
animation.setListener({});
dispatchMoveFinished(*holder);
auto it =std::find(mMoveAnimations.begin(),mMoveAnimations.end(),holder);
mMoveAnimations.erase(it);//mMoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
void DefaultItemAnimator::animateMoveImpl(RecyclerView::ViewHolder& holder, int fromX, int fromY, int toX, int toY) {
View* view = holder.itemView;
int deltaX = toX - fromX;
int deltaY = toY - fromY;
const int deltaX = toX - fromX;
const int deltaY = toY - fromY;
if (deltaX != 0) {
view->animate().translationX(0);
}
@ -202,24 +228,9 @@ void DefaultItemAnimator::animateMoveImpl(RecyclerView::ViewHolder& holder, int
mMoveAnimations.push_back(&holder);//add(holder);
Animator::AnimatorListener al;
al.onAnimationStart = [this,&holder](Animator& animator,bool isReverse) {
dispatchMoveStarting(holder);
};
al.onAnimationCancel = [this,view,deltaX,deltaY](Animator& animator) {
if (deltaX != 0) {
view->setTranslationX(0);
}
if (deltaY != 0) {
view->setTranslationY(0);
}
};
al.onAnimationEnd = [this,&animation,&holder](Animator& animator,bool isReverse) {
animation.setListener({});
dispatchMoveFinished(holder);
auto it =std::find(mMoveAnimations.begin(),mMoveAnimations.end(),&holder);
mMoveAnimations.erase(it);//mMoveAnimations.remove(holder);
dispatchFinishedWhenDone();
};
al.onAnimationStart = std::bind(&DefaultItemAnimator::onMoveAnimationStart,this,&holder,std::placeholders::_1,std::placeholders::_2);
//al.onAnimationCancel = std::bind(&DefaultItemAnimator::onMoveAnimationCancel,this,deltaX,deltaY,&holder,std::placeholders::_1,std::placeholders::_2);
al.onAnimationEnd = std::bind(&DefaultItemAnimator::onMoveAnimationEnd,this,&holder,std::placeholders::_1,std::placeholders::_2);
animation.setDuration(getMoveDuration()).setListener(al).start();
}
@ -251,6 +262,10 @@ bool DefaultItemAnimator::animateChange(RecyclerView::ViewHolder& oldHolder, Rec
return true;
}
void DefaultItemAnimator::onChangeAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse){
}
void DefaultItemAnimator::onChangeAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse){
}
void DefaultItemAnimator::animateChangeImpl(ChangeInfo& changeInfo) {
RecyclerView::ViewHolder* holder = changeInfo.oldHolder;
View* view = holder == nullptr ? nullptr : holder->itemView;

View File

@ -42,6 +42,14 @@ protected:
ChangeInfo(RecyclerView::ViewHolder& oldHolder, RecyclerView::ViewHolder& newHolder,
int fromX, int fromY, int toX, int toY);
};
protected:
void onRemoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onRemoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onMoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onMoveAnimationCancel(int deltaX,int deltaY,RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onMoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onChangeAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onChangeAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
protected:
void animateRemoveImpl(RecyclerView::ViewHolder& holder);
void endChangeAnimation(std::vector<ChangeInfo*>& infoList, RecyclerView::ViewHolder& item);