Addressing comments I originally made on Sandor's change.

This commit is contained in:
Rodrigo Damazio
2010-09-27 21:02:52 -03:00
parent 5733224f8d
commit d7c6761841
28 changed files with 243 additions and 158 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android"><!--
<item android:state_window_focused="false"
android:drawable="@drawable/left_arrow_chart" />
--><item android:state_pressed="true"
android:drawable="@drawable/left_arrow_chart_press" />
<item android:drawable="@drawable/left_arrow_chart" />
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

@@ -17,11 +17,11 @@ limitations under the License.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false"
android:drawable="@drawable/btn_arrow_left_default" />
android:drawable="@drawable/left_arrow_stats" />
<item android:state_pressed="true"
android:drawable="@drawable/btn_arrow_left_press" />
android:drawable="@drawable/left_arrow_stats_press" />
<item android:drawable="@drawable/btn_arrow_left_default" />
<item android:drawable="@drawable/left_arrow_stats" />
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@@ -17,11 +17,11 @@ limitations under the License.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false"
android:drawable="@drawable/btn_arrow_right_default" />
android:drawable="@drawable/left_arrow_track" />
<item android:state_pressed="true"
android:drawable="@drawable/btn_arrow_right_press" />
android:drawable="@drawable/left_arrow_track_press" />
<item android:drawable="@drawable/btn_arrow_right_default" />
<item android:drawable="@drawable/left_arrow_track" />
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false"
android:drawable="@drawable/right_arrow_chart" />
<item android:state_pressed="true"
android:drawable="@drawable/right_arrow_chart_press" />
<item android:drawable="@drawable/right_arrow_chart" />
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false"
android:drawable="@drawable/right_arrow_stats" />
<item android:state_pressed="true"
android:drawable="@drawable/right_arrow_stats_press" />
<item android:drawable="@drawable/right_arrow_stats" />
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false"
android:drawable="@drawable/right_arrow_track" />
<item android:state_pressed="true"
android:drawable="@drawable/right_arrow_track_press" />
<item android:drawable="@drawable/right_arrow_track" />
</selector>
@@ -177,15 +177,15 @@ public class ChartActivity extends Activity implements
cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
ArrayList<double[]> data = new ArrayList<double[]>();
// Need two locations so we can keep track of the last location.
Location[] locations = { new Location(""), new Location("")};
int i = 0;
Location location = new Location("");
do {
lastSeenLocationId = cursor.getLong(idColumnIdx);
providerUtils.fillLocation(cursor, locations[i]);
if (MyTracksUtils.isValidLocation(locations[i])) {
data.add(getDataPoint(locations[i], track));
providerUtils.fillLocation(cursor, location);
if (MyTracksUtils.isValidLocation(location)) {
double[] point = new double[3];
location = getDataPoint(location, track, point);
data.add(point);
}
i = (i + 1) % 2;
} while (cursor.moveToPrevious());
cv.addDataPoints(data);
}
@@ -465,11 +465,14 @@ public class ChartActivity extends Activity implements
* data[1] = the elevation
* data[2] = the speed
*
* @param location a location
* @return the data point
* This must be called in order for each point.
*
* @param location the location to get data for (this method takes ownership of that location)
* @param track the track to get data from
* @param result the resulting point to fill out
* @return the previous location, now available for reuse
*/
public double[] getDataPoint(Location location, Track track) {
double[] result = new double[3];
private Location getDataPoint(Location location, Track track, double[] result) {
switch (mode) {
case BY_DISTANCE:
result[0] = profileLength;
@@ -516,8 +519,16 @@ public class ChartActivity extends Activity implements
// Format as hours per unit
result[2] = (60.0 / result[2]);
}
Location oldLastLocation = lastLocation;
lastLocation = location;
return result;
if (oldLastLocation == null) {
// No previous location, but return a blank one for reuse
return new Location("");
}
return oldLastLocation;
}
/**
@@ -561,8 +572,7 @@ public class ChartActivity extends Activity implements
final ArrayList<double[]> theData = new ArrayList<double[]>();
int points = 0;
// Need two locations so we can keep track of the last location.
Location[] locations = { new Location(""), new Location("")};
int i = 0;
Location location = new Location("");
while (lastLocationRead < track.getStopId()) {
cursor = providerUtils.getLocationsCursor(
selectedTrackId, lastLocationRead, bufferSize, false);
@@ -574,16 +584,16 @@ public class ChartActivity extends Activity implements
cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
while (cursor.moveToNext()) {
points++;
providerUtils.fillLocation(cursor, locations[i]);
if (MyTracksUtils.isValidLocation(locations[i])) {
providerUtils.fillLocation(cursor, location);
if (MyTracksUtils.isValidLocation(location)) {
lastLocationRead = lastSeenLocationId =
cursor.getLong(idColumnIdx);
double[] point = getDataPoint(locations[i], track);
double[] point = new double[3];
location = getDataPoint(location, track, point);
if (points % chartSamplingFrequency == 0) {
theData.add(point);
}
}
i = (i + 1) % 2;
}
} else {
lastLocationRead += bufferSize;
@@ -76,7 +76,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Random;
import javax.xml.parsers.ParserConfigurationException;
@@ -213,40 +212,25 @@ public class MyTracks extends TabActivity implements OnTouchListener,
* Tabs/View navigation:
*/
private static final int NUM_TABS = 3;
private int currentTab = 0;
private NavControls navControls;
private final int icons[] =
{ R.drawable.arrow_grey, R.drawable.menu_by_time,
R.drawable.menu_elevation };
/** Icons shown on the left for each tab. */
private final int leftIcons[] =
{ R.drawable.left_arrow_chart_stateful,
R.drawable.left_arrow_track_stateful,
R.drawable.left_arrow_stats_stateful };
/** Icons shown on the right for each tab. */
private final int rightIcons[] =
{ R.drawable.right_arrow_stats_stateful,
R.drawable.right_arrow_chart_stateful,
R.drawable.right_arrow_track_stateful };
private final Runnable nextActivity = new Runnable() {
private final Runnable changeTab = new Runnable() {
public void run() {
currentTab = (currentTab + 1) % NUM_TABS;
navControls.setLeftIcon(icons[(currentTab + NUM_TABS - 1) % NUM_TABS]);
navControls.setRightIcon(icons[(currentTab + NUM_TABS + 1) % NUM_TABS]);
getTabHost().setCurrentTab(currentTab);
navControls.show();
getTabHost().setCurrentTab(navControls.getCurrentIcons());
}
};
private final Runnable prevActivity = new Runnable() {
public void run() {
currentTab--;
if (currentTab < 0) {
currentTab = NUM_TABS - 1;
}
navControls.setLeftIcon(icons[(currentTab + NUM_TABS - 1) % NUM_TABS]);
navControls.setRightIcon(icons[(currentTab + NUM_TABS + 1) % NUM_TABS]);
getTabHost().setCurrentTab(currentTab);
navControls.show();
}
};
private final Random random = new Random();
public static MyTracks getInstance() {
return instance;
}
@@ -307,9 +291,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
LayoutParams params =
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
layout.setLayoutParams(params);
navControls = new NavControls(this, layout, prevActivity, nextActivity);
navControls.setLeftIcon(icons[NUM_TABS - 1]);
navControls.setRightIcon(icons[1]);
navControls = new NavControls(this, layout, leftIcons, rightIcons, changeTab);
navControls.show();
tabHost.addView(layout);
layout.setOnTouchListener(this);
@@ -368,8 +350,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
Log.d(MyTracksConstants.TAG, "MyTracks.onResume");
super.onResume();
tryBindTrackRecordingService();
navControls.setLeftIcon(icons[(currentTab + NUM_TABS - 1) % NUM_TABS]);
navControls.setRightIcon(icons[(currentTab + NUM_TABS + 1) % NUM_TABS]);
}
@Override
@@ -15,13 +15,9 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -30,7 +26,6 @@ import android.view.animation.Animation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
/**
* Creates previous and next arrows for a given activity.
@@ -53,31 +48,22 @@ public class NavControls {
/**
* A touchable image view.
* When touched it changes the navigation control icons accordingly.
*/
public class TouchLayout extends RelativeLayout {
private final ImageView arrow;
private class TouchLayout extends RelativeLayout implements Runnable {
private final boolean isLeft;
private final ImageView icon;
public TouchLayout(Activity activity, boolean isLeft) {
super(activity);
arrow = new ImageView(activity);
arrow.setImageDrawable(activity.getResources().getDrawable(
isLeft ? R.drawable.btn_arrow_left : R.drawable.btn_arrow_right));
icon = new ImageView(activity);
public TouchLayout(Context context, boolean isLeft) {
super(context);
this.isLeft = isLeft;
this.icon = new ImageView(context);
icon.setVisibility(View.GONE);
addView(arrow);
addView(icon);
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
// TODO: This should be a smooth function not a step function.
if (metrics.heightPixels > 600) {
icon.setPadding((isLeft ? 25 : 15), 39, 15, 0);
} else {
icon.setPadding((isLeft ? 15 : 10), 27, 15, 0);
}
}
public void setIcon(Drawable drawable) {
public void setIcon(int iconId) {
Drawable drawable = getContext().getResources().getDrawable(iconId);
icon.setImageDrawable(drawable);
icon.setVisibility(View.VISIBLE);
}
@@ -87,18 +73,11 @@ public class NavControls {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setPressed(true);
hide();
if (this == prevImage) {
if (prevRunnable != null) {
handler.post(prevRunnable);
return true;
}
} else if (this == nextImage) {
if (nextRunnable != null) {
handler.post(nextRunnable);
return true;
}
}
shiftIcons(isLeft);
// Call the user back
handler.post(this);
break;
case MotionEvent.ACTION_UP:
setPressed(false);
@@ -106,55 +85,69 @@ public class NavControls {
}
return super.onTouchEvent(event);
}
@Override
public void run() {
touchRunnable.run();
setPressed(false);
}
}
private final Context context;
private final Runnable prevRunnable;
private final Runnable nextRunnable;
private final Handler handler = new Handler();
private final Runnable dismissControls = new Runnable() {
public void run() {
hide();
}
};
private final TouchLayout prevImage;
private final TouchLayout nextImage;
private final int[] leftIcons;
private final int[] rightIcons;
private final Runnable touchRunnable;
private boolean isVisible = false;
private boolean hasNext = true;
private boolean hasPrev = true;
private int currentIcons;
public NavControls(Context context, ViewGroup container,
int[] leftIcons, int[] rightIcons,
Runnable touchRunnable) {
this.leftIcons = leftIcons;
this.rightIcons = rightIcons;
this.touchRunnable = touchRunnable;
if (leftIcons.length != rightIcons.length || leftIcons.length < 1) {
throw new IllegalArgumentException("Invalid icons specified");
}
if (touchRunnable == null) {
throw new NullPointerException("Runnable cannot be null");
}
public NavControls(Activity activity, ViewGroup container,
Runnable prevRunnable, Runnable nextRunnable) {
this.context = activity;
this.prevRunnable = prevRunnable;
this.nextRunnable = nextRunnable;
LayoutParams prevParams = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
prevParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
prevParams.addRule(RelativeLayout.CENTER_VERTICAL);
prevImage = new TouchLayout(activity, true);
prevImage.setLayoutParams(prevParams);
prevImage.setVisibility(View.INVISIBLE);
container.addView(prevImage);
LayoutParams nextParams = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
prevParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
nextParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
prevParams.addRule(RelativeLayout.CENTER_VERTICAL);
nextParams.addRule(RelativeLayout.CENTER_VERTICAL);
nextImage = new TouchLayout(activity, false);
nextImage = new TouchLayout(context, false);
prevImage = new TouchLayout(context, true);
nextImage.setLayoutParams(nextParams);
prevImage.setLayoutParams(prevParams);
nextImage.setVisibility(View.INVISIBLE);
prevImage.setVisibility(View.INVISIBLE);
container.addView(prevImage);
container.addView(nextImage);
}
public void setHasNext(boolean hasNext) {
this.hasNext = hasNext;
}
public void setHasPrev(boolean hasPrev) {
this.hasPrev = hasPrev;
prevImage.setIcon(leftIcons[0]);
nextImage.setIcon(rightIcons[0]);
this.currentIcons = 0;
}
private void keepVisible() {
@@ -166,20 +159,18 @@ public class NavControls {
public void show() {
if (!isVisible) {
if (prevRunnable != null && hasPrev) {
SHOW_PREV_ANIMATION.setDuration(500);
SHOW_PREV_ANIMATION.startNow();
prevImage.setPressed(false);
prevImage.setAnimation(SHOW_PREV_ANIMATION);
prevImage.setVisibility(View.VISIBLE);
}
if (nextRunnable != null && hasNext) {
SHOW_NEXT_ANIMATION.setDuration(500);
SHOW_NEXT_ANIMATION.startNow();
nextImage.setPressed(false);
nextImage.setAnimation(SHOW_NEXT_ANIMATION);
nextImage.setVisibility(View.VISIBLE);
}
SHOW_PREV_ANIMATION.setDuration(500);
SHOW_PREV_ANIMATION.startNow();
prevImage.setPressed(false);
prevImage.setAnimation(SHOW_PREV_ANIMATION);
prevImage.setVisibility(View.VISIBLE);
SHOW_NEXT_ANIMATION.setDuration(500);
SHOW_NEXT_ANIMATION.startNow();
nextImage.setPressed(false);
nextImage.setAnimation(SHOW_NEXT_ANIMATION);
nextImage.setVisibility(View.VISIBLE);
isVisible = true;
keepVisible();
} else {
@@ -198,33 +189,25 @@ public class NavControls {
public void hide() {
isVisible = false;
if (prevRunnable != null) {
if (hasPrev) {
prevImage.setAnimation(HIDE_PREV_ANIMATION);
HIDE_PREV_ANIMATION.setDuration(500);
HIDE_PREV_ANIMATION.startNow();
} else {
prevImage.clearAnimation();
}
prevImage.setVisibility(View.INVISIBLE);
}
if (nextRunnable != null) {
if (hasNext) {
nextImage.setAnimation(HIDE_NEXT_ANIMATION);
HIDE_NEXT_ANIMATION.setDuration(500);
HIDE_NEXT_ANIMATION.startNow();
} else {
nextImage.clearAnimation();
}
nextImage.setVisibility(View.INVISIBLE);
}
prevImage.setAnimation(HIDE_PREV_ANIMATION);
HIDE_PREV_ANIMATION.setDuration(500);
HIDE_PREV_ANIMATION.startNow();
prevImage.setVisibility(View.INVISIBLE);
nextImage.setAnimation(HIDE_NEXT_ANIMATION);
HIDE_NEXT_ANIMATION.setDuration(500);
HIDE_NEXT_ANIMATION.startNow();
nextImage.setVisibility(View.INVISIBLE);
}
public void setLeftIcon(int resourceId) {
prevImage.setIcon(context.getResources().getDrawable(resourceId));
public int getCurrentIcons() {
return currentIcons;
}
public void setRightIcon(int resourceId) {
nextImage.setIcon(context.getResources().getDrawable(resourceId));
private void shiftIcons(boolean isLeft) {
// Increment or decrement by one, with wrap around
currentIcons = (currentIcons + leftIcons.length + (isLeft ? -1 : 1)) % leftIcons.length;
prevImage.setIcon(leftIcons[currentIcons]);
nextImage.setIcon(rightIcons[currentIcons]);
}
}
@@ -203,7 +203,9 @@ public interface MyTracksProviderUtils {
*
* @param track to load locations for
* @param buffer an array of locations to fill
* @deprecated use {@link #fillTrackPoints} instead
*/
@Deprecated
void getTrackPoints(Track track, TrackBuffer buffer);
/**
@@ -175,6 +175,8 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override
public void fillLocation(Cursor cursor, Location location) {
location.reset();
int idxLatitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE);
int idxLongitude =
cursor.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE);
@@ -865,7 +867,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
do {
if (reuseLocations) {
fillLocation(cursor, buffer.location(cursor.getLong(idColumnIdx)));
fillLocation(cursor, buffer.add(cursor.getLong(idColumnIdx)));
} else {
Location location = createLocation(cursor);
if (location == null) {
@@ -874,7 +876,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
buffer.add(location, cursor.getLong(idColumnIdx));
}
} while (cursor.moveToNext());
if (buffer.getLocationsLoaded() == 0) {
Log.w(MyTracksProvider.TAG, "No locations read.");
buffer.resetAt(startingPoint + buffer.getSize());
@@ -98,11 +98,11 @@ public class TrackBuffer {
/**
* Get a location from the end of the buffer.
* This may reuse Location objects already allocated to the buffer.
* @param id The of the location to be added.
* @param locationId The of the location to be added.
* @return The location object associated with the give id.
*/
public Location location(long id) {
lastLocationRead = Math.max(lastLocationRead, id);
public Location add(long locationId) {
lastLocationRead = Math.max(lastLocationRead, locationId);
if (buffer[locationsLoaded] == null) {
buffer[locationsLoaded] = new Location("");
} else {