App 2.35.0: the app takes on the Overview style's own colours

While the style shows its own palette (Sci-fi, Cartoon, Aviation, Nixie;
Retro and Terminal with "Original"), the navigation, buttons and titles
take it instead of the accent colour, e.g. turquoise for Retro
(StylePalette, style_palettes.xml). Blueprint and Mascot are removed; a
stored one opens Tiles. The navigation no longer saves view state, which
crashed a restore across the wide and narrow layouts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
2026-10-25 20:38:32 +01:00
co-authored by Claude Opus 5.5
parent c5f0d5dc9a
commit 921bab7170
24 changed files with 195 additions and 1834 deletions
@@ -64,12 +64,10 @@ public class MainActivity extends AppCompatActivity {
private FlowView flowView;
private SciFiView sciFiView;
private CartoonView cartoonView;
private BlueprintView blueprintView;
private OctagonView octagonView;
/** The styles built on {@link ClusterCanvasView}, fed together. */
private final java.util.List<ClusterCanvasView> canvasStyles = new java.util.ArrayList<>();
private TerminalView terminalView;
private MascotView mascotView;
/** The pane of each Overview style, by its {@link OverviewStyle} ordinal. */
private View[] stylePanes;
private View consumptionPane;
@@ -316,8 +314,10 @@ public class MainActivity extends AppCompatActivity {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
super.onCreate(savedInstanceState);
prefs = getSharedPreferences("abrp_prefs", MODE_PRIVATE);
// Before anything is inflated: every ?attr/evAccent… resolves against this overlay.
getTheme().applyStyle(AccentColor.fromPref(prefs.getString(AccentColor.PREF_KEY, null)).overlay, true);
// Before anything is inflated: every ?attr/evAccent… resolves against this overlay — the
// accent colour, or the Overview style's own palette while it shows that (StylePalette).
appliedOverlay = appOverlay();
getTheme().applyStyle(appliedOverlay, true);
setContentView(R.layout.activity_main);
@@ -338,21 +338,17 @@ public class MainActivity extends AppCompatActivity {
flowView = futuristicPane.findViewById(R.id.flow_view);
sciFiView = new SciFiView(this, null);
cartoonView = new CartoonView(this, null);
blueprintView = new BlueprintView(this, null);
octagonView = new OctagonView(this, null);
View sciFiPane = drawnPane(sciFiView), cartoonPane = drawnPane(cartoonView),
blueprintPane = drawnPane(blueprintView), mgPane = drawnPane(octagonView);
mgPane = drawnPane(octagonView);
terminalView = new TerminalView(this);
mascotView = new MascotView(this);
mascotView.setCharacter(MascotCharacter.fromPref(prefs.getString(MascotCharacter.PREF_KEY, null)));
java.util.Collections.addAll(canvasStyles, new MinimalView(this), terminalView,
new AviationView(this), new NixieView(this), new ChronographView(this), mascotView);
new AviationView(this), new NixieView(this), new ChronographView(this));
View[] canvasPanes = new View[canvasStyles.size()];
for (int i = 0; i < canvasPanes.length; i++) canvasPanes[i] = drawnPane(canvasStyles.get(i));
stylePanes = new View[] { vehiclePane, gaugesPane, cockpitPane, retroPane,
futuristicPane, sciFiPane, cartoonPane, blueprintPane, mgPane,
canvasPanes[0], canvasPanes[1], canvasPanes[2], canvasPanes[3], canvasPanes[4],
canvasPanes[5] };
futuristicPane, sciFiPane, cartoonPane, mgPane,
canvasPanes[0], canvasPanes[1], canvasPanes[2], canvasPanes[3], canvasPanes[4] };
// The Overview page holds every style; Settings → Overview style picks the one shown.
android.widget.FrameLayout overviewPage = new android.widget.FrameLayout(this);
overviewPage.setLayoutParams(new android.view.ViewGroup.LayoutParams(
@@ -365,7 +361,6 @@ public class MainActivity extends AppCompatActivity {
overviewPage.addView(futuristicPane);
overviewPage.addView(sciFiPane);
overviewPage.addView(cartoonPane);
overviewPage.addView(blueprintPane);
overviewPage.addView(mgPane);
for (View pane : canvasPanes) overviewPage.addView(pane);
consumptionPane = inflatePane(R.layout.pane_consumption);
@@ -1189,7 +1184,6 @@ public class MainActivity extends AppCompatActivity {
voiceKeySwitch.setOnCheckedChangeListener((btn, checked) ->
prefs.edit().putBoolean(UploadSettings.KEY_VOICE_KEY_OPENS, checked).apply());
bindTireUnit();
bindMascotCharacter();
bindDriveMode();
bindOverviewStyle();
bindAccentColor();
@@ -1294,7 +1288,7 @@ public class MainActivity extends AppCompatActivity {
/**
* The accent colour; a change recreates the activity so every view takes it. For a style
* with an original palette, "Original colours" comes first: it keeps the style in its own
* colours and leaves the app's accent as it is.
* colours, and the app takes them on too (StylePalette).
*/
private void bindAccentColor() {
OverviewStyle style = overviewStyle();
@@ -1307,17 +1301,10 @@ public class MainActivity extends AppCompatActivity {
int selected = originalColours(style) ? 0 : current.ordinal() + offset;
bindChoices(settingsPane.findViewById(R.id.accent_choices), labels, selected, position -> {
if (style.hasOriginal) prefs.edit().putBoolean(style.originalKey(), position == 0).apply();
if (position < offset) {
applyOverviewStyle();
return;
if (position >= offset) {
prefs.edit().putString(AccentColor.PREF_KEY, colors[position - offset].name()).apply();
}
AccentColor picked = colors[position - offset];
if (picked == current) {
applyOverviewStyle();
return;
}
prefs.edit().putString(AccentColor.PREF_KEY, picked.name()).apply();
recreate();
applyStyleOrRecreate();
});
applyAccentAvailability();
}
@@ -1332,7 +1319,6 @@ public class MainActivity extends AppCompatActivity {
prefs.edit().putString(PressureUnit.PREF_KEY, units[position].name()).apply());
}
/** Who sits in the Mascot style; the drop-down shows only while that style is chosen. */
private static final int[] DRIVE_MODE_IDS = { R.id.drive_mode_eco, R.id.drive_mode_normal,
R.id.drive_mode_sport, R.id.drive_mode_snow, R.id.drive_mode_custom };
private static final int[] DRIVE_MODE_LABELS = { R.string.drive_mode_eco, R.string.drive_mode_normal,
@@ -1443,17 +1429,6 @@ public class MainActivity extends AppCompatActivity {
}
}
private void bindMascotCharacter() {
MascotCharacter[] characters = MascotCharacter.values();
String[] labels = { getString(R.string.mascot_character_classic), getString(R.string.mascot_character_chibi),
getString(R.string.mascot_character_fox) };
int current = MascotCharacter.fromPref(prefs.getString(MascotCharacter.PREF_KEY, null)).ordinal();
bindChoices(settingsPane.findViewById(R.id.mascot_choices), labels, current, position -> {
prefs.edit().putString(MascotCharacter.PREF_KEY, characters[position].name()).apply();
mascotView.setCharacter(characters[position]);
});
}
/** The service reads these settings on every tick, so a change applies without a restart. */
private void bindCadenceControls() {
UploadSettings current = UploadSettings.from(prefs);
@@ -1712,6 +1687,24 @@ public class MainActivity extends AppCompatActivity {
return style;
}
/** The theme overlay applied in onCreate; a choice that changes it recreates the activity. */
private int appliedOverlay;
private int appOverlay() {
OverviewStyle style = overviewStyle();
return StylePalette.appOverlay(style, originalColours(style),
AccentColor.fromPref(prefs.getString(AccentColor.PREF_KEY, null)));
}
/**
* After a style or colour choice: the app's colours follow at once (the activity is
* recreated when they change, as for the accent colour), otherwise the Overview is redrawn.
*/
private void applyStyleOrRecreate() {
if (appOverlay() != appliedOverlay) recreate();
else applyOverviewStyle();
}
/** Whether a style with an original palette shows it (the default) or the accent colour. */
private boolean originalColours(OverviewStyle style) {
return style.hasOriginal && prefs.getBoolean(style.originalKey(), true);
@@ -1742,10 +1735,6 @@ public class MainActivity extends AppCompatActivity {
TextView note = settingsPane.findViewById(R.id.accent_note);
note.setVisibility(style.usesAccent ? View.GONE : View.VISIBLE);
note.setText(getString(R.string.accent_not_used, styleLabels()[style.ordinal()]));
// The wide layout keeps the Mascot field's place so the page does not jump.
View mascot = settingsPane.findViewById(R.id.mascot_field);
boolean wide = getResources().getConfiguration().screenWidthDp >= 1000;
mascot.setVisibility(style == OverviewStyle.MASCOT ? View.VISIBLE : wide ? View.INVISIBLE : View.GONE);
}
/** The drop-down's labels, by {@link OverviewStyle} ordinal. */
@@ -1754,10 +1743,10 @@ public class MainActivity extends AppCompatActivity {
getString(R.string.overview_style_cockpit), getString(R.string.overview_style_retro),
getString(R.string.overview_style_futuristic),
getString(R.string.overview_style_scifi), getString(R.string.overview_style_cartoon),
getString(R.string.overview_style_blueprint), getString(R.string.overview_style_mg),
getString(R.string.overview_style_mg),
getString(R.string.overview_style_minimal), getString(R.string.overview_style_terminal),
getString(R.string.overview_style_aviation), getString(R.string.overview_style_nixie),
getString(R.string.overview_style_chronograph), getString(R.string.overview_style_mascot) };
getString(R.string.overview_style_chronograph) };
}
/** The style drop-down; every style is fed on every reading, only the chosen one is shown. */
@@ -1770,7 +1759,7 @@ public class MainActivity extends AppCompatActivity {
bindChoices(field, styleLabels(), overviewStyle().ordinal(),
position -> {
prefs.edit().putString(PREF_OVERVIEW_STYLE, styles[position].name()).apply();
applyOverviewStyle();
applyStyleOrRecreate();
});
}
@@ -1827,7 +1816,6 @@ public class MainActivity extends AppCompatActivity {
flowView.setValues(v);
sciFiView.setValues(v);
cartoonView.setValues(v);
blueprintView.setValues(v);
octagonView.setValues(v);
for (ClusterCanvasView view : canvasStyles) view.setValues(v);
}