I have a RecyclerView that contains different child views.
Then user scrolls it.
I want to know exactly how many pixels user scrolled in comparison with the beginning state.
In other words, I want to know exactly the distance (in pixels) from current content of screen and the first item of RecyclerView.
I see RecyclerView has a method computeVerticalScrollOffset. But that method returns wrong value.
It's possible with OnScrollListener. Override onScroll() method, and its arguments are the distance scrolled by horizontal or vertical axis.
But there are few problems. This passes not the final scroll value, but many values, u have to summarize until the state becomes RecyclerView.SCROLL_STATE_IDLE.
private class YourOnScrollListener extends RecyclerView.OnScrollListener {
private int scrollXDistance = 0;
private int scrollYDistance = 0;
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
Log.d(TAG, "X distance: " + scrollXDistance + " " + "Y distance:" + scrollYDistance);
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
scrollXDistance += dx;
scrollYDistance += dy;
}
}
Related
I have a horizontal RecyclerView and am attempting to programatically scroll by an x value.
This has so far been achieved with smoothScrollBy(x, y), however, I can't for the life of me find a solution where I can set a scroll duration, e.g. 1000ms.
Any help would me much appreciated, thanks.
The code is as follows:
private void focus() {
View focusedRecyclerViewItem = getFocusedRecyclerViewItem();
TextView focusedTextView = getFocusedTextView(focusedRecyclerViewItem);
focusedTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 64);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mRecyclerView.clearOnScrollListeners();
countdown();
}
});
int x = (int) focusedRecyclerViewItem.getX() - mRecyclerView.getWidth() / 2;
mRecyclerView.smoothScrollBy(x, 0);
}
To clarify as the question was not initially clear - what I am looking for is a custom duration for the smoothScrollBy() method when it is called, not a duration before the smoothScrollBy() method is called.
I'm looking for best practices. I want to implement load more [progressbar] after every 10 items (Using RecyclerView).
In past, I did this by simply creating Loader class item and just added into the specific position in my List. Well, this time, I'm using PairList and it's impossible to add Loader class item (even tho I personally think, that's a pretty clean way to do it).
I found a few solutions on SO, which are almost the same: How to implement load more recyclerview in android
Is there any other way I could implement this load more progressbar after every 10th element (First load 10 items from API, then, when user reaches 10th item, we show progress bar [meanwhile we fetch the next 10 items], remove progress bar, add 10 items and so on).
Use this InfiniteScrollListener in your recycler scrollListener:
public abstract class InfiniteScrollListener extends RecyclerView.OnScrollListener {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager)recyclerView.getLayoutManager();
int visibleItemCount = linearLayoutManager.getChildCount();
int totalItemCount = linearLayoutManager.getItemCount();
int pastVisiblesItems = linearLayoutManager.findFirstVisibleItemPosition();
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loadMore();
}
}
}
protected abstract void loadMore();}
recyclerView Listener:
recyclerView.addOnScrollListener(new InfiniteScrollListener() {
#Override
protected void loadMore() {
boolean willLoad = //get your last api call data. if empty set false
int offset = recyclerView.getAdapter().getItemCount();
if(willLoad){
willLoad=false;
onCallApi(offset,10);
}
}
});
your api:
private void onCallApi(int offset,int limit){
//your api
}
I am implementing a Retrofit APi for getting data from the server and showing this in a RecyclerView using the Litho framework, and it's doing well. As all of us know when we have infinite data to show in recyclerview we have to implement the pagination pattern. And I know this, but I am confused how to implement this in the Litho framework. Litho the provides onScrollListener() method:
final Component component = Recycler.create(context)
.binder(recyclerBinder)
.onScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//
})
.build();
I don't know: how to use a customized EndlessRecyclerViewScrollListener for endless scrolling in Litho?
I have had success implementing the "infinite" scroll pattern leveraging the recyclerBinder within the onScrolled method of a OnScrollListener. A trivial example would be the following:
//Initialize the RecyclerBinder
recyclerBinder = new RecyclerBinder(c, new LinearLayoutInfo(getContext(), OrientationHelper.VERTICAL, false));
//Initialize a recycler component
Component component = Recycler.create(c)
.onScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// use the recyclerBinder to determine what items at what position are visible -
// (you could also use the findLastVisibleItemPosition() method depending on your implementation)
int firstVisibleItemPosition = recyclerBinder.findFirstVisibleItemPosition();
//check if it is within range relative to the current available items and is not loading (room to improve/modify logic pending use case)
if((recyclerBinder.getItemCount() - 5) <= firstVisibleItemPosition && !isLoading) {
//if so - use your service to get the next page
service.getNextPage();
}
}
})
.build();
Then in a call back method - you can insert your items starting at the item count
public void callback(List<T> results) {
int position = recyclerBinder.getItemCount();
for(T result: results) {
Component component = //assemble your component(s) ...
ComponentInfo.Builder info = ComponentInfo.create().component(component);
recyclerBinder.insertItemAt(position, info.build());
position++;
}
}
I have created a activity Webview content placed in Recyclerview.
I want to get the scroll Y position when I scroll webview.
I tried Webview.getScrollY(), Webview.getY(), RecyclerView.getScrollY(), RecyclerView.getY(),... but it do not work fine. I can't get current scroll Y.
Is there any suggest for get scroll Y of Webview or RecyclerView ?
Use a RecyclerView.OnScrollListener for the RecyclerView and a View.OnScrollChangeListener for the webview.
You'll have to keep track of the total scroll yourself, like this:
private int mTotalScrolled = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mTotalScrolled += dy;
}
});
...
}
private int getScrollForRecycler(){
return mTotalScrolled;
}
computeVerticalScrollOffset()is more convenient at this situation as #Pkmmte mentioned.
mTotalScrolled = recyclerView.computeVerticalScrollOffset();
Iphone App video link
How I can design and develop view which is posted in above video? This is basically the item expansion of recyclerview with animation. I have tried with onItemtouchlistener of recyclerview and also with some custom view with animation, but didn't get the accurate result.
Finally i came accross addonscrolllistener, this give me results but not accurate.
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if(newState == RecyclerView.FOCUS_UP) {
System.out.println("hello, ia m going up");
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0){
TextView tv = (TextView)recyclerView.findViewById(R.id.title);
//tv.setVisibility(View.VISIBLE);
if (tv.getVisibility()==View.VISIBLE){
System.out.println("yes");
}else {
slideToTop(tv);
}
}
}
});
private void slideToTop(View view){
TranslateAnimation animate = new TranslateAnimation(0,0,0,-view.getHeight());
animate.setDuration(1000);
animate.setFillAfter(false);
view.startAnimation(animate);
view.setVisibility(View.VISIBLE);
}
I think your question is too broad - however, here is some psuedocode:
onScrolled() {
View child = getSecondVisibleChild();
int distanceFromTop = child.getTop();
int distanceAtWhichExpandingShouldOccur = 100;
if(distanceFromTop < distanceAtWhichExpandingShouldOccur ) {
child.setHeight(child.getOriginalHeight() + (distanceFromTop - distanceAtWhichExpandingShouldOccur))
}
}
So you'll notice, the second visible child is the one who's height changes. It changed when it's less than distanceAtWhichExpandingShouldOccur from the top of the window. Its height changes to ensure its bottom remains stationary - therefore its height is increasing at the same pace its top is moving.
Once it's no longer the second visible child (aka, its top is 0), it should be scrolled off as normal and the next child should have its height changed when its top is less than distanceAtWhichExpandingShouldOccur.
This library can be a study case for you: https://github.com/florent37/MaterialLeanBack