update app widget layout

This commit is contained in:
Jimmy Shih
2012-10-02 14:30:53 -07:00
parent 7240d02c06
commit 5db20b48ca
9 changed files with 539 additions and 272 deletions
-114
View File
@@ -1,114 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2011 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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/track_widget_background"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:padding="@dimen/widget_margin" >
<LinearLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp" >
<LinearLayout
android:clickable="true"
android:id="@+id/track_widget_statistics"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="vertical" >
<LinearLayout style="@style/TrackWidgetStat" >
<TextView
android:text="@string/stats_total_distance"
style="@style/TrackWidgetLabel" />
<TextView style="@style/TrackWidgetSpacer" />
<TextView
android:id="@+id/track_widget_total_distance_value"
style="@style/TrackWidgetLabel" />
</LinearLayout>
<LinearLayout style="@style/TrackWidgetSeparator" />
<LinearLayout style="@style/TrackWidgetStat" >
<TextView
android:text="@string/stats_total_time"
style="@style/TrackWidgetLabel" />
<TextView style="@style/TrackWidgetSpacer" />
<Chronometer
android:id="@+id/track_widget_total_time_value"
style="@style/TrackWidgetLabel" />
</LinearLayout>
<LinearLayout style="@style/TrackWidgetSeparator" />
<LinearLayout style="@style/TrackWidgetStat" >
<TextView
android:id="@+id/track_widget_average_speed_label"
style="@style/TrackWidgetLabel" />
<TextView style="@style/TrackWidgetSpacer" />
<TextView
android:id="@+id/track_widget_average_speed_value"
style="@style/TrackWidgetLabel" />
</LinearLayout>
<LinearLayout
android:id="@+id/track_widget_moving_time_container"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="vertical" >
<LinearLayout style="@style/TrackWidgetSeparator" />
<LinearLayout style="@style/TrackWidgetStat" >
<TextView
android:text="@string/stats_moving_time"
style="@style/TrackWidgetLabel" />
<TextView style="@style/TrackWidgetSpacer" />
<TextView
android:id="@+id/track_widget_moving_time_value"
style="@style/TrackWidgetLabel" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:clipChildren="false"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingTop="4dp" >
<ImageButton
android:background="@android:color/transparent"
android:contentDescription="@string/icon_record_track"
android:id="@+id/track_widget_record_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/btn_record" />
<TextView
android:id="@+id/track_widget_record_status"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_width="0dp"
android:singleLine="true"
style="@style/TextSmall" />
<ImageButton
android:background="@android:color/transparent"
android:contentDescription="@string/icon_stop_recording"
android:id="@+id/track_widget_stop_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/btn_stop_0" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
+125
View File
@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2011 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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/track_widget_background"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:padding="@dimen/widget_margin" >
<LinearLayout
android:clickable="true"
android:id="@+id/track_widget_statistics"
android:layout_alignParentTop="true"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="vertical"
android:padding="4dp" >
<LinearLayout style="@style/LinearLayoutHorizontal" >
<!-- average moving speed -->
<LinearLayout style="@style/TrackWidgetItemContainer" >
<TextView
android:id="@+id/track_widget_average_moving_speed_label"
style="@style/TrackWidgetLabel" />
<LinearLayout style="@style/TrackWidgetValueContainer" >
<TextView
android:id="@+id/track_widget_average_moving_speed_value"
style="@style/TrackWidgetValue" />
<TextView
android:id="@+id/track_widget_average_moving_speed_unit"
style="@style/TrackWidgetUnit" />
</LinearLayout>
</LinearLayout>
<!-- vertical separator -->
<LinearLayout style="@style/LinearLayoutVertifcal" >
<LinearLayout style="@style/TrackWidgetVerticalSpacer" />
<LinearLayout style="@style/TrackWidgetVerticalSeparator" />
</LinearLayout>
<!-- moving time -->
<LinearLayout style="@style/TrackWidgetItemContainer" >
<TextView
android:text="@string/stats_moving_time"
style="@style/TrackWidgetLabel" />
<LinearLayout style="@style/TrackWidgetValueContainer" >
<TextView
android:id="@+id/track_widget_moving_time_value"
style="@style/TrackWidgetValue" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- horizontal separator -->
<LinearLayout style="@style/TrackWidgetHorizontalSeparator" />
<LinearLayout style="@style/LinearLayoutHorizontal" >
<!-- average speed -->
<LinearLayout style="@style/TrackWidgetItemContainer" >
<TextView
android:id="@+id/track_widget_average_speed_label"
style="@style/TrackWidgetLabel" />
<LinearLayout style="@style/TrackWidgetValueContainer" >
<TextView
android:id="@+id/track_widget_average_speed_value"
style="@style/TrackWidgetValue" />
<TextView
android:id="@+id/track_widget_average_speed_unit"
style="@style/TrackWidgetUnit" />
</LinearLayout>
</LinearLayout>
<!-- vertical separator -->
<LinearLayout style="@style/LinearLayoutVertifcal" >
<LinearLayout style="@style/TrackWidgetVerticalSeparator" />
<LinearLayout style="@style/TrackWidgetVerticalSpacer" />
</LinearLayout>
<!-- total distance -->
<LinearLayout style="@style/TrackWidgetItemContainer" >
<TextView
android:text="@string/stats_total_distance"
style="@style/TrackWidgetLabel" />
<LinearLayout style="@style/TrackWidgetValueContainer" >
<TextView
android:id="@+id/track_widget_total_distance_value"
style="@style/TrackWidgetValue" />
<TextView
android:id="@+id/track_widget_total_distance_unit"
style="@style/TrackWidgetUnit" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_below="@id/track_widget_statistics"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:paddingBottom="4dp"
android:paddingTop="4dp" >
<LinearLayout style="@style/TrackWidgetVerticalSpacer" />
<ImageButton
android:id="@+id/track_widget_record_button"
style="@style/TrackWidgetRecordButton" />
<TextView
android:id="@+id/track_widget_record_status"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_weight="4"
android:layout_width="0dp"
android:singleLine="true"
style="@style/TextSmall" />
<ImageButton
android:id="@+id/track_widget_stop_button"
style="@style/TrackWidgetStopButton" />
<LinearLayout style="@style/TrackWidgetVerticalSpacer" />
</LinearLayout>
<ImageView style="@style/TrackWidgetLogo" />
</RelativeLayout>
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/track_widget_background"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:padding="@dimen/widget_margin" >
<LinearLayout
android:layout_alignParentTop="true"
android:layout_height="100dp"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:paddingBottom="4dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="4dp" >
<ImageButton
android:id="@+id/track_widget_record_button"
style="@style/TrackWidgetRecordButton" />
<LinearLayout
android:clickable="true"
android:id="@+id/track_widget_statistics"
android:layout_height="fill_parent"
android:layout_weight="1"
android:layout_width="0dp"
android:orientation="vertical"
android:paddingLeft="4dp"
android:paddingRight="4dp" >
<LinearLayout
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="fill_parent"
android:orientation="vertical" >
<TextView
android:text="@string/stats_moving_time"
style="@style/TrackWidgetLabel" />
<LinearLayout style="@style/TrackWidgetValueContainer" >
<TextView
android:id="@+id/track_widget_moving_time_value"
style="@style/TrackWidgetValue" />
</LinearLayout>
</LinearLayout>
<LinearLayout style="@style/TrackWidgetHorizontalSeparator" />
<LinearLayout
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="fill_parent"
android:orientation="vertical" >
<TextView
android:text="@string/stats_total_distance"
style="@style/TrackWidgetLabel" />
<LinearLayout style="@style/TrackWidgetValueContainer" >
<TextView
android:id="@+id/track_widget_total_distance_value"
style="@style/TrackWidgetValue" />
<TextView
android:id="@+id/track_widget_total_distance_unit"
style="@style/TrackWidgetUnit" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<ImageButton
android:id="@+id/track_widget_stop_button"
style="@style/TrackWidgetStopButton" />
</LinearLayout>
<ImageView style="@style/TrackWidgetLogo" />
</RelativeLayout>
+2 -12
View File
@@ -18,44 +18,34 @@ limitations under the License.
<color name="black">#FF000000</color>
<color name="blue">#FF0000FF</color>
<color name="gray">#FF444444</color>
<color name="orange">#FFFAAD2C</color>
<color name="red">#FFBE161B</color>
<!-- holo_orange_dark -->
<color name="warning_background">#FFFF8800</color>
<!-- elevation chart colors, green and transparent green -->
<color name="elevation_border">#FF339933</color>
<color name="elevation_fill">#40B3CFB3</color>
<!-- speed chart colors, blue and transparent blue -->
<color name="speed_border">#FF0066FF</color>
<color name="speed_fill">#40C8E0FF</color>
<!-- pace chart colors, blue and transparent blue -->
<color name="pace_border">#FF0066FF</color>
<color name="pace_fill">#40C8E0FF</color>
<!-- heart rate chart colors, red and transparent red -->
<color name="heart_rate_border">#FFCC3300</color>
<color name="heart_rate_fill">#40E88A70</color>
<!-- cadence chart colors, pink and transparent pink -->
<color name="cadence_border">#FFF128F3</color>
<color name="cadence_fill">#40F128F3</color>
<!-- power chart colors, purple and transparent purple -->
<color name="power_border">#FF401465</color>
<color name="power_fill">#40401465</color>
<!-- track widget line -->
<!-- track widget -->
<color name="track_widget_line">#99999999</color>
<!-- dynamic track slow path, green -->
<color name="slow_path">#F774DF00</color>
<!-- dynamic track normal path, blue -->
<color name="normal_path">#F75858FA</color>
<!-- dynamic track fast path, red -->
<color name="fast_path">#F7DF0101</color>
</resources>
+13 -6
View File
@@ -2137,19 +2137,19 @@ limitations under the License.
<!-- Stats Page -->
<string name="stats_average_moving_pace"
translation_description="In the 'Stats' page, the average moving pace.">
Average moving pace
Avg moving pace
</string>
<string name="stats_average_moving_speed"
translation_description="In the 'Stats' page, the average moving speed.">
Average moving speed
Avg moving speed
</string>
<string name="stats_average_pace"
translation_description="In the 'Stats' page, the average pace.">
Average pace
Avg pace
</string>
<string name="stats_average_speed"
translation_description="In the 'Stats' page, the average speed.">
Average speed
Avg speed
</string>
<string name="stats_elevation"
translation_description="In the 'Stats' page, the elevation.
@@ -2211,7 +2211,7 @@ limitations under the License.
</string>
<string name="stats_total_distance"
translation_description="In the 'Stats' page, the total distance.">
Total distance
Distance
</string>
<string name="stats_total_time"
translation_description="In the 'Stats' page, the total time.">
@@ -2318,7 +2318,14 @@ limitations under the License.
translation_description="Abbreviation for miles per hour. E.g, '5 mi/h'.">
mi/h
</string>
<string name="unit_minute_per_kilometer"
translation_description="Abbreviation for minutes per kilometer. E.g, '5 min/km'.">
min/km
</string>
<string name="unit_minute_per_mile"
translation_description="Abbreviation for minutes per mile. E.g, '5 min/mi'.">
min/mi
</string>
<!-- Value -->
<string name="value_adapt_accuracy"
translation_description="In a setting picker, the value to adapt for accuracy.">
+96 -15
View File
@@ -111,6 +111,18 @@ limitations under the License.
<item name="android:singleLine">true</item>
<item name="android:textColor">@android:color/secondary_text_dark</item>
</style>
<!-- The style for a horizontal linear layout -->
<style name="LinearLayoutHorizontal">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:orientation">horizontal</item>
</style>
<!-- The style for a vertical linear layout -->
<style name="LinearLayoutVertifcal">
<item name="android:layout_height">fill_parent</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:orientation">vertical</item>
</style>
<!-- The style for the scroll view -->
<style name="ScrollView">
<item name="android:layout_height">fill_parent</item>
@@ -194,27 +206,96 @@ limitations under the License.
<item name="android:layout_width">fill_parent</item>
<item name="android:orientation">vertical</item>
</style>
<!-- The style for the track widget label -->
<style name="TrackWidgetLabel" parent="@style/TextSmall">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_width">0dp</item>
<!-- The style for the track widget button -->
<style name="TrackWidgetButton">
<item name="android:background">@android:color/transparent</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:scaleType">fitXY</item>
</style>
<!-- The style for the track widget separator -->
<style name="TrackWidgetSeparator">
<!-- The style for the track widget horizontal separator -->
<style name="TrackWidgetHorizontalSeparator">
<item name="android:background">@color/track_widget_line</item>
<item name="android:layout_height">1dp</item>
<item name="android:layout_width">fill_parent</item>
</style>
<!-- The style for the track widget spacer -->
<style name="TrackWidgetSpacer">
<item name="android:layout_height">fill_parent</item>
<item name="android:layout_width">4dp</item>
</style>
<!-- The style for the track widget stat -->
<style name="TrackWidgetStat">
<!-- The style for the track widget item container -->
<style name="TrackWidgetItemContainer">
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_width">0dp</item>
<item name="android:orientation">vertical</item>
<item name="android:paddingBottom">2dp</item>
<item name="android:paddingTop">2dp</item>
</style>
<!-- The style for the track widget label -->
<style name="TrackWidgetLabel" parent="@style/TextSmall">
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:singleLine">true</item>
<item name="android:textAllCaps">true</item>
<item name="android:textColor">@color/orange</item>
</style>
<style name="TrackWidgetLogo">
<item name="android:contentDescription">@string/my_tracks_app_name</item>
<item name="android:layout_alignParentRight">true</item>
<item name="android:layout_alignParentTop">true</item>
<item name="android:layout_height">24dp</item>
<item name="android:layout_width">20dp</item>
<item name="android:padding">4dp</item>
<item name="android:scaleType">fitXY</item>
<item name="android:src">@drawable/my_tracks_icon</item>
</style>
<!-- The style for the track widget record button -->
<style name="TrackWidgetRecordButton" parent="@style/TrackWidgetButton">
<item name="android:contentDescription">@string/icon_record_track</item>
<item name="android:layout_height">63dp</item>
<item name="android:layout_width">75dp</item>
<item name="android:src">@drawable/btn_record</item>
</style>
<!-- The style for the track widget stop button -->
<style name="TrackWidgetStopButton" parent="@style/TrackWidgetButton">
<item name="android:contentDescription">@string/icon_stop_recording</item>
<item name="android:layout_height">63dp</item>
<item name="android:layout_width">63dp</item>
<item name="android:src">@drawable/btn_stop_0</item>
</style>
<!-- The style for the track widget unit -->
<style name="TrackWidgetUnit" parent="@style/TextSmall">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_width">0dp</item>
<item name="android:paddingLeft">4dp</item>
<item name="android:singleLine">true</item>
</style>
<!-- The style for the track widget value -->
<style name="TrackWidgetValue" parent="@style/TextSmall">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">2</item>
<item name="android:layout_width">0dp</item>
<item name="android:singleLine">true</item>
<item name="android:textColor">@android:color/white</item>
<item name="android:textStyle">bold</item>
</style>
<!-- The style for the track widget value container -->
<style name="TrackWidgetValueContainer">
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:orientation">horizontal</item>
</style>
<!-- The style for the track widget vertical separator -->
<style name="TrackWidgetVerticalSeparator">
<item name="android:background">@color/track_widget_line</item>
<item name="android:layout_height">0dp</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_width">1dp</item>
</style>
<!-- The style for the track widget vertical spacer -->
<style name="TrackWidgetVerticalSpacer">
<item name="android:layout_height">0dp</item>
<item name="android:layout_weight">2</item>
<item name="android:layout_width">1dp</item>
</style>
</resources>
+4 -1
View File
@@ -15,7 +15,10 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/track_widget"
android:initialLayout="@layout/track_widget_large"
android:minHeight="110dp"
android:minResizeHeight="40dp"
android:minResizeWidth="250dp"
android:minWidth="250dp"
android:resizeMode="vertical"
android:updatePeriodMillis="0" />
@@ -33,7 +33,7 @@ import java.util.regex.Pattern;
/**
* Various string manipulation methods.
*
*
* @author Sandor Dornbush
* @author Rodrigo Damazio
*/
@@ -64,7 +64,8 @@ public class StringUtils {
}
/**
* Formats the relative date and time based on user's phone date/time preferences.
* Formats the relative date and time based on user's phone date/time
* preferences.
*
* @param context the context
* @param time the time in milliseconds
@@ -74,15 +75,15 @@ public class StringUtils {
if (now - time > DateUtils.WEEK_IN_MILLIS) {
return formatDateTime(context, time);
} else {
return DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_ABBREV_RELATIVE).toString();
return DateUtils.getRelativeTimeSpanString(
time, now, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString();
}
}
/**
* Formats the time using the ISO 8601 date time format with fractional
* seconds in UTC time zone.
*
*
* @param time the time in milliseconds
*/
public static String formatDateTimeIso8601(long time) {
@@ -91,7 +92,7 @@ public class StringUtils {
/**
* Formats the elapsed timed in the form "MM:SS" or "H:MM:SS".
*
*
* @param time the time in milliseconds
*/
public static String formatElapsedTime(long time) {
@@ -100,7 +101,7 @@ public class StringUtils {
/**
* Formats the elapsed time in the form "H:MM:SS".
*
*
* @param time the time in milliseconds
*/
public static String formatElapsedTimeWithHour(long time) {
@@ -136,7 +137,45 @@ public class StringUtils {
}
}
}
/**
* Gets the distance in an array of two strings. The first string is the
* distance. The second string is the unit.
*
* @param context the context
* @param distance the distance
* @param metricUnits true to use metric unit
*/
public static String[] getDistanceParts(Context context, double distance, boolean metricUnits) {
String[] result = new String[2];
if (Double.isNaN(distance) || Double.isInfinite(distance)) {
result[0] = context.getString(R.string.value_unknown);
result[1] = context.getString(metricUnits ? R.string.unit_meter : R.string.unit_feet);
return result;
}
int unitId;
if (metricUnits) {
if (distance > 500.0) {
distance *= UnitConversions.M_TO_KM;
unitId = R.string.unit_kilometer;
} else {
unitId = R.string.unit_meter;
}
} else {
if (distance * UnitConversions.M_TO_MI > 0.5) {
distance *= UnitConversions.M_TO_MI;
unitId = R.string.unit_mile;
} else {
distance *= UnitConversions.M_TO_FT;
unitId = R.string.unit_feet;
}
}
result[0] = String.format("%.2f", distance);
result[1] = context.getString(unitId);
return result;
}
/**
* Formats the speed.
*
@@ -171,11 +210,51 @@ public class StringUtils {
}
}
/**
* Gets the speed in an array of two strings. The first string is the
* speed. The second string is the unit.
*
* @param context the context
* @param speed the speed
* @param metricUnits true to use metric unit
* @param reportSpeed true to report speed
*/
public static String[] getSpeedParts(
Context context, double speed, boolean metricUnits, boolean reportSpeed) {
String[] result = new String[2];
int unitId;
if (metricUnits) {
unitId = reportSpeed ? R.string.unit_kilometer_per_hour : R.string.unit_minute_per_kilometer;
} else {
unitId = reportSpeed ? R.string.unit_mile_per_hour : R.string.unit_minute_per_mile;
}
result[1] = context.getString(unitId);
if (Double.isNaN(speed) || Double.isInfinite(speed)) {
result[0] = context.getString(R.string.value_unknown);
return result;
}
speed *= UnitConversions.MS_TO_KMH;
if (metricUnits) {
if (!reportSpeed) {
// convert from hours to minutes
speed = speed == 0 ? 0.0 : 60.0 / speed;
}
} else {
speed *= UnitConversions.KM_TO_MI;
if (!reportSpeed) {
// convert from hours to minutes
speed = speed == 0 ? 0.0 : 60.0 / speed;
}
}
result[0] = String.format("%.2f", speed);
return result;
}
/**
* Formats the given text as a XML CDATA element. This includes adding the
* starting and ending CDATA tags. Please notice that this may result in
* multiple consecutive CDATA tags.
*
*
* @param text the given text
*/
public static String formatCData(String text) {
@@ -185,7 +264,7 @@ public class StringUtils {
/**
* Gets the time, in milliseconds, from an XML date time string as defined at
* http://www.w3.org/TR/xmlschema-2/#dateTime
*
*
* @param xmlDateTime the XML date time string
*/
public static long getTime(String xmlDateTime) {
@@ -193,8 +272,9 @@ public class StringUtils {
ParsePosition position = new ParsePosition(0);
Date date = ISO_8601_BASE.parse(xmlDateTime, position);
if (date == null) {
throw new IllegalArgumentException("Invalid XML dateTime value: " + xmlDateTime
+ " (at position " + position.getErrorIndex() + ")"); }
throw new IllegalArgumentException("Invalid XML dateTime value: " + xmlDateTime
+ " (at position " + position.getErrorIndex() + ")");
}
// Parse the date time extras
Matcher matcher = ISO_8601_EXTRAS.matcher(xmlDateTime.substring(position.getIndex()));
@@ -246,7 +326,7 @@ public class StringUtils {
* Gets the time as an array of three integers. Index 0 contains the number of
* seconds, index 1 contains the number of minutes, and index 2 contains the
* number of hours.
*
*
* @param time the time in milliseconds
* @return an array of 3 elements.
*/
@@ -284,7 +364,6 @@ public class StringUtils {
return Html.fromHtml(context.getString(resId, args));
}
/**
* Gets the frequency display options.
*
@@ -299,8 +378,9 @@ public class StringUtils {
if (value == PreferencesUtils.FREQUENCY_OFF) {
options[i] = context.getString(R.string.value_off);
} else if (value < 0) {
options[i] = context.getString(metricUnits ? R.string.value_integer_kilometer
: R.string.value_integer_mile, Math.abs(value));
options[i] = context.getString(
metricUnits ? R.string.value_integer_kilometer : R.string.value_integer_mile,
Math.abs(value));
} else {
options[i] = context.getString(R.string.value_integer_minute, value);
}
@@ -27,15 +27,16 @@ import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.maps.mytracks.R;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.os.Bundle;
import android.support.v4.app.TaskStackBuilder;
import android.view.View;
import android.util.SparseBooleanArray;
import android.widget.RemoteViews;
/**
@@ -48,31 +49,57 @@ import android.widget.RemoteViews;
*/
public class TrackWidgetProvider extends AppWidgetProvider {
private static final int LARGE_HEIGHT = 110;
// Array of appwidget id to use large size
private static final SparseBooleanArray useLargeSize = new SparseBooleanArray();
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
|| context.getString(R.string.track_paused_broadcast_action).equals(action)
|| context.getString(R.string.track_resumed_broadcast_action).equals(action)
|| context.getString(R.string.track_started_broadcast_action).equals(action)
|| context.getString(R.string.track_stopped_broadcast_action).equals(action)
|| context.getString(R.string.track_update_broadcast_action).equals(action)) {
long trackId = intent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L);
update(context, trackId);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
new ComponentName(context, TrackWidgetProvider.class));
for (int appWidgetId : appWidgetIds) {
RemoteViews remoteViews = getRemoteViews(context, trackId, useLargeSize.get(appWidgetId));
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
}
@TargetApi(16)
@Override
public void onAppWidgetOptionsChanged(
Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
boolean large = newOptions == null
|| newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT) >= LARGE_HEIGHT;
useLargeSize.put(appWidgetId, large);
RemoteViews remoteViews = getRemoteViews(context, -1L, large);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
/**
* Updates the widget.
*
* @param context the context
* @param trackId the track id
* @param large true to use the large layout
*/
private void update(Context context, long trackId) {
private RemoteViews getRemoteViews(Context context, long trackId, boolean large) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
large ? R.layout.track_widget_large : R.layout.track_widget_small);
// Get the preferences
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
boolean recordingTrackPaused = PreferencesUtils.getBoolean(context,
R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
boolean metricUnits = PreferencesUtils.getBoolean(
@@ -83,30 +110,23 @@ public class TrackWidgetProvider extends AppWidgetProvider {
if (trackId == -1L) {
trackId = recordingTrackId;
}
if (trackId == -1L) {
trackId = PreferencesUtils.getLong(context, R.string.selected_track_id_key);
}
Track track = trackId != -1L ? myTracksProviderUtils.getTrack(trackId)
: myTracksProviderUtils.getLastTrack();
TripStatistics tripStatistics = track == null ? null : track.getTripStatistics();
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.track_widget);
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
updateStatisticsContainer(context, remoteViews, track);
updateTotalDistance(context, remoteViews, tripStatistics, metricUnits);
updateTotalTime(remoteViews, tripStatistics, isRecording, recordingTrackPaused);
updateAverageSpeed(context, remoteViews, tripStatistics, metricUnits);
updateMovingTime(context, remoteViews, tripStatistics);
updateTotalDistance(context, remoteViews, tripStatistics, metricUnits);
updateRecordButton(context, remoteViews, isRecording, recordingTrackPaused);
updateRecordStatus(context, remoteViews, isRecording, recordingTrackPaused);
updateStopButton(context, remoteViews, isRecording);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
new ComponentName(context, TrackWidgetProvider.class));
for (int appWidgetId : appWidgetIds) {
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
if (large) {
boolean reportSpeed = PreferencesUtils.getBoolean(
context, R.string.report_speed_key, PreferencesUtils.REPORT_SPEED_DEFAULT);
updateAverageMovingSpeed(context, remoteViews, tripStatistics, metricUnits, reportSpeed);
updateAverageSpeed(context, remoteViews, tripStatistics, metricUnits, reportSpeed);
updateRecordStatus(context, remoteViews, isRecording, recordingTrackPaused);
}
return remoteViews;
}
/**
@@ -130,6 +150,20 @@ public class TrackWidgetProvider extends AppWidgetProvider {
remoteViews.setOnClickPendingIntent(R.id.track_widget_statistics, pendingIntent);
}
/**
* Updates moving time.
*
* @param context the context
* @param remoteViews the remote views
* @param tripStatistics the trip statistics
*/
private void updateMovingTime(
Context context, RemoteViews remoteViews, TripStatistics tripStatistics) {
String movingTimeValue = tripStatistics == null ? context.getString(R.string.value_unknown)
: StringUtils.formatElapsedTime(tripStatistics.getMovingTime());
remoteViews.setTextViewText(R.id.track_widget_moving_time_value, movingTimeValue);
}
/**
* Updates total distance.
*
@@ -140,73 +174,10 @@ public class TrackWidgetProvider extends AppWidgetProvider {
*/
private void updateTotalDistance(Context context, RemoteViews remoteViews,
TripStatistics tripStatistics, boolean metricUnits) {
String totalDistanceValue = tripStatistics == null ? context.getString(R.string.value_unknown)
: StringUtils.formatDistance(context, tripStatistics.getTotalDistance(), metricUnits);
remoteViews.setTextViewText(R.id.track_widget_total_distance_value, totalDistanceValue);
}
/**
* Updates total time.
*
* @param remoteViews the remote views
* @param tripStatistics the trip statistics
* @param isRecording true if recording
* @param recordingTrackPaused true if recording track is paused
*/
private void updateTotalTime(RemoteViews remoteViews, TripStatistics tripStatistics,
boolean isRecording, boolean recordingTrackPaused) {
long totalTime;
if (tripStatistics == null) {
totalTime = 0L;
} else {
totalTime = tripStatistics.getTotalTime();
if (isRecording && !recordingTrackPaused) {
totalTime += System.currentTimeMillis() - tripStatistics.getStopTime();
}
}
remoteViews.setChronometer(R.id.track_widget_total_time_value,
SystemClock.elapsedRealtime() - totalTime, null, isRecording && !recordingTrackPaused);
}
/**
* Updates average speed.
*
* @param context the context
* @param remoteViews the remote views
* @param tripStatistics the trip statistics
* @param metricUnits true to use metric units
*/
private void updateAverageSpeed(Context context, RemoteViews remoteViews,
TripStatistics tripStatistics, boolean metricUnits) {
boolean reportSpeed = PreferencesUtils.getBoolean(
context, R.string.report_speed_key, PreferencesUtils.REPORT_SPEED_DEFAULT);
String averageSpeedLabel = context.getString(
reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace);
remoteViews.setTextViewText(R.id.track_widget_average_speed_label, averageSpeedLabel);
String averageSpeedValue = tripStatistics == null ? context.getString(R.string.value_unknown)
: StringUtils.formatSpeed(
context, tripStatistics.getAverageSpeed(), metricUnits, reportSpeed);
remoteViews.setTextViewText(R.id.track_widget_average_speed_value, averageSpeedValue);
}
/**
* Updates moving time.
*
* @param context the context
* @param remoteViews the remote views
* @param tripStatistics the trip statistics
*/
private void updateMovingTime(
Context context, RemoteViews remoteViews, TripStatistics tripStatistics) {
boolean showMovingTime = PreferencesUtils.getBoolean(context,
R.string.stats_show_moving_time_key, PreferencesUtils.STATS_SHOW_MOVING_TIME_DEFAULT);
remoteViews.setViewVisibility(
R.id.track_widget_moving_time_container, showMovingTime ? View.VISIBLE : View.GONE);
if (showMovingTime) {
String movingTimeValue = tripStatistics == null ? context.getString(R.string.value_unknown)
: StringUtils.formatElapsedTime(tripStatistics.getMovingTime());
remoteViews.setTextViewText(R.id.track_widget_moving_time_value, movingTimeValue);
}
double distance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance();
String[] distanceParts = StringUtils.getDistanceParts(context, distance, metricUnits);
remoteViews.setTextViewText(R.id.track_widget_total_distance_value, distanceParts[0]);
remoteViews.setTextViewText(R.id.track_widget_total_distance_unit, distanceParts[1]);
}
/**
@@ -235,6 +206,69 @@ public class TrackWidgetProvider extends AppWidgetProvider {
remoteViews.setOnClickPendingIntent(R.id.track_widget_record_button, pendingIntent);
}
/**
* Updates the stop button.
*
* @param context the context
* @param remoteViews the remote views
* @param isRecording true if recording
*/
private void updateStopButton(Context context, RemoteViews remoteViews, boolean isRecording) {
remoteViews.setImageViewResource(
R.id.track_widget_stop_button, isRecording ? R.drawable.btn_stop_1 : R.drawable.btn_stop_0);
remoteViews.setBoolean(R.id.track_widget_stop_button, "setEnabled", isRecording);
if (isRecording) {
Intent intent = new Intent(context, ControlRecordingService.class).setAction(
context.getString(R.string.track_action_end));
PendingIntent pendingIntent = PendingIntent.getService(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.track_widget_stop_button, pendingIntent);
}
}
/**
* Updates average moving speed.
*
* @param context the context
* @param remoteViews the remote views
* @param tripStatistics the trip statistics
* @param metricUnits true to use metric units
* @param reportSpeed true to report speed
*/
private void updateAverageMovingSpeed(Context context, RemoteViews remoteViews,
TripStatistics tripStatistics, boolean metricUnits, boolean reportSpeed) {
String averageMovingSpeedLabel = context.getString(
reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace);
remoteViews.setTextViewText(
R.id.track_widget_average_moving_speed_label, averageMovingSpeedLabel);
Double speed = tripStatistics == null ? Double.NaN : tripStatistics.getAverageMovingSpeed();
String[] speedParts = StringUtils.getSpeedParts(context, speed, metricUnits, reportSpeed);
remoteViews.setTextViewText(R.id.track_widget_average_moving_speed_value, speedParts[0]);
remoteViews.setTextViewText(R.id.track_widget_average_moving_speed_unit, speedParts[1]);
}
/**
* Updates average speed.
*
* @param context the context
* @param remoteViews the remote views
* @param tripStatistics the trip statistics
* @param metricUnits true to use metric units
* @param reportSpeed true to report speed
*/
private void updateAverageSpeed(Context context, RemoteViews remoteViews,
TripStatistics tripStatistics, boolean metricUnits, boolean reportSpeed) {
String averageSpeedLabel = context.getString(
reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace);
remoteViews.setTextViewText(R.id.track_widget_average_speed_label, averageSpeedLabel);
Double speed = tripStatistics == null ? Double.NaN : tripStatistics.getAverageSpeed();
String[] speedParts = StringUtils.getSpeedParts(context, speed, metricUnits, reportSpeed);
remoteViews.setTextViewText(R.id.track_widget_average_speed_value, speedParts[0]);
remoteViews.setTextViewText(R.id.track_widget_average_speed_unit, speedParts[1]);
}
/**
* Updates recording status.
*
@@ -259,24 +293,4 @@ public class TrackWidgetProvider extends AppWidgetProvider {
R.id.track_widget_record_status, context.getResources().getColor(colorId));
remoteViews.setTextViewText(R.id.track_widget_record_status, status);
}
/**
* Updates the stop button.
*
* @param context the context
* @param remoteViews the remote views
* @param isRecording true if recording
*/
private void updateStopButton(Context context, RemoteViews remoteViews, boolean isRecording) {
remoteViews.setImageViewResource(
R.id.track_widget_stop_button, isRecording ? R.drawable.btn_stop_1 : R.drawable.btn_stop_0);
remoteViews.setBoolean(R.id.track_widget_stop_button, "setEnabled", isRecording);
if (isRecording) {
Intent intent = new Intent(context, ControlRecordingService.class).setAction(
context.getString(R.string.track_action_end));
PendingIntent pendingIntent = PendingIntent.getService(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.track_widget_stop_button, pendingIntent);
}
}
}