App 2.21.0: Overview style Dashboard, an instrument cluster
Power, speed and battery as gauges and a strip of gear, climate, clock, usage and battery; Settings picks Tiles or Dashboard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
@@ -66,6 +66,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
private View serverPane;
|
||||
private View logPane;
|
||||
private View vehiclePane;
|
||||
private View dashboardPane;
|
||||
private View consumptionPane;
|
||||
private View chargingPane;
|
||||
/** Display, battery, charging price and Wi-Fi. */
|
||||
@@ -242,15 +243,24 @@ public class MainActivity extends AppCompatActivity {
|
||||
servicePane = inflatePane(R.layout.pane_service);
|
||||
serverPane = inflatePane(R.layout.pane_server);
|
||||
vehiclePane = inflatePane(R.layout.pane_vehicle);
|
||||
dashboardPane = inflatePane(R.layout.pane_dashboard);
|
||||
// The Overview page holds both styles; Settings → Overview style picks the one shown.
|
||||
android.widget.FrameLayout overviewPage = new android.widget.FrameLayout(this);
|
||||
overviewPage.setLayoutParams(new android.view.ViewGroup.LayoutParams(
|
||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
overviewPage.addView(vehiclePane);
|
||||
overviewPage.addView(dashboardPane);
|
||||
consumptionPane = inflatePane(R.layout.pane_consumption);
|
||||
chargingPane = inflatePane(R.layout.pane_charging);
|
||||
settingsPane = inflatePane(R.layout.pane_settings);
|
||||
logPane = inflatePane(R.layout.pane_log);
|
||||
panes = new View[] { vehiclePane, consumptionPane, chargingPane, servicePane, serverPane,
|
||||
panes = new View[] { overviewPage, consumptionPane, chargingPane, servicePane, serverPane,
|
||||
settingsPane, logPane };
|
||||
|
||||
UpdateLog.noteVersion(this, BuildConfig.VERSION_NAME);
|
||||
bindVehiclePane();
|
||||
bindDashboard();
|
||||
bindConsumptionPane();
|
||||
bindChargingPane();
|
||||
bindServerPane();
|
||||
@@ -1053,6 +1063,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
voiceKeySwitch.setOnCheckedChangeListener((btn, checked) ->
|
||||
prefs.edit().putBoolean(UploadSettings.KEY_VOICE_KEY_OPENS, checked).apply());
|
||||
bindTireUnit();
|
||||
bindOverviewStyle();
|
||||
bindAccentColor();
|
||||
fullScreenSwitch = settingsPane.findViewById(R.id.full_screen_switch);
|
||||
fullScreenSwitch.setChecked(UploadSettings.fullScreen(prefs));
|
||||
@@ -1292,9 +1303,12 @@ public class MainActivity extends AppCompatActivity {
|
||||
showEstimate(vehRangeTrip, vehRangeTripNote, vehUsageTrip, vehUsageTripNote, trip,
|
||||
trip == null ? "" : getString(R.string.usage_over_distance, trip.distanceKm),
|
||||
R.string.range_trip_waiting);
|
||||
RangeEstimator.Estimate average = estimator.average(remaining, monotonicMs);
|
||||
showEstimate(vehRangeAverage, vehRangeAverageNote, vehUsageAverage, vehUsageAverageNote,
|
||||
estimator.average(remaining, monotonicMs), getString(R.string.usage_last_5_min),
|
||||
R.string.range_waiting);
|
||||
average, getString(R.string.usage_last_5_min), R.string.range_waiting);
|
||||
dashTripKm = trip == null ? null : trip.distanceKm;
|
||||
if (dashUsage != null) dashUsage.setText(average == null ? "—"
|
||||
: String.format(java.util.Locale.US, "%.1f kWh/100 km", average.kwhPer100Km));
|
||||
}
|
||||
|
||||
private void showEstimate(TextView range, TextView rangeNote, TextView usage, TextView usageNote,
|
||||
@@ -1404,6 +1418,73 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Dashboard (Overview style) ----------
|
||||
|
||||
static final String PREF_OVERVIEW_STYLE = "overview_style";
|
||||
private GaugeView dashPower, dashSpeed, dashBattery;
|
||||
private BatteryBarView dashBatteryBar;
|
||||
private TextView dashGear, dashClimate, dashUsage, dashBatteryText;
|
||||
/** Kilometres since start, from the range estimator; null until it has a distance. */
|
||||
private Double dashTripKm;
|
||||
|
||||
private boolean dashboardStyle() {
|
||||
return "DASHBOARD".equals(prefs.getString(PREF_OVERVIEW_STYLE, "TILES"));
|
||||
}
|
||||
|
||||
private void applyOverviewStyle() {
|
||||
boolean dash = dashboardStyle();
|
||||
dashboardPane.setVisibility(dash ? View.VISIBLE : View.GONE);
|
||||
vehiclePane.setVisibility(dash ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
/** Tiles (the cards) or Dashboard (gauges); both are fed on every reading. */
|
||||
private void bindOverviewStyle() {
|
||||
String[] labels = { getString(R.string.overview_style_tiles), getString(R.string.overview_style_dashboard) };
|
||||
bindChoices(settingsPane.findViewById(R.id.overview_style_choices), labels, dashboardStyle() ? 1 : 0,
|
||||
position -> {
|
||||
prefs.edit().putString(PREF_OVERVIEW_STYLE, position == 1 ? "DASHBOARD" : "TILES").apply();
|
||||
applyOverviewStyle();
|
||||
});
|
||||
}
|
||||
|
||||
private void bindDashboard() {
|
||||
dashPower = dashboardPane.findViewById(R.id.dash_power);
|
||||
dashSpeed = dashboardPane.findViewById(R.id.dash_speed);
|
||||
dashBattery = dashboardPane.findViewById(R.id.dash_battery);
|
||||
dashBatteryBar = dashboardPane.findViewById(R.id.dash_battery_bar);
|
||||
dashGear = dashboardPane.findViewById(R.id.dash_gear);
|
||||
dashClimate = dashboardPane.findViewById(R.id.dash_climate);
|
||||
dashUsage = dashboardPane.findViewById(R.id.dash_usage);
|
||||
dashBatteryText = dashboardPane.findViewById(R.id.dash_battery_text);
|
||||
dashPower.configure(-50f, 150f, 50f, 5, getString(R.string.dash_unit_kw));
|
||||
dashSpeed.configure(0f, 180f, 20f, 4, getString(R.string.dash_unit_kmh));
|
||||
dashBattery.configure(0f, 100f, 25f, 5, getString(R.string.dash_unit_battery));
|
||||
dashBattery.setEndLabels("E", "F");
|
||||
dashBattery.setWarnBelow(20f);
|
||||
applyOverviewStyle();
|
||||
}
|
||||
|
||||
/** The gauges and the strip; every value null-safe ("—", no needle). */
|
||||
private void showDashboard(EnergySnapshot s) {
|
||||
if (dashPower == null) return;
|
||||
Float power = s.getBatteryPowerKw();
|
||||
dashPower.setValue(power, power == null ? null : String.format(java.util.Locale.US, "%.1f", power), null);
|
||||
Float speed = s.getSpeedKmh();
|
||||
String total = getString(R.string.dash_total, fmt(s.getOdometerKm(), "%,.0f km"));
|
||||
String trip = getString(R.string.dash_trip, dashTripKm == null ? "—"
|
||||
: String.format(java.util.Locale.US, "%.1f km", dashTripKm));
|
||||
dashSpeed.setValue(speed, speed == null ? null : String.format(java.util.Locale.US, "%.0f", speed),
|
||||
total + "\n" + trip);
|
||||
Float soc = s.getSocPercent();
|
||||
dashBattery.setValue(soc, soc == null ? null : String.format(java.util.Locale.US, "%.0f %%", soc),
|
||||
fmt(s.getRangeKm(), "%.0f km"));
|
||||
dashBatteryBar.setSoc(soc);
|
||||
dashBatteryText.setText(fmt(soc, "%.0f %%"));
|
||||
Boolean parked = s.getParked();
|
||||
dashGear.setText(parked == null ? "—" : parked ? "P" : "D");
|
||||
dashClimate.setText(fmt(s.getClimate().getDriverTargetCelsius(), "%.0f °C"));
|
||||
}
|
||||
|
||||
private void showVehicle(EnergySnapshot s) {
|
||||
try {
|
||||
vehSoc.setText(fmt(s.getSocPercent(), "%.0f %%"));
|
||||
@@ -1422,6 +1503,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
vehTireFr.setText(unit.format(s.getTirePressures().getFrontRightKpa()));
|
||||
vehTireRl.setText(unit.format(s.getTirePressures().getRearLeftKpa()));
|
||||
vehTireRr.setText(unit.format(s.getTirePressures().getRearRightKpa()));
|
||||
showDashboard(s);
|
||||
} catch (Throwable ignored) {
|
||||
// Leave the last good reading on screen.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user