forked from upstream-mirrors/OpenTracks
Voice announcements and Interval: add sub km/miles options.
Fixes #1195.
This commit is contained in:
@@ -28,6 +28,6 @@ public class AnnouncementsSettingsFragment extends PreferenceFragmentCompat {
|
|||||||
voiceFrequency.setEntries(PreferencesUtils.getVoiceAnnouncementFrequencyEntries());
|
voiceFrequency.setEntries(PreferencesUtils.getVoiceAnnouncementFrequencyEntries());
|
||||||
|
|
||||||
ListPreference voiceDistance = findPreference(getString(R.string.voice_announcement_distance_key));
|
ListPreference voiceDistance = findPreference(getString(R.string.voice_announcement_distance_key));
|
||||||
voiceDistance.setEntries(PreferencesUtils.getVoiceAnnouncementDistanceEntries());
|
voiceDistance.setEntries(PreferencesUtils.getVoiceAnnouncementDistanceEntries(getContext()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import de.dennisguse.opentracks.data.models.UnitConversions;
|
|||||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
import de.dennisguse.opentracks.ui.customRecordingLayout.CsvLayoutUtils;
|
import de.dennisguse.opentracks.ui.customRecordingLayout.CsvLayoutUtils;
|
||||||
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
||||||
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,7 +304,8 @@ public class PreferencesUtils {
|
|||||||
/**
|
/**
|
||||||
* @return Result depends on isMetricUnits
|
* @return Result depends on isMetricUnits
|
||||||
*/
|
*/
|
||||||
static String[] getVoiceAnnouncementDistanceEntries() {
|
@Deprecated //TODO Context should not be used here; requires refactoring of StringUtils.
|
||||||
|
static String[] getVoiceAnnouncementDistanceEntries(Context context) {
|
||||||
String[] values = resources.getStringArray(R.array.voice_announcement_distance_values);
|
String[] values = resources.getStringArray(R.array.voice_announcement_distance_values);
|
||||||
String[] options = new String[values.length];
|
String[] options = new String[values.length];
|
||||||
boolean metricUnits = isMetricUnits();
|
boolean metricUnits = isMetricUnits();
|
||||||
@@ -311,8 +313,8 @@ public class PreferencesUtils {
|
|||||||
if (resources.getString(R.string.announcement_off).equals(values[i])) {
|
if (resources.getString(R.string.announcement_off).equals(values[i])) {
|
||||||
options[i] = resources.getString(R.string.value_off);
|
options[i] = resources.getString(R.string.value_off);
|
||||||
} else {
|
} else {
|
||||||
int value = Integer.parseInt(values[i]);
|
Distance distance = Distance.one(metricUnits).multipliedBy(Double.parseDouble(values[i]));
|
||||||
options[i] = resources.getString(metricUnits ? R.string.value_integer_kilometer : R.string.value_integer_mile, value);
|
options[i] = StringUtils.formatDistance(context, distance, metricUnits, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
|||||||
|
|
||||||
public void update(Track.Id trackId, boolean metricUnits, @Nullable IntervalOption interval) {
|
public void update(Track.Id trackId, boolean metricUnits, @Nullable IntervalOption interval) {
|
||||||
if (interval == null) {
|
if (interval == null) {
|
||||||
interval = IntervalOption.OPTION_1;
|
interval = IntervalOption.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTrackPointId = null;
|
lastTrackPointId = null;
|
||||||
@@ -119,6 +119,8 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
|||||||
* Intervals length this view model support.
|
* Intervals length this view model support.
|
||||||
*/
|
*/
|
||||||
public enum IntervalOption {
|
public enum IntervalOption {
|
||||||
|
OPTION_0_1(0.1f),
|
||||||
|
OPTION_0_5(0.5f),
|
||||||
OPTION_1(1),
|
OPTION_1(1),
|
||||||
OPTION_2(2),
|
OPTION_2(2),
|
||||||
OPTION_3(3),
|
OPTION_3(3),
|
||||||
@@ -128,9 +130,11 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
|||||||
OPTION_20(20),
|
OPTION_20(20),
|
||||||
OPTION_50(50);
|
OPTION_50(50);
|
||||||
|
|
||||||
private final int multiplier;
|
static IntervalOption DEFAULT = OPTION_1;
|
||||||
|
|
||||||
IntervalOption(int multiplier) {
|
private final double multiplier;
|
||||||
|
|
||||||
|
IntervalOption(double multiplier) {
|
||||||
this.multiplier = multiplier;
|
this.multiplier = multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,13 +144,12 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
|||||||
.multipliedBy(multiplier);
|
.multipliedBy(multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getMultiplier() {
|
||||||
|
return multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean sameMultiplier(IntervalOption intervalOption) {
|
public boolean sameMultiplier(IntervalOption intervalOption) {
|
||||||
return intervalOption != null && this.multiplier == intervalOption.multiplier;
|
return intervalOption != null && this.multiplier == intervalOption.multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "" + multiplier; //TODO Somehow IntervalsFragment relies on a parsable Integer.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
|
|||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
|
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fragment to display the intervals from recorded track.
|
* A fragment to display the intervals from recorded track.
|
||||||
@@ -95,6 +96,7 @@ public class IntervalsFragment extends Fragment {
|
|||||||
return viewBinding.getRoot();
|
return viewBinding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated //TODO This method must be re-implemented.
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
@@ -109,11 +111,10 @@ public class IntervalsFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||||
TextView v = (TextView) super.getView(position, convertView, parent);
|
TextView v = (TextView) super.getView(position, convertView, parent);
|
||||||
if (metricUnits) {
|
|
||||||
v.setText(getContext().getString(R.string.value_integer_kilometer, Integer.parseInt(v.getText().toString())));
|
IntervalStatisticsModel.IntervalOption option = getItem(position);
|
||||||
} else {
|
String stringValue = StringUtils.formatDistance(getContext(), option.getDistance(metricUnits), metricUnits, 0);
|
||||||
v.setText(getContext().getString(R.string.value_integer_mile, Integer.parseInt(v.getText().toString())));
|
v.setText(stringValue);
|
||||||
}
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,12 +125,19 @@ public class IntervalsFragment extends Fragment {
|
|||||||
};
|
};
|
||||||
|
|
||||||
viewBinding.intervalsDropdown.setAdapter(intervalsAdapter);
|
viewBinding.intervalsDropdown.setAdapter(intervalsAdapter);
|
||||||
viewBinding.intervalsDropdown.setOnItemClickListener((parent, view1, position, id) -> updateIntervals(metricUnits, IntervalStatisticsModel.IntervalOption.values()[position]));
|
viewBinding.intervalsDropdown.setOnItemClickListener((parent, view1, position, id) -> {
|
||||||
|
updateIntervals(metricUnits, IntervalStatisticsModel.IntervalOption.values()[position]);
|
||||||
|
|
||||||
viewBinding.intervalsDropdown.setText(
|
//TODO This duplicates the intervalAdapter code
|
||||||
getContext().getString(R.string.value_integer_kilometer, Integer.parseInt(selectedInterval != null ? selectedInterval.toString() : IntervalStatisticsModel.IntervalOption.values()[0].toString())),
|
IntervalStatisticsModel.IntervalOption option = selectedInterval != null ? selectedInterval : IntervalStatisticsModel.IntervalOption.DEFAULT;
|
||||||
false
|
String stringValue = StringUtils.formatDistance(getContext(), option.getDistance(metricUnits), metricUnits, 0);
|
||||||
);
|
viewBinding.intervalsDropdown.setText(stringValue, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO This duplicates the intervalAdapter code
|
||||||
|
IntervalStatisticsModel.IntervalOption option = selectedInterval != null ? selectedInterval : IntervalStatisticsModel.IntervalOption.DEFAULT;
|
||||||
|
String stringValue = StringUtils.formatDistance(getContext(), option.getDistance(metricUnits), metricUnits, 0);
|
||||||
|
viewBinding.intervalsDropdown.setText(stringValue, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -136,11 +136,15 @@ public class StringUtils {
|
|||||||
* @param metricUnits true to use metric units. False to use imperial units
|
* @param metricUnits true to use metric units. False to use imperial units
|
||||||
*/
|
*/
|
||||||
public static String formatDistance(Context context, Distance distance, boolean metricUnits) {
|
public static String formatDistance(Context context, Distance distance, boolean metricUnits) {
|
||||||
|
return formatDistance(context, distance, metricUnits, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatDistance(Context context, Distance distance, boolean metricUnits, int decimalCount) {
|
||||||
if (distance.isInvalid()) {
|
if (distance.isInvalid()) {
|
||||||
return context.getString(R.string.value_unknown);
|
return context.getString(R.string.value_unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<String, String> distanceParts = getDistanceParts(context, distance, metricUnits);
|
Pair<String, String> distanceParts = getDistanceParts(context, distance, metricUnits, decimalCount);
|
||||||
|
|
||||||
return context.getString(R.string.distance_with_unit, distanceParts.first, distanceParts.second);
|
return context.getString(R.string.distance_with_unit, distanceParts.first, distanceParts.second);
|
||||||
}
|
}
|
||||||
@@ -196,21 +200,25 @@ public class StringUtils {
|
|||||||
* @return the formatted distance (or null) and it's unit as {@link Pair}
|
* @return the formatted distance (or null) and it's unit as {@link Pair}
|
||||||
*/
|
*/
|
||||||
public static Pair<String, String> getDistanceParts(Context context, Distance distance, boolean metricUnits) {
|
public static Pair<String, String> getDistanceParts(Context context, Distance distance, boolean metricUnits) {
|
||||||
|
return getDistanceParts(context, distance, metricUnits, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<String, String> getDistanceParts(Context context, Distance distance, boolean metricUnits, int decimalCount) {
|
||||||
if (distance.isInvalid()) {
|
if (distance.isInvalid()) {
|
||||||
return new Pair<>(null, context.getString(metricUnits ? R.string.unit_meter : R.string.unit_feet));
|
return new Pair<>(null, context.getString(metricUnits ? R.string.unit_meter : R.string.unit_feet));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metricUnits) {
|
if (metricUnits) {
|
||||||
if (distance.greaterThan(Distance.of(500))) {
|
if (distance.greaterThan(Distance.of(500))) {
|
||||||
return new Pair<>(formatDecimal(distance.toKM()), context.getString(R.string.unit_kilometer));
|
return new Pair<>(formatDecimal(distance.toKM(), decimalCount), context.getString(R.string.unit_kilometer));
|
||||||
} else {
|
} else {
|
||||||
return new Pair<>(formatDecimal(distance.toM()), context.getString(R.string.unit_meter));
|
return new Pair<>(formatDecimal(distance.toM(), decimalCount), context.getString(R.string.unit_meter));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (distance.greaterThan(Distance.ofMile(0.5))) {
|
if (distance.greaterThan(Distance.ofMile(0.5))) {
|
||||||
return new Pair<>(formatDecimal(distance.toMI()), context.getString(R.string.unit_mile));
|
return new Pair<>(formatDecimal(distance.toMI(), decimalCount), context.getString(R.string.unit_mile));
|
||||||
} else {
|
} else {
|
||||||
return new Pair<>(formatDecimal(distance.toFT()), context.getString(R.string.unit_feet));
|
return new Pair<>(formatDecimal(distance.toFT(), decimalCount), context.getString(R.string.unit_feet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,6 +265,9 @@
|
|||||||
<string name="voice_announcement_distance_default" translatable="false">@string/announcement_off</string>
|
<string name="voice_announcement_distance_default" translatable="false">@string/announcement_off</string>
|
||||||
<string-array name="voice_announcement_distance_values">
|
<string-array name="voice_announcement_distance_values">
|
||||||
<item>@string/voice_announcement_distance_default</item> <!-- km/miles -->
|
<item>@string/voice_announcement_distance_default</item> <!-- km/miles -->
|
||||||
|
<item>0.1</item>
|
||||||
|
<item>0.2</item>
|
||||||
|
<item>0.5</item>
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
<item>5</item>
|
<item>5</item>
|
||||||
<item>10</item>
|
<item>10</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user