App 2.12.1: no scroll bars; energy since start

The pages' scroll bars never faded on the car: a ScrollView shows its
bar on every layout, and the live values lay the page out every two
seconds. StableScrollView, the root of every page, now has none.

A new "Energy since start" tile, left of "Usage since start", shows the
net kWh taken from the pack since the trip began, recuperation counted
back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
2026-10-18 13:12:12 +02:00
co-authored by Claude Opus 5.5
parent d711e0cfda
commit 66fed48aae
9 changed files with 56 additions and 6 deletions
@@ -92,7 +92,8 @@ public class MainActivity extends AppCompatActivity {
vehCharging, vehHvac,
vehTireFl, vehTireFr, vehTireRl, vehTireRr,
vehRangeTrip, vehRangeTripNote, vehRangeAverage, vehRangeAverageNote,
vehUsageTrip, vehUsageTripNote, vehUsageAverage, vehUsageAverageNote;
vehUsageTrip, vehUsageTripNote, vehUsageAverage, vehUsageAverageNote,
vehEnergyTrip, vehEnergyTripNote;
/** Usable pack capacity for the range estimates; the car does not publish it. */
static final String USABLE_KWH_KEY = "usable_kwh";
@@ -1187,6 +1188,8 @@ public class MainActivity extends AppCompatActivity {
vehUsageTripNote = vehiclePane.findViewById(R.id.vehicle_usage_trip_note);
vehUsageAverage = vehiclePane.findViewById(R.id.vehicle_usage_average);
vehUsageAverageNote = vehiclePane.findViewById(R.id.vehicle_usage_average_note);
vehEnergyTrip = vehiclePane.findViewById(R.id.vehicle_energy_trip);
vehEnergyTripNote = vehiclePane.findViewById(R.id.vehicle_energy_trip_note);
}
private double usableKwh() {
@@ -1204,6 +1207,9 @@ public class MainActivity extends AppCompatActivity {
estimator.add(monotonicMs, s.getBatteryPowerKw(), s.getSpeedKmh());
Double remaining = RangeEstimator.remainingKwh(s.getSocPercent(), usableKwh());
RangeEstimator.Estimate trip = estimator.sinceStart(remaining);
Double energy = estimator.energySinceStart();
vehEnergyTrip.setText(energy == null ? "—" : getString(R.string.energy_kwh, energy));
vehEnergyTripNote.setText(energy == null ? R.string.energy_trip_waiting : R.string.energy_trip_note);
showEstimate(vehRangeTrip, vehRangeTripNote, vehUsageTrip, vehUsageTripNote, trip,
trip == null ? "" : getString(R.string.usage_over_distance, trip.distanceKm),
R.string.range_trip_waiting);
@@ -110,6 +110,11 @@ final class RangeEstimator {
tripLast = s;
}
/** Net energy taken from the pack since start, in kWh; null before the trip's first sample. */
synchronized Double energySinceStart() {
return tripLast == null ? null : tripEnergyKwh;
}
/** Range at the consumption since start; null until the trip has some distance behind it. */
synchronized Estimate sinceStart(Double remainingKwh) {
if (remainingKwh == null || tripDistanceKm < MIN_DISTANCE_KM) return null;
@@ -16,18 +16,28 @@ import android.widget.ScrollView;
* Here only scrolling that is not part of a layout counts as the driver's position, and every
* layout restores it. ScrollView.scrollTo clamps against the real content height, so a
* position that no longer exists still ends at the bottom rather than past it.
*
* No scroll bar: a ScrollView shows its bar on every layout, and the live values lay the page
* out every two seconds, so on the car it never faded. The pages scroll by touch.
*/
public class StableScrollView extends ScrollView {
private int wantedScrollY;
private boolean inLayout;
public StableScrollView(Context context) { super(context); }
public StableScrollView(Context context) {
super(context);
setVerticalScrollBarEnabled(false);
}
public StableScrollView(Context context, AttributeSet attrs) { super(context, attrs); }
public StableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
setVerticalScrollBarEnabled(false);
}
public StableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setVerticalScrollBarEnabled(false);
}
@Override