On scroll change using list-view Android - android

I am developing an application which consists on scroll-change-listener,Here is my problem, I am getting the Number of items for the server.Until here every thing works fine to me.
1.IF i am showing the 10 values in the list-view,that 10 values only should stream.
2.When Scroll state is changed the reaming item should hit server.
3.Below is my code .
#Override
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
if (visibleItemCount < 1)
return;
streaming.clear();
int firstPoisitionValue = symbolList.getFirstVisiblePosition();
int lastPositionValue = symbolList.getLastVisiblePosition();
WatchListData row;
String symbol;
for (int i = firstPoisitionValue; i <= lastPositionValue; i++) {
row = model.get(i);
symbol=row.getSymbol();
Log.w("Hello Android", "Symbol Value ::>"+symbol);
streaming.add(symbol);
}
if (streamFlag) {
System.out.println("calling the request");
streamingRequest("quote", streamingSymbols);
streamFlag = false;
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
pauseStreaming();
if(scrollState == SCROLL_STATE_IDLE){
streamingRequest("quote", streamingSymbols);
}
Thanks,
Nikhilreddy.

You can do this by using onScroll Listener. Using this listener When scroll reaches the end you can load new items to the list. refer this link. It may help you.Dynamic listView

Related

listview - access to non-visible items

I would like to check which of elements on my listview is also a member of another list and check all of them (by changing background). But the only way I can think of is:
for (String str : list1){
if (list2.contains(str)) {
lv.getChildAt(adapter.getPosition(str)).setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
}
}
But that works only for visible elements of the list and throws null pointer exception when accessing non-visible elements. What can I do to apply changes for all list items? Do I have to write my own adapter or maybe there is any "equivalent" of getChiledAt but working for all elements of the listview not only visible ones?
I didn't try by myself, but a suggestion. Can you please try this way, and check.
Idea is to use setOnScrollListener with onScroll method and to have null check inside for loop.
It's not good solution though, because for loop working on every scroll.
lv.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
for (String str : list1) {
if (list2.contains(str)) {
if (lv.getChildAt(adapter.getPosition(str)) != null) {
lv.getChildAt(adapter.getPosition(str))
.setBackgroundColor(
getResources()
.getColor(
android.R.color.darker_gray));
}
}
}
}
});
The solution was to use onScroll method (as Chitrang suggested) and set everything only for visible item. Android Magic works, everything works fine, also for non-visible items :)
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
for (int i = lv.getFirstVisiblePosition(); i<=lv.getLastVisiblePosition(); i++){
if (list2.contains(lv.getItemAtPosition(i).toString()))
lv.getChildAt(i - lv.getFirstVisiblePosition()).setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
}
}
}
You can create a new List, with the (i assume you have) id like the listview's data.
Example :
You have class Person with int id, String name. Create a new List<Integer> to store all (not just the visible one) of your listview's person id, normally by using the listview's adapter.

Drag-drop not working in nhaarman's ListviewAnimation library

I am using nhaarman's ListviewAnimation library https://github.com/nhaarman/ListViewAnimations which works great.
But I am facing following issues:
The main problem I am facing is, I am not able to debug my code. I have directly copy/pasted the four required libraries into libs folder. Placing a debug point inside any of the listview methods like onItemLongClick() does not work.
The second problem is, drag-drop listView is not working in my code. Whenever I try to drag any list item, on dropping the list item, the item takes the same position from which it was dragged.
Here's the code I have used:
listview.enableDragAndDrop();
listview.setDraggableManager(new TouchViewDraggableManager(
R.id.list_row_draganddrop_textview));
listview.setOnItemMovedListener(this);
listview.setOnItemLongClickListener(this);
#Override
public void onItemMoved(final int originalPosition, final int newPosition) {
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(getApplicationContext(), "Moved"
+ swingBottomInAnimationAdapter.getItem(newPosition)
+ newPosition, Toast.LENGTH_SHORT);
mToast.show();
}
#Override
public boolean onItemLongClick(final AdapterView<?> parent,
final View view, final int position, final long id) {
if (listview != null) {
listview.startDragging(position - listview.getHeaderViewsCount());
}
return true;
}
Whenever I try to drag any list item, on dropping the list item, the item takes the same position from which it was dragged.
Of course. Handling the change in position is your responsibility, and you should take care of it inside the onItemMoved callback:
#Override
public void onItemMoved(final int originalPosition, final int newPosition) {
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(getApplicationContext(), "Moved"
+ swingBottomInAnimationAdapter.getItem(newPosition)
+ newPosition, Toast.LENGTH_SHORT);
mToast.show();
// Adapt the following to your implementation
if (originalPosition != newPosition) {
YourObject item = (YourObject) yourAdapter.getItem(originalPosition);
yourAdapter.moveItem(item, newPosition);
}
}
The method mentioned above would look something like:
public void moveItem(YourObject item, int newIndex) {
if (mEntries != null) {
mEntries.remove(item);
mEntries.add(newIndex, item);
notifyDataSetChanged();
}
}
If you go through the source code, you'll see that what you are dragging around is a Bitmap. The list item is sitting at its original position.
For others having the same problem - Niek Haarman has answered this question on GitHub here.
Don't see GitHub going down soon, but as it is good tone to paste the answer too, here it is:
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() {
return true;
}
position is not a stable id here. You need a stable id for the item
which does not depend on the position.
use
import com.nhaarman.listviewanimations.ArrayAdapter;
instead of
import android.widget.ArrayAdapter;
that is the reason it doesn't calling onItemMoved

Scroll a ListView to the top without any screen flickering

I have implemented a ListView that has the functionality that you see in many apps, where user scrolls to bottom and it loads more, that OnScrollListener is this:
public class OnScrolledToEndListener implements AbsListView.OnScrollListener
{
private int prevLast;
#Override
public void onScrollStateChanged(AbsListView absListView, int i)
{
}
#Override
public void onScroll(AbsListView absListView, int first, int visible, int total)
{
int last = first + visible;
if (last == total)
{
if (prevLast != last)
{
prevLast = last;
onScrolledToEnd();
}
}
}
public void onScrolledToEnd()
{
}
}
Now the problem is that when a user has scrolled to the bottom of a list, and hits the refresh button in my app, I want it to start over at the top of the list, because if it stays at the bottom of the list, then the scroll listener will immediately trigger. The best way I've found to solve this is by doing the following before executing the refresh:
mListView.setSelection(0);
mListView.post(
new Runnable()
{
#Override
public void run()
{
mListView.setVisibility(View.GONE);
mLoadingLayout.setVisibility(View.VISIBLE); //this is basically a progressbar
// do the refresh
}
}
);
But there is a slight flicker when the list scrolls to the top. Any ideas on how to make it look better?
I figured out the solution. Apparently setting the ListView to View.GONE makes it not update its layout, so I set it to View.INVISIBLE instead and it worked. I didn't even have to use a Runnable.
mListView.setSelection(0);
mListView.setVisibility(View.INVISIBLE);
mLoadingLayout.setVisibility(View.VISIBLE);

Android: infinite ListView loading items at wrong time

I'm trying to implement an infinite ListView, it has 10 elements loaded first, when I scroll to the bottom of these 10 elements, it should load another 10. This is the code I've written till now:
private class ResultListScrollListener implements OnScrollListener{
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (mResultListView.getLastVisiblePosition() >= mResultListView.getCount()-1 && mResultListView.getLastVisiblePosition()<count-1) {
page_num++;
//count is final variable=60 so that scrolling stops at 60.
Log.i("onScrollStateChanged", "last visible: "+ mResultListView.getLastVisiblePosition() + " Page num: " + page_num);
new LoadItemsAsyncTask().execute();
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
}
It does load more elements, but it loads at wrong time, instead of loading when last visible position is 9, 19, 29 .... etc , it loads erratically, like twice at 9, then skips 19 then thrice at 29. How can I fix this? Here is my LogCat output so you can see when the onScrollStateChanged has been called:
07-09 12:16:06.197: I/onScrollStateChanged(27014): last visible: 9 Page num: 1
07-09 12:16:06.648: I/onScrollStateChanged(27014): last visible: 9 Page num: 2
07-09 12:16:11.122: D/dalvikvm(27014): GC_CONCURRENT freed 1069K, 26% free 3477K/4643K, paused 11ms+4ms
07-09 12:16:24.946: I/onScrollStateChanged(27014): last visible: 29 Page num: 3
07-09 12:16:25.376: I/onScrollStateChanged(27014): last visible: 29 Page num: 4
07-09 12:16:26.527: I/onScrollStateChanged(27014): last visible: 29 Page num: 5
EDIT
I got it to behave properly by keeping a track of the previous last visible position and loading items only if the previous is NOT equal to the current. So now I have
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (mResultListView.getLastVisiblePosition() >= mResultListView.getCount()-1 && mResultListView.getLastVisiblePosition()<count-1
&& mResultListView.getLastVisiblePosition()!=last_visible) { //added this condition
page_num++;
Log.i("onScrollStateChanged", "last visible: "+ mResultListView.getLastVisiblePosition() + " Page num: " + page_num);
last_visible=mResultListView.getLastVisiblePosition();
new LoadItemsAsyncTask().execute();
}
}
}
Now I get proper output like:
07-09 12:33:26.152: I/onScrollStateChanged(27734): last visible: 9 Page num: 1
07-09 12:33:29.735: D/dalvikvm(27734): GC_CONCURRENT freed 1092K, 26% free 3455K/4643K, paused 10ms+7ms
07-09 12:33:33.969: I/onScrollStateChanged(27734): last visible: 19 Page num: 2
07-09 12:33:43.409: I/onScrollStateChanged(27734): last visible: 29 Page num: 3
07-09 12:33:49.014: I/onScrollStateChanged(27734): last visible: 39 Page num: 4
07-09 12:33:53.979: I/onScrollStateChanged(27734): last visible: 49 Page num: 5
But I am unable to understand why it did not work without the dit. Any explanations?
If u want an easy solution go with chris banes pull to refresh libraries
1.> https://github.com/chrisbanes/Android-PullToRefresh
2.> https://github.com/chrisbanes/ActionBar-PullToRefresh
All the listviews in this library have an onLastItemVisibleListener where you can put your code
You can also check wether the list is already refreshing by isRefreshing() to stop the list from loading again.
Here is my implementation which works enough well
list.setOnScrollListener(new AbsListView.OnScrollListener() {
// is the number of list items (counted from the end) that should, if visible, trigger the loading process.
// If you set threshold to 0, for instance, the user has to scroll to the very end of the list in order to load more items.
int treshhold = 0;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if(isLastPageEmpty){
return;
}
if (list.getLastVisiblePosition() >= list.getCount() - 1 - treshhold) {
page++;
if(itemsArray != null) {
lastVisibleListPosition = itemsArray.size();
}
GetItemsAsync async = new GetItemsAsync();
async.execute();
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
private class GetItemsAsync extends AsyncTask<Void, Void, Result> {
#Override
protected Result doInBackground(Void... params) {
// send request for new items
}
#Override
protected void onPostExecute(Result result) {
super.onPostExecute(result);
try {
if (result.status.equalsIgnoreCase("fail")) {
// show error
} else {
if(result.items.size() == 0){
// no more items
isLastPageEmpty = true;
return;
}
if (itemsArray == null) {
itemsArray = result.items;
} else {
itemsArray.addAll(result.items);
}
adapter = new ListAdapter(getActivity(), itemsArray);
list.setAdapter(adapter);
// scroll list to previous position
if(lastVisibleListPosition > 0){
list.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
list.setSelection(lastVisibleListPosition - 1); list.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Check data when Scroll with the OnScrollListener in ListView (android)

My ListView (two TextView, one Icon) have more than 4000 rows and It scroll very slowly.
The problem is For{} statement with Cursor make my program worse.
I want to get the First Character(from one of two TextView) to display when User Scroll. So, any solutions to archive this and make my program better.
My function like this:
public void onScroll(AbsListView view, int firstVisibleItem, int VisibleItemCount, int totalItemCount){
//int lastItem = firstVisibleItem + VisibleItemCount - 1;
Cursor cursor = mDbHelper.loadTitleRaw();
startManagingCursor(cursor);
ArrayList<String> myArrayList = new ArrayList<String>();
for(cursor.moveToFirst(); cursor.moveToNext(); cursor.isAfterLast()) {
String mTitleRaw = cursor.getString(cursor.getColumnIndex(SBooksDbAdapter.KEY_TITLE_RAW));
myArrayList.add(mTitleRaw);
}
String[] mString = myArrayList.toArray(new String[myArrayList.size()]);
if(mReady){
char firstLetter = mString[firstVisibleItem].charAt(0);
if(!mShowing && firstLetter != mPrevLetter){
mShowing = true;
mDialogText.setVisibility(View.VISIBLE);
}
mDialogText.setText(((Character)firstLetter).toString());
mHandler.removeCallbacks(mRemoveWindow);
mHandler.postDelayed(mRemoveWindow, 3000);
mPrevLetter = firstLetter;
}
}
You are almost certainly doing this wrong. You don't want to instantiate a new Cursor on every scroll, you want to create it once, then reuse it. This is usually done in the onCreate() method. You could also get rid of that whole ArrayList / Array mess.
What's happening the way you're doing it is that every time you scroll AT ALL it's querying the database for all the records. Then it's copying all those values into an ArrayList, then it's copying all the values into an array. You're taking one object (with a bunch of data) then turning it into a bunch of objects which each have very little data. Other than being unnecessarily repetitious, this is probably killing you on garbage collection, not to mention running the query over and over. You really only want one copy of the data floating around and you want to make as few queries as possible.
Something like this should help out a lot:
public class MyActivity extends Activity {
private Cursor cursor;
public void onCreate(Bundle savedInstanceState) {
// all the other stuff you're already doing.
cursor = mDbHelper.loadTitleRaw();
startManagingCursor(cursor);
}
public void onScroll(AbsListView view, int firstVisibleItem, int VisibleItemCount, int totalItemCount) {
if(mReady){
cursor.moveToPosition(firstVisibleItem);
char firstLetter = cursor.getString(cursor.getColumnIndex(SBooksDbAdapter.KEY_TITLE_RAW)).charAt(0);
if(!mShowing && firstLetter != mPrevLetter){
mShowing = true;
mDialogText.setVisibility(View.VISIBLE);
}
mDialogText.setText(((Character)firstLetter).toString());
mHandler.removeCallbacks(mRemoveWindow);
mHandler.postDelayed(mRemoveWindow, 3000);
mPrevLetter = firstLetter;
}
}
}
Bonus points... if the ListView is being populated from a Cursor in the first place (which seems an almost certainty in this case) you might just be able to reuse the same Cursor instead of having 2 floating around.

Categories

Resources