android-ibc-forum

Unnamed repository; edit this file 'description' to name the repository.
git clone http://git.code.weiherhei.de/android-ibc-forum.git
Log | Files | Refs

EndlessListActivity.java (6808B)


      1 /**
      2  * 
      3  */
      4 package de.mtbnews.android;
      5 
      6 import java.util.ArrayList;
      7 import java.util.List;
      8 
      9 import android.app.ListActivity;
     10 import android.content.SharedPreferences;
     11 import android.preference.PreferenceManager;
     12 import android.widget.AbsListView;
     13 import android.widget.BaseAdapter;
     14 import android.widget.ListView;
     15 import android.widget.AbsListView.OnScrollListener;
     16 
     17 /**
     18  * Erweitert die Oberklasse {@link ListActivity} für "endlose" Listen, die
     19  * seitenweise vom Server geladen werden. Bei Erreichen des Endes wird
     20  * automatisch der nächste Bereich nachgeladen.
     21  * 
     22  * @author dankert
     23  * 
     24  */
     25 public abstract class EndlessListActivity<T> extends ListActivity
     26 {
     27 	/**
     28 	 * boolean-Parameter der ansagt, dass die Anzeige mit dem letzten Element
     29 	 * beginnen soll.
     30 	 */
     31 	public static final String LAST_POST = "last_post";
     32 
     33 	/**
     34 	 * boolean-Parameter der ansagt, dass die Anzeige mit dem ersten Element
     35 	 * beginnen soll.
     36 	 */
     37 	public static final String FIRST_POST = "first_post";
     38 
     39 	private boolean loadingInProgress = true;
     40 
     41 	protected int displayFrom;
     42 	protected int displayTo;
     43 	protected boolean autoScrollDown;
     44 
     45 	/**
     46 	 * Die in dieser ListActivity enthaltene Liste.<br>
     47 	 * Die Referenz auf diese Liste darf sich nicht ändern, da der ListAdapter
     48 	 * mit dieser Instanz verbunden ist. Durch 'final' wird das sicher gestellt.
     49 	 */
     50 	final protected List<T> entries = new ArrayList<T>();
     51 
     52 	private SharedPreferences prefs;
     53 
     54 	private boolean firstLoad;
     55 
     56 	/**
     57 	 * Absolute Anzahl aller verfügbaren Elemente.
     58 	 * 
     59 	 * @return Anzahl
     60 	 */
     61 	protected abstract int getTotalSize();
     62 
     63 	protected boolean isAutoScrolldown()
     64 	{
     65 		return prefs.getBoolean("scroll_down", false);
     66 	}
     67 
     68 	/**
     69 	 * Initiales Laden der ersten Listeneinträge.
     70 	 */
     71 	protected void initialLoad()
     72 	{
     73 		firstLoad = true;
     74 		prefs = PreferenceManager.getDefaultSharedPreferences(this);
     75 		final int numLoad = Integer.parseInt(prefs.getString("num_load", "10"));
     76 
     77 		if (getIntent().getBooleanExtra(FIRST_POST, false))
     78 			autoScrollDown = false;
     79 		else if (getIntent().getBooleanExtra(LAST_POST, false))
     80 			autoScrollDown = true;
     81 		else
     82 			autoScrollDown = isAutoScrolldown();
     83 
     84 		if (autoScrollDown)
     85 		{
     86 			loadEntries(new OnListLoadedListener<T>()
     87 			{
     88 
     89 				@Override
     90 				public void listLoaded(List<T> list)
     91 				{
     92 					final int end = getTotalSize();
     93 					final int start = Math.max(0, end - numLoad);
     94 
     95 					loadEntries(new OnListLoadedListener<T>()
     96 					{
     97 
     98 						@Override
     99 						public void listLoaded(List<T> list)
    100 						{
    101 							entries.clear();
    102 							entries.addAll(list);
    103 							((BaseAdapter) getListAdapter()).notifyDataSetChanged();
    104 
    105 							displayFrom = start;
    106 							displayTo = end;
    107 
    108 							getListView().setSelection(entries.size() - 1);
    109 
    110 							setOnScrollListener();
    111 
    112 							loadingInProgress = false;
    113 						}
    114 					}, start, end);
    115 
    116 				}
    117 			}, 0, 1);
    118 
    119 		}
    120 		else
    121 		{
    122 			final int start = 0;
    123 			final int end = numLoad - 1;
    124 
    125 			loadEntries(new OnListLoadedListener<T>()
    126 			{
    127 
    128 				@Override
    129 				public void listLoaded(List<T> list)
    130 				{
    131 					entries.clear();
    132 					entries.addAll(list);
    133 					((BaseAdapter) getListAdapter()).notifyDataSetChanged();
    134 
    135 					displayFrom = start;
    136 					displayTo = start + entries.size() - 1;
    137 
    138 					setOnScrollListener();
    139 
    140 					loadingInProgress = false;
    141 				}
    142 			}, start, end);
    143 		}
    144 
    145 	}
    146 
    147 	/**
    148 	 * @param from
    149 	 * @param to
    150 	 * @param firstLoad
    151 	 * @return gelandene Elemente
    152 	 */
    153 	abstract protected void loadEntries(OnListLoadedListener<T> onListLoaded, final int from, final int to,
    154 			boolean firstLoad);
    155 
    156 	/**
    157 	 * @param onListLoaded
    158 	 * @param from
    159 	 * @param to
    160 	 * @param firstLoad
    161 	 * @return gelandene Elemente
    162 	 */
    163 	private void loadEntries(OnListLoadedListener<T> onListLoaded, int from, int to)
    164 	{
    165 		loadEntries(onListLoaded, from, to, firstLoad);
    166 		firstLoad = false;
    167 	}
    168 
    169 	private void setOnScrollListener()
    170 	{
    171 		final ListView list = getListView();
    172 
    173 		/**
    174 		 * Weitere List-Einträge automatisch nachladen.
    175 		 */
    176 		list.setOnScrollListener(new OnScrollListener()
    177 		{
    178 			@Override
    179 			public void onScrollStateChanged(AbsListView view, int scrollState)
    180 			{
    181 			}
    182 
    183 			/**
    184 			 * Callback method to be invoked when the list or grid has been
    185 			 * scrolled. This will be called after the scroll has completed
    186 			 * Parameters
    187 			 * 
    188 			 * @param view
    189 			 *            The view whose scroll state is being reported
    190 			 * @param firstVisibleItem
    191 			 *            the index of the first visible cell (ignore if
    192 			 *            visibleItemCount == 0)
    193 			 * @param visibleItemCount
    194 			 *            the number of visible cells
    195 			 * @param totalItemCount
    196 			 *            the number of items in the list adaptor {@inheritDoc}
    197 			 * 
    198 			 * @see android.widget.AbsListView.OnScrollListener#onScroll(android.widget.AbsListView,
    199 			 *      int, int, int)
    200 			 */
    201 			@Override
    202 			public void onScroll(AbsListView view, final int firstVisibleItem, final int visibleItemCount,
    203 					final int totalItemCount)
    204 			{
    205 
    206 				// Letztes Item, dass angezeigt wird.
    207 				int lastInScreen = firstVisibleItem + visibleItemCount;
    208 
    209 				if (autoScrollDown)
    210 				{
    211 					// Sind wir am oberen Rand der Liste und die Liste ist noch
    212 					// nicht vollständig geladen?
    213 					if (firstVisibleItem == 0 && displayFrom > 0 && !loadingInProgress)
    214 					{
    215 						loadingInProgress = true;
    216 
    217 						int start = Math.max(0, displayFrom - Integer.parseInt(prefs.getString("num_load", "10")));
    218 
    219 						int end = displayFrom - 1;
    220 
    221 						loadEntries(new OnListLoadedListener<T>()
    222 						{
    223 
    224 							@Override
    225 							public void listLoaded(List<T> list)
    226 							{
    227 								int loadedSize = list.size();
    228 								displayFrom -= loadedSize;
    229 
    230 								list.addAll(entries);
    231 								entries.clear();
    232 								entries.addAll(list);
    233 
    234 								((BaseAdapter) getListAdapter()).notifyDataSetChanged();
    235 
    236 								// Zur gleichen Position springen (die jetzt
    237 								// aber etwas weiter nach hinten verschoben
    238 								// ist).
    239 								getListView().setSelection(firstVisibleItem + loadedSize);
    240 
    241 								loadingInProgress = false;
    242 							}
    243 						}, start, end);
    244 
    245 					}
    246 				}
    247 				else
    248 				{
    249 					// Sind wir am unterenRand der Liste?
    250 					if ((lastInScreen == totalItemCount) && (totalItemCount < getTotalSize()) && !(loadingInProgress))
    251 					{
    252 						loadingInProgress = true;
    253 
    254 						int start = displayTo + 1;
    255 						int end = start + Integer.parseInt(prefs.getString("num_load", "10")) - 1;
    256 
    257 						loadEntries(new OnListLoadedListener<T>()
    258 						{
    259 							@Override
    260 							public void listLoaded(List<T> list)
    261 							{
    262 								int loadedSize = list.size();
    263 								entries.addAll(list);
    264 
    265 								displayTo += loadedSize;
    266 
    267 								((BaseAdapter) getListAdapter()).notifyDataSetChanged();
    268 
    269 								loadingInProgress = false;
    270 							}
    271 						}, start, end);
    272 
    273 					}
    274 				}
    275 			}
    276 		});
    277 	}
    278 
    279 	interface OnListLoadedListener<T>
    280 	{
    281 		abstract void listLoaded(List<T> list);
    282 	}
    283 }