dynamic listview adding "Load more items" at the end of scroll

AndroidListviewDynamic Loading

Android Problem Overview


I have a listview which is fetching data from sqlite database by Json.

I want to turn it into dynamic listview that at the end of scroll, a "load more items" appears in the footer of the list while loading more items and adding them to the adapter (for example 10 items each time). I have problem in implementing this feature. Please help me with it. Thanks.

public class AllProductsActivity extends Activity {

... defining variables...;

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);

	new LoadAllProducts().execute();

}

class LoadAllProducts extends AsyncTask<String, String, String> {

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		... progress dialog...
	}

	protected String doInBackground(String... args) {
		countryList = new ArrayList<Country>();
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		JSONObject json = jParser.makeHttpRequest(url_all_products, "GET", params);

		Log.d("All Products: ", json.toString());

		try {
			// Checking for SUCCESS TAG
			int success = json.getInt(TAG_SUCCESS);

			if (success == 1) {
				// products found
				// Getting Array of Products
				products = json.getJSONArray(TAG_PRODUCTS);

				// looping through All Products
				for (int i = 0; i < products.length(); i++) {
					JSONObject c = products.getJSONObject(i);

					// Storing each json item in variable
					String id = c.getString(TAG_PID);
					String name = c.getString(TAG_NAME);
					String description = c.getString(TAG_DESCRIPTION);
					String due_date = c.getString(TAG_DUE_DATE);
					String staff = c.getString(TAG_STAFF);
					String status = c.getString(TAG_STATUS);

					country = new Country(id,name,description,
							due_date, staff, status);
					countryList.add(country);
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}

		return null;
	}

	protected void onPostExecute(String file_url) {
		pDialog.dismiss();
		runOnUiThread(new Runnable() {
			public void run() {

				displayListView();

			}
		});
	}
}

private void displayListView() {
	dataAdapter = new MyCustomAdapter(this,
			R.layout.country_info, countryList);
	ListView listView = (ListView) findViewById(R.id.listView1);
	listView.setAdapter(dataAdapter);
}

private class MyCustomAdapter extends ArrayAdapter<Country> {

	... blah blah blah ...

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		ViewHolder holder = null;
		Log.v("ConvertView", String.valueOf(position));
		if (convertView == null) {
		... blah blah blah ...
		}

		return convertView;
	}
}
}

Android Solutions


Solution 1 - Android

you try the following code

list.setOnScrollListener(new OnScrollListener() {
		
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			
			
		}
		
		public void onScroll(AbsListView view, int firstVisibleItem,
				int visibleItemCount, int totalItemCount) {
			
			if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
			{
				if(flag_loading == false)
				{
					flag_loading = true;
					additems();
				}
			}
		}
	});

in the additem() add the next 10 items to array list and set the flag_loading as false. and call notifydatasetchanged. it should work.

Solution 2 - Android

There is the solution, Activity has to implement interface AbsListView.OnScrollListener

In Activity:

int currentFirstVisibleItem = 0;
int currentVisibleItemCount = 0;
int totalItemCount = 0;
int currentScrollState = 0;
boolean loadingMore = false;
Long startIndex = 0L;
Long offset = 10L;
View footerView;



@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    this.currentFirstVisibleItem = firstVisibleItem;
    this.currentVisibleItemCount = visibleItemCount;
    this.totalItemCount = totalItemCount;
}

@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
    this.currentScrollState = scrollState;
    this.isScrollCompleted();
}

private void isScrollCompleted() {
    if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE && this.totalItemCount == (currentFirstVisibleItem + currentVisibleItemCount)) {
        /*** In this way I detect if there's been a scroll which has completed ***/
        /*** do the work for load more date! ***/
        if (!loadingMore) {
            loadingMore = true;
            new LoadMoreItemsTask(this).execute();
        }
    }
}



private class LoadMoreItemsTask extends AsyncTask<Void, Void, List<ListItem>> {

    private Activity activity;
    private View footer;

    private LoadMoreItemsTask(Activity activity) {
        this.activity = activity;
        loadingMore = true;
        footer = activity.getLayoutInflater().inflate(R.layout.base_list_item_loading_footer, null);
    }

    @Override
    protected void onPreExecute() {
        list.addFooterView(footer);
        list.setAdapter(adapter);
        super.onPreExecute();
    }

    @Override
    protected List<ListItem> doInBackground(Void... voids) {
    
        return getNextItems(startIndex, offset);
    }

    @Override
    protected void onPostExecute(List<ListItem> listItems) {
        if (footer != null) {
               list.removeFooterView(footer);
        }
        list.setAdapter(adapter);

        loadingMore = false;
        if (listItems.size() > 0) {
            startIndex = startIndex + listItems.size();
            setItems(listItems);
        }
        super.onPostExecute(listItems);
    }

  
}

Oncreate:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.base_list);
    list = (ListView) findViewById(R.id.list);
    list.setOnItemClickListener(this);
    list.setOnScrollListener(this);


        footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.base_list_item_loading_footer, null, false);



    initAdapter();


    new LoadMoreItemsTask(this).execute();

}

base_list_item_loading_footer.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_item_footer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="15dp" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="horizontal" >

        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
        </ProgressBar>

        <TextView
            style="@style/ItemHeadTextStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/loading_list_items" />
    </LinearLayout>
</RelativeLayout> 

I hope , it helps.

Solution 3 - Android

Best way to implement Dynamic Expandaple LW with footer explained below:

private int firstVisibleItem, visibleItemCount,totalItemCount;

expandapleListView.setOnScrollListener(new AbsListView.OnScrollListener() {

            @Override
            public void onScroll(AbsListView view,
                                 int firstVisibleItemm, int visibleItemCountt,
                                 int totalItemCountt) {
                firstVisibleItem = firstVisibleItemm;
                visibleItemCount = visibleItemCountt;
                totalItemCount = totalItemCountt;


            }

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                final int lastItem = firstVisibleItem + visibleItemCount;
                if (lastItem == totalItemCount && scrollState == SCROLL_STATE_IDLE) {
                    expandapleInt++;

                    new AsyncTask().execute();
              
					//get next 10-20 items(your choice)items

                }
            }
        });

Footer implementation:

Given below xml code, should be in bottom of Layout that your ListView inside it...

 <RelativeLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_gravity="center"
android:id="@+id/footer">

<ProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_toLeftOf="@+id/textView3"
    android:layout_toStartOf="@+id/textView3">
</ProgressBar>

<TextView

    android:layout_width="wrap_content"
    android:layout_height="wrap_content"

    android:text="Loading"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:id="@+id/textView3" />

Bind it in your activity

footer = (RelativeLayout) findViewById(R.id.footer);
footer.setVisibility(View.GONE);

onPreExecute

footer.setVisibility(View.VISIBLE);

onPostExecute

footer.setVisibility(View.GONE);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNamikaze MinatoView Question on Stackoverflow
Solution 1 - Androidnull pointerView Answer on Stackoverflow
Solution 2 - AndroidRichard KeyView Answer on Stackoverflow
Solution 3 - AndroidUcdemirView Answer on Stackoverflow