Nếu các bạn dùng ứng dụng Gmail, Android Market thì sẽ thấy trong các listview ở dưới cùng đều có hiện một cái loading animation sẽ load thêm dữ liệu khi mình scroll xuống tới cái loading đó. Hôm nay mình sẽ demo cách để làm việc này, khá đơn giản thôi.
Các bạn có sẵn code của list14 trong ApiDemos rồi, copy cái adapter đó ra dùng cho tiện nhé. Trong cái adapter đó, các bạn thêm giúp một hàm appendItems() để có thể nối thêm dữ liệu vào adapter hiện hành:
public void appendItems(ArrayListitems) { mItems.addAll(items);notifyDataSetChanged();}
Với ListView của mình, các bạn cần thêm vào một FooterView chính là cái hiển thị loading đó, lưu ý cơ bản là chỉ có thể thêm footer/header vào trong ListView trước khi setAdapter, xòn xóa thì lúc nào cũng được
LayoutInflater inflater = LayoutInflater.from(this);mLoadMoreFooter = inflater.inflate(R.layout.loading_footer_item, null);getListView().addFooterView(mLoadMoreFooter);
Rồi, giờ cần bắt sự kiện khi nào mình scroll list tới cuối và cái loading được hiện lên thì mình sẽ load thêm dữ liệu mới và add vào list, trong sự kiện onScroll() của ListView mình sẽ xử lý như sau:
@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// minus 1 here because the total list item count include the// loading footerif (view.getLastVisiblePosition() >= totalItemCount - 1)checkLoadMore();}
Rồi, cái hàm checkLoadMore đơn giản chỉ là kiểm tra xem lúc đó có đang load dữ liệu chưa, dĩ nhiên nếu đang load dữ liệu rồi thì mình ko load thêm làm gì nữa, còn nếu chưa thì mình bắt đầu load thêm dữ liệu, vậy thôi
private void checkLoadMore() {if (mLoading)return;/** if the loading footer is still there, then we will load more items*/if (getListView().getFooterViewsCount() != 0) {loadMoreItems();}}private void loadMoreItems() {mLoading = true;new Thread() {public void run() {try {// in this example, we just simply wait for 2 secondsThread.sleep(2000);Message msg = mMainhandler.obtainMessage(MSG_APPEND_MORE_ITEMS, generateList());mMainhandler.sendMessage(msg);} catch (InterruptedException e) {e.printStackTrace();}};}.start();}
Hàm loadMoreItems() thì vì đây là ví dụ nên mình chỉ cho làm mỗi việc là đợi 2 giây rồi tạo dữ liệu giả ra, coi như là đã lấy được dữ liệu từ server về rồi chẳng hạn. Hàm generateList() tạo ra một list với 15 String.
Vì mình load dữ liệu ở một thread riêng biệt, mà khi muốn cập nhật trên giao diện (chụ thể ở đây là ListView) thì mình cần phải làm trong main thread, nên mình sẽ gửi một message tới handler của main thread để xử lý.
switch (msg.what) {case MSG_APPEND_MORE_ITEMS:ArrayListnewData = (ArrayList ) msg.obj; if (mAdapter == null) {mAdapter = new SimpleAdapter(LoadingListDemoActivity.this,newData);setListAdapter(mAdapter);} else {mAdapter.appendItems(newData);}// if the list we get from server is smaller than 15 (in this// example)// then that means there's nothing more to get, remove the// loading item nowif (newData.size() <>getListView().removeFooterView(mLoadMoreFooter);}mLoading = false;break;}
Đoạn code ở trên là: nếu như dữ liệu lấy về không đủ số lượng đã yêu cầu thì hiểu như là đã khôngcòn gì để load thêm nữa, vậy thì sẽ xóa cái loading ra khỏi list, vậy là xong :)
Đây là toàn bộ code của Activity:
package tvtbinh.bino.demo.loadingfooter;import java.util.ArrayList;import android.app.ListActivity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import android.widget.AbsListView.OnScrollListener;public class LoadingListDemoActivity extends ListActivity {private SimpleAdapter mAdapter;private View mLoadMoreFooter;private boolean mLoading;private static final int MSG_APPEND_MORE_ITEMS = 0;private static final int NUMBER_OF_ITEMS_REQUESTED = 15;/*** Use this field to count how many trunks that we have loaded if it's more* than 4 then we will not load anymore*/private int mTrunksCount = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// inflate the loading item and add to the ListView// we all know that the footers/headers must be addded before setting// the adapter for ListViewLayoutInflater inflater = LayoutInflater.from(this);mLoadMoreFooter = inflater.inflate(R.layout.loading_footer_item, null);getListView().addFooterView(mLoadMoreFooter);getListView().setOnScrollListener(mScrollListener);mLoading = false;mAdapter = new SimpleAdapter(LoadingListDemoActivity.this,new ArrayList()); setListAdapter(mAdapter);}/*** A mocking method for getting data from some source asynchronously*/private void loadMoreItems() {mLoading = true;new Thread() {public void run() {try {// in this example, we just simply wait for 2 secondsThread.sleep(2000);Message msg = mMainhandler.obtainMessage(MSG_APPEND_MORE_ITEMS, generateList());mMainhandler.sendMessage(msg);} catch (InterruptedException e) {e.printStackTrace();}};}.start();}/*** Generate an arrayList with 15 strings*/private ArrayListgenerateList() { ArrayListresults = new ArrayList (); mTrunksCount++;if (mTrunksCount <= 4) {for (int i = 0; i <>results.add(String.valueOf(System.currentTimeMillis()));}}return results;}private Handler mMainhandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case MSG_APPEND_MORE_ITEMS:ArrayListnewData = (ArrayList ) msg.obj; if (mAdapter == null) {mAdapter = new SimpleAdapter(LoadingListDemoActivity.this,newData);setListAdapter(mAdapter);} else {mAdapter.appendItems(newData);}// if the list we get from server is smaller than 15 (in this// example)// then that means there's nothing more to get, remove the// loading item nowif (newData.size() <>getListView().removeFooterView(mLoadMoreFooter);}mLoading = false;break;}};};/*** Check if should load more item at this time*/private void checkLoadMore() {if (mLoading)return;/** if the loading footer is still there, then we will load more items*/if (getListView().getFooterViewsCount() != 0) {loadMoreItems();}}private OnScrollListener mScrollListener = new OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {// We have nothing to do with this right now}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// minus 1 here because the total list item count include the// loading footerif (view.getLastVisiblePosition() >= totalItemCount - 1)checkLoadMore();}};private static class SimpleAdapter extends BaseAdapter {private ArrayListmItems; private LayoutInflater mInflater;private Bitmap mIcon1;private Bitmap mIcon2;public SimpleAdapter(Context context, ArrayListitems) { mItems = new ArrayList(items); mInflater = LayoutInflater.from(context);// Icons bound to the rows.mIcon1 = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon48x48_1);mIcon2 = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon48x48_2);}public void appendItems(ArrayListitems) { mItems.addAll(items);notifyDataSetChanged();}@Overridepublic int getCount() {if (mItems == null) {return 0;}return mItems.size();}@Overridepublic Object getItem(int position) {return mItems.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = mInflater.inflate(R.layout.list_item_icon_text,null);holder = new ViewHolder();holder.text = (TextView) convertView.findViewById(R.id.text);holder.icon = (ImageView) convertView.findViewById(R.id.icon);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.text.setText(mItems.get(position));holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);return convertView;}static class ViewHolder {TextView text;ImageView icon;}}}
hay quá, đúng là thứ mình đang tìm, cám ơn bạn
Trả lờiXóaHuyDo
Cảm ơn anh :)
Trả lờiXóaTam Vo
Thanks Ban
Trả lờiXóacho mình xin code được không bạn
Trả lờiXóathere are some things wrong..
Trả lờiXóa