project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListFragment.java
author Xeli
Sat, 03 Dec 2011 18:49:17 +0100
changeset 6485 7586c266b52e
parent 6446 a49d01b96185
child 7584 7831c84cc644
permissions -rw-r--r--
android: hopefully prevents a FC, I can't reproduce it though..

package org.hedgewars.hedgeroid.Downloader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;

public class DownloadListFragment extends ListFragment implements OnItemClickListener, OnScrollListener, Runnable{

	private View targetView = null;
	private ArrayList<OnItemMovementListener> listeners = new ArrayList<OnItemMovementListener>(); 

	public void onActivityCreated(Bundle savedInstanceState){
		super.onActivityCreated(savedInstanceState);

		ArrayList<DownloadPackage> tasks = new ArrayList<DownloadPackage>();

		ArrayAdapter<DownloadPackage> adapter = new ArrayAdapter<DownloadPackage>(getActivity().getApplicationContext(), android.R.layout.simple_list_item_1, tasks);
		setListAdapter(adapter);
		getListView().setOnItemClickListener(this);
		getListView().setOnScrollListener(this);

		if(getActivity() instanceof OnItemMovementListener){
			listeners.add((OnItemMovementListener)getActivity());
		}

		getListView().setCacheColorHint(Color.TRANSPARENT);//To prevent a blackish background while scrolling
		
		
		Thread t = new Thread(this, "DownloadListParser");
		t.start();
	}

	public void run(){
		XmlPullParserFactory xmlPullFactory;
		try {
			xmlPullFactory = XmlPullParserFactory.newInstance();
			XmlPullParser xmlPuller = xmlPullFactory.newPullParser();

			URL url = new URL("http://www.xelification.com/tmp/downloads.xml");
			HttpURLConnection conn = (HttpURLConnection)url.openConnection();

			BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()), 1024);
			xmlPuller.setInput(br);

			final ArrayAdapter<DownloadPackage> adapter = (ArrayAdapter<DownloadPackage>) getListAdapter();
			
			int eventType = xmlPuller.getEventType();
			while(eventType != XmlPullParser.END_DOCUMENT){
			
				if(eventType == XmlPullParser.START_TAG){
					if(xmlPuller.getName().toLowerCase().equals("task")){
						final DownloadPackage task = DownloadPackage.getTaskFromXML(getActivity(), xmlPuller);
						
						getActivity().runOnUiThread(new Runnable(){
							public void run() {
								adapter.add(task);								
							}
						});
					}
				}
				eventType = getEventType(xmlPuller);
			}
			
			
		} catch (XmlPullParserException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	

	/**
	 * Skips whitespaces..
	 */
	private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{
		int eventType = xmlPuller.next();
		while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){
			eventType = xmlPuller.next();
		}
		return eventType;
	}

	public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
		DownloadPackage task = (DownloadPackage)arg0.getAdapter().getItem(position);
		/*
		FragmentTransaction ft = getFragmentManager().beginTransaction();
		Fragment prev = getFragmentManager().findFragmentByTag("dialog");

		//remove any old dialogs
		if(prev != null) ft.remove(prev);
		ft.addToBackStack(null);

		//create a new dialog based on this task
		
		DialogFragment newFragment = DownloadDialogFragment.newInstance(task);

		//show it
		newFragment.show(ft, "dialog");
		 */
		targetView = arg1;

		//determine state
		int min = arg0.getTop();
		int max = arg0.getBottom();
		int top = targetView.getTop();

		previousXCoord = top;
		for(OnItemMovementListener listener : listeners){
			listener.onNewItemSelected(task, top, min, max, targetView.getHeight()*2);
		}
	}

	private int previousXCoord = 0;

	/*
	 * (non-Javadoc)
	 * @see android.widget.AbsListView.OnScrollListener#onScroll(android.widget.AbsListView, int, int, int)
	 * 
	 * Android renews the Items used in the view, so when a user scroll down the list, 
	 * as soon as the item has dissapeard from the list it gets reused at the bottom.
	 * 
	 * For this reason we cannot just keep sending the targetView.getTop() but we must
	 *  remember if the view is supposed to be at the top or bottom of the list. We 
	 *  remember this with int state, 
	 *     - 0 means we've got accurate reading from getTop()
	 *     - -1 means it's somewhere at the top of the list
	 *     - 1 means it's at the bottom somewhere
	 */
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		if(targetView != null){
			int top = targetView.getTop() + (targetView.getHeight()/2);
			int min = view.getTop();
			int max = view.getBottom();

			if(Math.abs(previousXCoord - top) > targetView.getHeight()*2 ){
				top = previousXCoord;
			}

			for(OnItemMovementListener listener : listeners){
				listener.onViewMoved(top, min, max);
			}

			previousXCoord = top;
		}
	}

	public void onScrollStateChanged(AbsListView view, int scrollState) {
		switch(scrollState){
		case OnScrollListener.SCROLL_STATE_FLING: Log.d("tag", "fling"); break;
		case OnScrollListener.SCROLL_STATE_IDLE:Log.d("tag", "idle"); break;
		case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:Log.d("tag", "scroll"); break;

		}

	}
}

interface OnItemMovementListener{
	/**
	 * When I new item has been selected this method will be called
	 * @param task The task which goes with this item
	 * @param x The middle of this item
	 * @param minX The top of the parent of this item
	 * @param maxX The bottom of the parent of this item
	 */
	void onNewItemSelected(DownloadPackage task, int x, int minX, int maxX, int size);

	/**
	 * When the item has been moved this method is called
	 * @param x The middle of this item
	 * @param minX The top of the parent of this item
	 * @param maxX The bottom of the parent of this item
	 */
	void onViewMoved(int x, int minX, int maxX);
}