I have my own Adapter extended from a BaseAdapter. I need to know when the latest element from the Adapter is shown on user's screen when user scrolls to it. Please advice.
You could override the onDraw() method in the element's view. When onDraw() is called, you know that the element is on the screen. Design wise, you could have an observer in each element's view. The adapter will register itself (or a different client) as an observer to the last/latest element's view. When the view is drawn, it will notify the observer.
Try this...
adapter.notifyDataSetChanged();
It will Refresh your adapter, notifies if any change..
Check the code below:
listView.setOnScrollListener(new OnScrollListener() {
// ...
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
boolean isLastRowShown = view.getLastVisiblePosition() == (view.getAdapter().getCount() - 1);
}
});
Related
I have a custom cursor adapter to populate a list view in my fragment.
I want to set the visibility of certain elements within the list view items, depending on whether the item is the first visible one in the list or not. Is it possible to get that info in the bindView() method of the Cursor adapter?
Adapter's purpose plan:
Create views
Attaching data to them
Return the view for the ListView to use.
Conclusion: Adapter doesn't know where the view it's creating will be shown.
However, the ListView does know about this and it's probably the only way you can get this working.
Example code to get you started:
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
int previousFirst = -1;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (previousFirst != firstVisibleItem) {
previousFirst = firstVisibleItem;
TextView textView = (TextView) view.findViewById(R.id.title);
if (textView != null) textView.setText("First: " + firstVisibleItem);
}
}
});
Problems with this code:
Once the first item changes, you need to set it's text back to the previous one.
Same goes with the view hierarchy. If you change how this view looks, after it's not the first one anymore you need to change it back.
ListView doesn't scroll upon creation. So the first item will not have the text changed until you scroll manually.
ListView doesn't include the options to customize the first visible item internally, that's why you have to use all these dirty hacks. However, it is possible :). I leave you to overcome these problems yourself.
Good luck!
This is for example as I haven't coded it yet, since I don't know how to start.
Let's say in Android I have String array with 100 values:
String[] myString = new String[100];
for (int number = 0; number < 100; number++) {
myString[number] = "image " + number;
}
Which way should I display for example 5 values per page (which view to use (table, grid) and should I use Fragment replace for each page).
I would like to achieve something like this, but in Android. I just need some guidelines to start.
In general if you have noticed, explicit pagination is not so often done in android, instead, infinite scrolling is used, for example your news feed in Facebook is a list, when you reach the bottom, it loads more and you can scroll more, at the bottom of that it loads again.
To implement this, it is quite easy, just set an onScrollListener and override onScrollStateChanged() method.
Set onScrollListener after initializing your ListView:
//In onCreate()
ListView listView = (ListView)findViewById(R.id.list_view);
listView.setOnScrollListener(new ListScrollListener());
Make your listener class:
private class ListScrollListener implements OnScrollListener{
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (listView.getLastVisiblePosition() >= listView.getCount()-1) {
page_num++;
//TODO Load more list items.
//notify the adapter of the listview that data has changed
mAdapter.notifyDataSetChanged();
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//This can be left blank
}
}
If you want you can add a footer with a ProgressBar to your ListView to display when you are loading more items with listView.addFooterView(View v);
You can find a nice tutorial about a custom ListView at Vogella tutorials.
I know that ListView creates only the needed view items and others are dynamically created as we scroll and the functions handling this are newView and bindView.but I can't find the function that disposes the items that go out of the view.
I use a custom CursorAdapter for my ListView.
I need that to create an ArrayList to keep the items that are currently on the view. How can I do this or does the ListView have such functionality?
If you want to know which items are currently visible in your ListView you can set an onScrollListener to the ListView.
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});
In onScroll you can get the first and last visible position (firstVisibleItem + visibleItemCount) and thus get the items from your underlying ArrayList that are currently visible.
I have a listView which has its content as random generated numbers. If one item in the listView is scrolled out of the screen and then scrolled back in, the random generated number is changed (it generates a new number).
Is there any way I can prevent this from happening?
A example code is here
This is because every time your item goes off the screen and again come to front it calls getview() method. To solve this you can store all random generated numbers in an array in starting and use it to show the items.
OR
i think using view holder class (i didn't try).
Just try this code for listview implement listener and/or your getview() method calling every time on scroll up and/or down,
mListView.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// write down your code here
// i think notifyDataSetChanged() this method calling whatever u require.
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// write down your code here
}
}); // mListView.setOnScrollListener close
I am loading a listview from Http server, 20 at a time ,At the end of Listview I a want to load next 20 data from server and this process will continue till data ends in server ,I used class that extend BaseAdapter to populate first 20 data .what should i do??
This looks to be an elegant solution as well: http://benjii.me/2010/08/endless-scrolling-listview-in-android/
It also implements an AbsListView.OnScrollListener, and uses an AsyncTask to load more content as soon as a certain threshold of remaining items in the current scroll view is reached.
Ok i have seen that this is a common problem, so i have made a SMALL LIBRARY with custom load more and pull to refresh ListView in github, please check this at here, all is very explained in the repository.
You can implement an AbsListView.OnScrollListener, that gets informed and which allows you to load more data.
See e.g.
....
ListView.setOnScrollListener(this);
....
And then have a look at https://github.com/pilhuhn/ZwitscherA/blob/master/src/de/bsd/zwitscher/TweetListActivity.java#L287
Or take a look at the List9 example from the sdk examples.
Heiko Rupp's code is the best option for this problem.
The only thing you should do is implement onScrollListener and in onScroll()
just check if there is an end of list by using the code
boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount-1;
if true load your data with regular fashion..
thaks Heiko Rupp for this snippet :)
This is what I used to load more data at the end of the listview
listview.setOnScrollListener(new OnScrollListener(){
#Override
public void onScroll(AbsListView view,
int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
//Algorithm to check if the last item is visible or not
final int lastItem = firstVisibleItem + visibleItemCount;
if(lastItem == totalItemCount){
// you have reached end of list, load more data
}
}
#Override
public void onScrollStateChanged(AbsListView view,int scrollState) {
//blank, not using this
}
});
I had this issue when I was accidentally trying to update a view from a non-ui thread. Pushing the ui update code to the ui thread resolved my issue!
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
// insert ui update code here
}
}
});