Fragmentize ZoneList, which is needed in DateTimeSettings refactoring.

- remove old ZonePicker and rename ZoneList to ZonePicker, as
  the name is really confusing (see LocalePicker)
- Make the new ZonePicker fragment.
- remove dependency toward "ZoneList" class.
-- AndroidManifest.xml does not allow the other components to
   access ZoneList directly, so it would be ok to remove without
   using activity-alias.
-- Noticed there is a significant code duplication between
   DateTimeSettings and DateTimeSettingsActivity. I'll work on it
   later.
- add DateTimeSettingsSetupWizardXL class, which is not used yet,
  but will be in the near future.
-- It is not recognized by AndroidManifest.xml

Change-Id: Id26152a3d560f9e0bd84afdf3e1c5101f0e166b4
This commit is contained in:
Daisuke Miyakawa
2010-09-03 15:40:17 -07:00
parent 0cec40628b
commit 0f4f2f3a81
8 changed files with 262 additions and 325 deletions

View File

@@ -16,55 +16,261 @@
package com.android.settings;
import android.app.ListActivity;
import android.content.Intent;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.ListFragment;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import org.xmlpull.v1.XmlPullParserException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
public class ZonePicker extends ListActivity {
/**
* The class displaying a list of time zones that match a filter string
* such as "Africa", "Europe", etc. Choosing an item from the list will set
* the time zone. Pressing Back without choosing from the list will not
* result in a change in the time zone setting.
*/
public class ZonePicker extends ListFragment {
private static final String TAG = "ZonePicker";
private ArrayAdapter<CharSequence> mFilterAdapter;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mFilterAdapter = ArrayAdapter.createFromResource(this,
R.array.timezone_filters, android.R.layout.simple_list_item_1);
setListAdapter(mFilterAdapter);
public static interface ZoneSelectionListener {
// You can add any argument if you really need it...
public void onZoneSelected();
}
protected void addItem(List<Map> data, String name, String zone) {
HashMap temp = new HashMap();
temp.put("title", name);
temp.put("zone", zone);
data.add(temp);
private static final String KEY_ID = "id";
private static final String KEY_DISPLAYNAME = "name";
private static final String KEY_GMT = "gmt";
private static final String KEY_OFFSET = "offset";
private static final String XMLTAG_TIMEZONE = "timezone";
private static final int HOURS_1 = 60 * 60000;
private static final int MENU_TIMEZONE = Menu.FIRST+1;
private static final int MENU_ALPHABETICAL = Menu.FIRST;
// Initial focus position
private int mDefault;
private boolean mSortedByTimezone;
private SimpleAdapter mTimezoneSortedAdapter;
private SimpleAdapter mAlphabeticalAdapter;
private ZoneSelectionListener mListener;
@Override
public void onActivityCreated(Bundle savedInstanseState) {
super.onActivityCreated(savedInstanseState);
final String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT};
final int[] to = new int[] {android.R.id.text1, android.R.id.text2};
MyComparator comparator = new MyComparator(KEY_OFFSET);
Activity activity = getActivity();
List<HashMap> timezoneSortedList = getZones();
Collections.sort(timezoneSortedList, comparator);
mTimezoneSortedAdapter = new SimpleAdapter(activity,
(List) timezoneSortedList,
android.R.layout.simple_list_item_2,
from,
to);
List<HashMap> alphabeticalList = new ArrayList<HashMap>(timezoneSortedList);
comparator.setSortingKey(KEY_DISPLAYNAME);
Collections.sort(alphabeticalList, comparator);
mAlphabeticalAdapter = new SimpleAdapter(getActivity(),
(List) alphabeticalList,
android.R.layout.simple_list_item_2,
from,
to);
// Sets the adapter
setSorting(true);
// If current timezone is in this list, move focus to it
setSelection(mDefault);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
String filter = (String) mFilterAdapter.getItem(position);
// If All is chosen, reset the filter
if (filter.equals("All")) {
filter = null;
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, MENU_ALPHABETICAL, 0, R.string.zone_list_menu_sort_alphabetically)
.setIcon(android.R.drawable.ic_menu_sort_alphabetically);
menu.add(0, MENU_TIMEZONE, 0, R.string.zone_list_menu_sort_by_timezone)
.setIcon(R.drawable.ic_menu_3d_globe);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
if (mSortedByTimezone) {
menu.findItem(MENU_TIMEZONE).setVisible(false);
menu.findItem(MENU_ALPHABETICAL).setVisible(true);
} else {
menu.findItem(MENU_TIMEZONE).setVisible(true);
menu.findItem(MENU_ALPHABETICAL).setVisible(false);
}
Intent zoneList = new Intent();
zoneList.setClass(this, ZoneList.class);
zoneList.putExtra("filter", filter);
startActivityForResult(zoneList, 0);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// If subactivity has resulted in a timezone selection, close this act.
if (resultCode == RESULT_OK) {
finish();
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_TIMEZONE:
setSorting(true);
return true;
case MENU_ALPHABETICAL:
setSorting(false);
return true;
default:
return false;
}
}
}
public void setZoneSelectionListener(ZoneSelectionListener listener) {
mListener = listener;
}
private void setSorting(boolean timezone) {
setListAdapter(timezone ? mTimezoneSortedAdapter : mAlphabeticalAdapter);
mSortedByTimezone = timezone;
}
private List<HashMap> getZones() {
List<HashMap> myData = new ArrayList<HashMap>();
long date = Calendar.getInstance().getTimeInMillis();
try {
XmlResourceParser xrp = getActivity().getResources().getXml(R.xml.timezones);
while (xrp.next() != XmlResourceParser.START_TAG)
continue;
xrp.next();
while (xrp.getEventType() != XmlResourceParser.END_TAG) {
while (xrp.getEventType() != XmlResourceParser.START_TAG) {
if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) {
return myData;
}
xrp.next();
}
if (xrp.getName().equals(XMLTAG_TIMEZONE)) {
String id = xrp.getAttributeValue(0);
String displayName = xrp.nextText();
addItem(myData, id, displayName, date);
}
while (xrp.getEventType() != XmlResourceParser.END_TAG) {
xrp.next();
}
xrp.next();
}
xrp.close();
} catch (XmlPullParserException xppe) {
Log.e(TAG, "Ill-formatted timezones.xml file");
} catch (java.io.IOException ioe) {
Log.e(TAG, "Unable to read timezones.xml file");
}
return myData;
}
protected void addItem(List<HashMap> myData, String id, String displayName,
long date) {
HashMap map = new HashMap();
map.put(KEY_ID, id);
map.put(KEY_DISPLAYNAME, displayName);
TimeZone tz = TimeZone.getTimeZone(id);
int offset = tz.getOffset(date);
int p = Math.abs(offset);
StringBuilder name = new StringBuilder();
name.append("GMT");
if (offset < 0) {
name.append('-');
} else {
name.append('+');
}
name.append(p / (HOURS_1));
name.append(':');
int min = p / 60000;
min %= 60;
if (min < 10) {
name.append('0');
}
name.append(min);
map.put(KEY_GMT, name.toString());
map.put(KEY_OFFSET, offset);
if (id.equals(TimeZone.getDefault().getID())) {
mDefault = myData.size();
}
myData.add(map);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
Map map = (Map) l.getItemAtPosition(position);
// Update the system timezone value
final Activity activity = getActivity();
AlarmManager alarm = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone((String) map.get(KEY_ID));
if (mListener != null) {
mListener.onZoneSelected();
}
}
private static class MyComparator implements Comparator<HashMap> {
private String mSortingKey;
public MyComparator(String sortingKey) {
mSortingKey = sortingKey;
}
public void setSortingKey(String sortingKey) {
mSortingKey = sortingKey;
}
public int compare(HashMap map1, HashMap map2) {
Object value1 = map1.get(mSortingKey);
Object value2 = map2.get(mSortingKey);
/*
* This should never happen, but just in-case, put non-comparable
* items at the end.
*/
if (!isComparable(value1)) {
return isComparable(value2) ? 1 : 0;
} else if (!isComparable(value2)) {
return -1;
}
return ((Comparable) value1).compareTo(value2);
}
private boolean isComparable(Object value) {
return (value != null) && (value instanceof Comparable);
}
}
}