Reputation: 1879
I have a ListView, first its scrolled down, now when we scroll up,it reach top most point. I want to detect that .Is there any way?I am developing application with api level 8.Pls help..
Upvotes: 29
Views: 21977
Reputation: 2651
Too late but try this one it works well in RecyclerView. -1 to check if it can scroll to top while 1 is to check if it can scroll to bottom
if (listView.canScrollVertically(-1))
listView.smoothScrollToPosition(0);
else
onBackPressed();
Upvotes: 0
Reputation: 2887
My friends, combining Graeme's answer with the onScroll method...
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(firstVisibleItem == 0 && listIsAtTop()){
swipeRefreshLayout.setEnabled(true);
}else{
swipeRefreshLayout.setEnabled(false);
}
}
});
private boolean listIsAtTop() {
if(listView.getChildCount() == 0) return true;
return listView.getChildAt(0).getTop() == 0;
}
Upvotes: 13
Reputation: 1059
This question is old but I have a solution that works perfectly and it is possible that works for someone looking for a solution.
int limitRowsBDshow = 10; //size limit your list
listViewMessages.setOnScrollListener(new AbsListView.OnScrollListener() {
int counter = 1;
int currentScrollState;
int currentFirstVisibleItem;
int currentVisibleItemCount;
int currentTotalItemCount;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
this.currentScrollState = scrollState;
this.isScrollCompleted();
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
this.currentFirstVisibleItem = firstVisibleItem;
this.currentVisibleItemCount = visibleItemCount;
this.currentTotalItemCount = totalItemCount;
}
private void isScrollCompleted() {
if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE) {
/*** detect if there's been a scroll which has completed ***/
counter++;
if (currentFirstVisibleItem == 0 && currentTotalItemCount > limitRowsBDshow - 1) {
linearLay20msgMas.setVisibility(View.VISIBLE);
}
}
}
});
This code is found a time ago (here StackOverflow). But I can not find this to mention
Upvotes: 1
Reputation: 25864
edit
See comments below as to why, especially on different API versions (esp later ones), this isn't a foolproof way to see if you're list is at the top (padding etc). However, it does give you a start for a solution on devices below API 14:
private boolean listIsAtTop() {
if(listView.getChildCount() == 0) return true;
return listView.getChildAt(0).getTop() == 0;
}
As far as my implementation years ago - this worked perfectly at the time.
Upvotes: 41
Reputation: 682
If you can extends ListView directly, then you can use the protected method called "computeVerticalScrollOffset()" inside the override method "onScrollChanged()".
With that protected method return 0, means that your ListView is now reached at top.
Code Snippet
listView = new ListView(this){
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if( computeVerticalScrollOffset() == 0 ){
// Reach top
}
}
Upvotes: 0
Reputation: 508
I know this question is old, but it shows up top in Google search results. There is a new method introduced in API level 14 that gives exactly what we needed:
http://developer.android.com/reference/android/view/View.html#canScrollVertically%28int%29
For older platforms one can use similar static methods of See edit below.ViewCompat
in the v4 support library.
Unlike Graeme's method, this method is immune of problems caused by the internal view reuse of ListView
and/or header offset.
Edit: final solution
I've found a method in the source code of SwipeRefreshLayout that handles this. It can be rewritten as:
public boolean canScrollUp(View view) {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (view instanceof AbsListView) {
final AbsListView absListView = (AbsListView) view;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView
.getChildAt(0).getTop() < absListView.getPaddingTop());
} else {
return view.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(view, -1);
}
}
You may need to add custom logic if the passed-in view is a custom view.
Upvotes: 21
Reputation: 552
Graeme's answer is close but is missing something that user2036198 added, a check for getFirstVisiblePosition(). getChildAt(0) doesn't return the very first view for the very first item in the list. AbsListView implementations don't make a single view for every position and keep them all in memory. Instead, view recycling takes effect to limit the number of views instantiated at any one time.
The fix is pretty simple:
public boolean canScrollVertically(AbsListView view) {
boolean canScroll = false;
if (view != null && view.getChildCount() > 0) {
// First item can be partially visible, top must be 0 for the item
canScroll = view.getFirstVisiblePosition() != 0 || view.getChildAt(0).getTop() != 0;
}
return canScroll;
}
For best results on ICS or higher, always use ViewCompat from the v4 support library or View.canScrollVertically(). Use the above method on lower API levels as ViewCompat always returns false for canScrollVertically() and canScrollHorizontally() below ICS.
Upvotes: 0
Reputation: 21
You will need to check what is the first visible position then applying Graeme's solution to see if the first visible listview item is at the top position.
Something like lv.getFirstVisiblePosition() == 0 && (lv.getChildCount() == 0 || lv.getChildAt(0).getTop() == 0)
Upvotes: 2
Reputation: 613
lstView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//To change body of implemented methods use File | Settings | File Templates.
if (0 == firstVisibleItem){
Toast.makeText(MyActivity.this, "Scroll to Top ", Toast.LENGTH_SHORT).show();
}
}
});
Upvotes: -1
Reputation: 1624
You can use an OnScrollListener to be notified the position 0 is now visible. Use the onScroll
method.
Upvotes: 1