概要
Android Marketみたく、ListViewの最後尾に来たらクルクル出して要素追加したいなーと思ったのでやってみました。
内容的には、文字のリストを10個表示し、最後尾までスクロールすると10個さらに追加していく感じです。
ファイル構成
ファイル構成としては以下の様な感じです。
・src
jp.dip.sys1.android.listview_additional_reading.ListViewAdditionalReading.java
・res
layout
listview_footer.xml
main.xml
他は普通のAndroidプロジェクトと同じです。
ListView最後尾のクルクルはListView#addFooterView(View)で。
ListViewにはaddFooterView(View)なるメソッドがあり、そこに任意のViewを突っ込むと、
ListViewの要素の最後尾に常に表示されるViewを設定する事が出来ます。
という事で、クルクルするViewをListViewにまず突っ込みます。
■listview_footer.xml
単純にProgressBarを真ん中に表示するだけのViewです。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent" android:layout_height="fill_parent"android:textAppearance="?android:attr/textAppearanceLarge"android:minHeight="?android:attr/listPreferredItemHeight"android:gravity="center"><ProgressBar android:id="@android:id/text1"android:layout_width="wrap_content" android:layout_height="wrap_content"android:gravity="center_vertical" /></LinearLayout>■ListViewAdditionalReading#onCreate(Bundle)
onCreateの中でListViewのaddFooterViewしときます。多分タイミングはいつでもいいです。多分。
@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);ListView listView = getListView();listView.addFooterView(getFooter());listView.setAdapter(getAdapter());listView.setOnScrollListener(this);}■ListViewAdditionalReading#getFooter()
getFooter()の中でlistview_footerをinflateしてます。
private View getFooter() {if (mFooter == null) {mFooter = getLayoutInflater().inflate(R.layout.listview_footer,null);}return mFooter;}ListView最後尾までスクロールしたよね判定はOnScrollListenerで。
フッタは勝手に出るので良いとして、あとは最後尾までスクロールしたという判定が必要です。
そこでandroid.widget.AbsListView.OnScrollListenerを利用しました。
■OnScrollListener#onScroll(AbsListView, int, int, int)
onScrollにはスクロールしているListViewと、表示されている要素の先頭インデックス、要素の表示数、要素の総数が渡ってきます。
「表示されている要素の先頭インデックス」と「要素の表示数」を足した値が「要素の総数」となる時、
ListViewの最後尾まで来た、と判定できそうです。赤字の所で判定を行い、追加読み込みの処理を呼び出すようにしました。
@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if (totalItemCount == firstVisibleItem + visibleItemCount) {additionalReading();}}追加読み込みしたらListView#invalidateViews()で再描画。
■ListViewAdditionalReading#additionalReading
ListViewに要素を追加させる処理です。
AsyncTaskを使っていますが、doInBackgroundでランダムでsleepさせてるだけです。通信処理等が必要な場合はdoInBackground()でメインの処理を行うといいでしょう。
onPostExecute()でListViewの要素追加、そしてListView#invalidateViews()を呼び出しています。
ListViewはデータを表示させる為にAdapterをsetします。AdapterはデータのListを持っています。
要素を追加する場合はListにデータ追加してListView#invalidateViews()を呼び出してあげます。すると表示に反映されます。
private void additionalReading() {// 読み込み回数が最大値以上ならスキップ。フッタを消すif (mCount >= MAX_COUNT) {invisibleFooter();return;}// 既に読み込み中ならスキップif (mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING) {return;}mTask = new AsyncTask<Long, Void, Void>() {@Overrideprotected Void doInBackground(Long[] params) {try {Log.d(TAG, "sleep..." + params[0]);Thread.sleep(params[0]);} catch (Exception e) {e.printStackTrace();}return null;};protected void onPostExecute(Void result) {addListData();getListView().invalidateViews();};}.execute(Math.abs(new Random(System.currentTimeMillis()).nextLong() % 3000));}■ListViewAdditionalReading#invisibleFooter()
追加読み込み回数がMAXになるとフッタを消してます。
private void invisibleFooter() {getListView().removeFooterView(getFooter());}こんな感じになります。
詳細はプロジェクトのソースを参照して下さい。
サンプルプロジェクトは下記リンクのListViewAdditionalReading.zipです。

お世話になります。
返信削除配列を以下のように変更すると
{ "A", "B", "C", "D", "E", "F","G", "H", "I", "J" };
→{ "A" };
A0-A4までリスト表示され、footerが表示されたまま入力も受け付けなくなりました。
いろいろ試したのですが解決できませんでした。
footerを消すにはどうしたら良いのでしょうか?
リストの個数が少ないとスクロールが起きない→onScrollも起きないと思われるので、最初に表示したときにFooterが表示されているかの判定処理も必要かと思います。
返信削除やりたいことにドンピシャでとても役に立ちました。ありがとうございました。
返信削除参考にさせて頂きます!ありがとうございます!
返信削除