I have a ListView in which, as the question suggests, I am loading images with a delay. The problem is that this method is overriding my custom onScrollListener. I tried using:
aq.id(listview).scrolled(new customScrollListener());
aq.id(listview).adapter(myAdapter);
These two lines are in the calling activity class, and I do this after I have loaded all data in the list. Even after this the scrollListener doesn't seem to be working. Where am I going wrong? Any ideas?
UPDATE - CustomScrollListener:
private class CustomScrollListener implements OnScrollListener {
private Context context;
private int visibleThreshold = 0;
private int currentPage = 0;
private int previousTotal = 0;
private boolean loading = true;
CustomScrollListener(Context context) {
this.context = context;
}
CustomScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
currentPage++;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold) && totalItemCount>10) {
// do something
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
}
Your problem is that AndroidQuery souldDelay will override your own listener. Look at the docs:
The shouldDelay() method uses the setOnScrollListener() method and
will override any previously non-aquery assigned scroll listener. If a
scrolled listener is required, use the aquery method
scrolled(OnScrollListener listener) to register your listener instead.
source: aquery image loading
Related
I wanto to update my listVIew when I scroll down my list and I am on a last possition and scroll down I do this but it nor work good
mConnectionList.setOnScrollListener(new AbsListView.OnScrollListener() {
private int visibleThreshold = 5;
private int currentPage = 0;
private int previousTotal = 0;
private boolean loading = true;
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(totalItemCount == previousTotal && currentPage == totalItemCount){
getConnections();
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
});
A commonly used class which would accomplish this would be the PagedListAdapter class. It allows for the behavior you describe (which is called paging), but you would need to use a recyclerview.
See:
https://developer.android.com/reference/android/arch/paging/PagedListAdapter
I want my RecyclerView to show data in limits. for example if there is 1000 records in the database. i want to fetch only 50 and provide those to RecyclerView get display .but when the user scrolls down to 48th position i want to fetch 50 more records from data base and add those to the RecyclerView.
i have already created a simple RecyclerView which takes data from Drawable folder and that works just fine.
public class MyCustomAdapter extends RecyclerView.Adapter<MyCustomAdapter.MyViewHolder> {
Context context;
ArrayList<Information> data;
LayoutInflater inflater;
public MyCustomAdapter(Context context,ArrayList<Information> data){
this.context=context;
this.data=data;
inflater=LayoutInflater.from(context);
}
#Override
public MyCustomAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=inflater.inflate(R.layout.item_row,parent,false);
MyViewHolder holder=new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.text.setText(data.get(position).title);
holder.img.setImageResource(data.get(position).imgid);
}
#Override
public int getItemCount() {
return data.size();
}
//for getting refrences to img and txt row
public class MyViewHolder extends RecyclerView.ViewHolder{
ImageView img;
TextView text;
public MyViewHolder(View itemView) {
super(itemView);
img= (ImageView) itemView.findViewById(R.id.img_row);
text= (TextView) itemView.findViewById(R.id.txt_row);
}
}
}
you need to implement pagination in your list view.
You don't need to do much codding we have libraries to do this.
Please refer the link:- https://github.com/nicolasjafelle/PagingListView
You can use EndlessRecyclerView scroll lister to achieve this:
public class EndlessScrollRecyclListener extends RecyclerView.OnScrollListener
{
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;
private int startingPageIndex = 0;
private int currentPage = 0;
#Override
public void onScrolled(RecyclerView mRecyclerView, int dx, int dy)
{
super.onScrolled(mRecyclerView, dx, dy);
LinearLayoutManager mLayoutManager = (LinearLayoutManager) mRecyclerView
.getLayoutManager();
visibleItemCount = mRecyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
onScroll(firstVisibleItem, visibleItemCount, totalItemCount);
}
public void onScroll(int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount)
{
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0)
{
this.loading = true;
}
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount))
{
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem +
visibleThreshold))
{
onLoadMore(currentPage + 1, totalItemCount);
loading = true;
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount);
}
and then just
rvList.setOnScrollListener(new EndlessScroll...);
I'm trying to implement an endless scrolling to top where I would load more data when the user is getting close to the top of the listview (like in a messenger app). I have a scroll to bottom class which works fine, but I don't manage to find a library or modify this code to detect the scroll to top.
Could anybody help?
Here is the class :
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (totalItemCount - visibleItemCount)<=(firstVisibleItem + visibleThreshold)) {
onLoadMore(currentPage + 1, totalItemCount);
loading = true;
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount);
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}
I made some modification to your class, adding a parameter to decide the direction setScrollDirection by default it will be SCROLL_DIRECTION_DOWN please test it and let me know how it works :)
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
public final static int SCROLL_DIRECTION_UP = 0;
public final static int SCROLL_DIRECTION_DOWN = 1;
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
private int scrollDirection = SCROLL_DIRECTION_DOWN;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
Log.v("EndlessScroll", "firstVisibleItem: "+firstVisibleItem);
Log.v("EndlessScroll", "visibleItemCount: "+visibleItemCount);
Log.v("EndlessScroll", "totalItemCount: "+totalItemCount);
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading)
{
if( scrollDirection == SCROLL_DIRECTION_DOWN && (totalItemCount - visibleItemCount)<=(firstVisibleItem + visibleThreshold)) {
onLoadMore(currentPage + 1, totalItemCount);
loading = true;
}
else if( scrollDirection == SCROLL_DIRECTION_UP && firstVisibleItem<=visibleThreshold) {
onLoadMore(currentPage + 1, totalItemCount);
loading = true;
}
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount);
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
public int getScrollDirection() {
return scrollDirection;
}
public void setScrollDirection(int scrollDirection) {
if (scrollDirection == SCROLL_DIRECTION_DOWN || scrollDirection == SCROLL_DIRECTION_UP)
{ this.scrollDirection = scrollDirection; }
}
public boolean isLoading() {
return loading;
}
public void finishedLoading() {
this.loading = false;
}
}
The problem is based upon a specific use case, which is as follows:
1) Go the end of list and load more data until the API returns an empty list
2) After that call refresh() and the layout will refresh but the issue is that after I call refresh() the loadmore() doesn't gets called.
I have used SuperListView, I have used EndlessScrollListener with official SwipeToRefreshLayout, but nothing works.
I might be using the adapter in a wrong way I guess but below are the code snippets which I am using:
void showContent(){
contentListModel = ((ContentListModel) baseModel);
contentAdapter = ContentAdapter(getActivity(),R.layout.content_item,contentListModel.getContents());
mListView.setAdapter(contentAdapter);
}
void showRefreshContent(){
contentListModel = new ContentListModel();
contentAdapter.clear();
contentListModel = ((ContentListModel) baseModel);
contentAdapter.addAll(contentListModel.getContents());
mListView.setAdapter(contentAdapter);
}
void showLoadMoreContent(){
contentListModel = ((ContentListModel) baseModel);
contentAdapter.addAll(contentListModel.getContents());
contentAdapter.notifyDataSetChanged();
}
I could share the complete code but that might be irrelevant I guess, for backend I am using Spring + Android Annotations + [Observer + Facade] Design Patterns.
Thanks in advance.
EndlessScrollListener
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 8;
// The current offset index of data you have loaded
private int currentPage = 1;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
#Override
public void onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (totalItemCount - visibleItemCount)<=(firstVisibleItem + visibleThreshold)) {
onLoadMore(currentPage + 1, totalItemCount);
loading = true;
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount);
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}
You can Override listView methods, like in this snippet:
#Override
public void onScrollStateChanged(AbsListView absListView, int i)
{
}
#Override
public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount)
{
boolean loadMore = totalCount != totalLoadedCount && firstVisible + visibleCount >= totalCount;
if (loadMore)
{
totalLoadedCount = totalCount;
getContent(dto.loadedCount);
}
}
Where's in line totalCount != totalLoadedCount && firstVisible + visibleCount >= totalCount; you are detecting, if listView has been scrolled to the bottom, and getContent(dto.loadedCount); is method, that load new data to your list.
The full tutorial is here.
I have a onScrollListener that calls an AsyncTask once the last View in the ListView is shown. The AsyncTask adds Data to a ListView using an ArrayAdapter. The problem is when I clear the ArrayAdapter with arrayAdapter.clear() it clears the adapter but all the variables in AbsListView still think the Items exist so it doesn't detect when I am at the bottom of the ListView, Here is the onScrollListener.
class EndlessScrollListener implements OnScrollListener {
private int visibleThreshold = 5;
private boolean loading = true;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (firstVisibleItem + visibleItemCount) == totalItemCount) {
new loadComments().execute();
loading = true;
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
}
How Can I also reset the variables in AbsListView so it understand the when I have reached the bottom of the listView?
After calling clear() on your Adapter, you must call adapter.notifyDataSetChanged(). Here is the snippet from the API:
public void notifyDataSetChanged()
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.