Closed AgneseBussone closed 5 years ago
Recyclerview automatically keeps scroll position when you update items in it.
you may need to programmatically scroll it to the start
My carousel is nested into an EpoxyRecyclerView
that reset its position at the top automatically when I refresh the content, so I was expecting the same behaviour from the carousel.
I'm using the generated model class for the carousel and I don't see a way to reset the position programmatically (and per my understanding I'm not allowed to modify a model after the buildModels()
has been called).
Should I use a different way to build the carousel?
I've tried resetting the position in the onBind()
callback like this
new OfferCarouselModel_()
.id("offer")
.padding(carouselPadding)
.numViewsToShowOnScreen(1.1F)
.models(generatePopularOfferModels())
.onBind(new OnModelBoundListener<OfferCarouselModel_, OfferCarousel>() {
@Override
public void onModelBound(OfferCarouselModel_ model, OfferCarousel view, int position) {
view.scrollToPosition(0);
}
})
.addIf(!offersList.isEmpty(), this);
but still doesn't work.
try posting the call to view.scrollToPosition(0);
- when you update a carousel's contents the model building is posted to the next frame, just like a normal EpoxyController requestModelBuild
call
That solved my issue.
Thank you!
I need to reopen the issue because I still have some trouble with this.
I've tried this
new OfferCarouselModel_()
.id("offer")
.padding(carouselPadding)
.numViewsToShowOnScreen(1.2F)
.models(generatePopularOfferModels())
.onBind(new OnModelBoundListener<OfferCarouselModel_, OfferCarousel>() {
@Override
public void onModelBound(OfferCarouselModel_ model, final OfferCarousel view, int position) {
if (resetOfferCarouselPosition()) {
new Handler().post(new Runnable() {
@Override
public void run() {
view.scrollToPosition(0);
}
});
}
}
})
.addIf(!offersList.isEmpty(), this);
and it's working as expected, except that the onBind()
is not always called. For example, if I build the models and then trigger the refresh of the data immediately ("swipe down to refresh" action), the onBind()
won't be called, but I still need to reset the position of the carousel to the first item.
I've tried using an Interceptor
, but the scrollToPosition()
method is not available from the model; I need to access the view, but I'm not sure how to do that in the right way.
Is there a way to access the view from the model? Or is there a better way to handle this?
onBind()
is always called when the model is bound. if it isn't called then the model isn't being bound again.
if you want direct access to the views you can use epoxyController.getAdapter().getBoundViewHolders
- iterate through those and do whatever you want with them
I tried different things, but the only one that seems to work in all my use cases is the following
if (resetOfferCarouselPosition) {
BoundViewHolders boundViewHolders = getAdapter().getBoundViewHolders();
EpoxyModel<?> model = getAdapter().getModelById(offerCarouselId);
if (model != null) {
EpoxyViewHolder holder = boundViewHolders.getHolderForModel(model);
if (holder != null) {
((OfferCarousel) holder.itemView).scrollToPosition(0);
resetOfferCarouselPosition = false;
}
}
}
at the end of the buildModels()
. Is there a better solution?
Hello! Thanks for the great library!
I have a nested custom Carousel and I need to reset it to the initial position after refreshing the content. I'm using the version
2.19.0
and I load the models in thebuildModels()
like thisand when I need to refresh the content I clear the list in the controller, set the new data and then
requestModelBuild()
.Everything works fine, but if I scrolled through the carousel before refreshing its content it'll be at the old position, not at the first one. The Carousel class it's really simple
Am I missing something? Thank you!