App 2.16.4: drop-downs that keep full screen

Back to drop-downs for upload frequency, tyre pressure unit and accent
colour, as Material exposed dropdown menus instead of Spinners. A
Spinner's list is a focusable window of its own without the
full-screen flags, so the car showed its bars while it was open; an
exposed dropdown's list leaves the focus with the activity, so the app
stays full screen. Styled like the other input fields, with full-height
rows. Replaces the buttons of 2.16.3.

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 20:11:25 +02:00
co-authored by Claude Opus 5.5
parent f614ab08be
commit 79bcfa05f6
14 changed files with 62 additions and 69 deletions
+2 -2
View File
@@ -34,8 +34,8 @@ android {
applicationId "com.stinnesbeck.nilsmg4"
minSdk 27
targetSdk 36
versionCode 87
versionName "2.16.3"
versionCode 88
versionName "2.16.4"
// Nothing about the server ships in the APK: its URL and ingest token are entered in
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
@@ -126,7 +126,7 @@ public class MainActivity extends AppCompatActivity {
/** Upload page: live telemetry switch and cadence. */
private SwitchMaterial liveTelemetrySwitch, boostSwitch, voiceKeySwitch, fullScreenSwitch;
private TextView steeringKeysText;
private com.google.android.material.chip.ChipGroup intervalChoices;
private com.google.android.material.textfield.MaterialAutoCompleteTextView intervalChoices;
private TextInputLayout lowSocLayout;
private TextInputEditText lowSocInput;
@@ -1126,28 +1126,18 @@ public class MainActivity extends AppCompatActivity {
}
/**
* A single choice as buttons on the page (choice_chip.xml), in place of a drop-down: a
* drop-down opens a window of its own that is not full screen, and the car's bars came back
* while it was open. Rebinding replaces the buttons, so it may be called again.
* A single choice as a drop-down (Widget.EV.Dropdown). An exposed dropdown menu rather than
* a Spinner: a Spinner's list is a focusable window of its own without the full-screen
* flags, and the car showed its bars while it was open; this list leaves the focus with
* the activity. setSimpleItems keeps every option listed (a plain adapter would filter the
* list down to the current text). Rebinding is safe.
*/
private void bindChoices(com.google.android.material.chip.ChipGroup group, String[] labels, int selected,
java.util.function.IntConsumer onPick) {
group.setOnCheckedStateChangeListener(null);
group.removeAllViews();
for (int i = 0; i < labels.length; i++) {
com.google.android.material.chip.Chip chip = (com.google.android.material.chip.Chip)
getLayoutInflater().inflate(R.layout.choice_chip, group, false);
chip.setId(View.generateViewId());
chip.setText(labels[i]);
chip.setTag(i);
group.addView(chip);
if (i == selected) chip.setChecked(true);
}
group.setOnCheckedStateChangeListener((g, checkedIds) -> {
if (checkedIds.isEmpty()) return;
View chosen = g.findViewById(checkedIds.get(0));
if (chosen != null) onPick.accept((Integer) chosen.getTag());
});
private void bindChoices(com.google.android.material.textfield.MaterialAutoCompleteTextView view,
String[] labels, int selected, java.util.function.IntConsumer onPick) {
view.setOnItemClickListener(null);
view.setSimpleItems(labels);
view.setText(labels[selected], false);
view.setOnItemClickListener((parent, item, position, id) -> onPick.accept(position));
}
/** The accent colour; a change recreates the activity so every view takes it. */
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="?attr/evAccentSurface" />
<item android:color="@color/ev_surface_raised" />
</selector>
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="?attr/evAccent" />
<item android:color="@color/ev_outline" />
</selector>
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="?attr/evAccent" />
<item android:color="@color/ev_text_primary" />
</selector>
@@ -27,7 +27,9 @@
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_service_timing" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/label_frequency" android:textAppearance="@style/Text.EV.Body" android:layout_marginTop="20dp" />
<com.google.android.material.chip.ChipGroup android:id="@+id/interval_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" app:singleSelection="true" app:selectionRequired="true" app:chipSpacingHorizontal="12dp" app:chipSpacingVertical="8dp" />
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.EV.Dropdown" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp">
<com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/interval_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:inputType="none" android:textSize="20sp" app:simpleItemLayout="@layout/dropdown_item" />
</com.google.android.material.textfield.TextInputLayout>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_frequency" android:textAppearance="@style/Text.EV.Secondary" android:layout_marginTop="12dp" />
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/boost_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_boost_low_soc" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
<com.google.android.material.textfield.TextInputLayout android:id="@+id/low_soc_layout" style="@style/Widget.EV.Input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="@string/label_low_soc_threshold">
@@ -9,9 +9,13 @@
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/voice_key_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_voice_key" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_voice_key" android:textAppearance="@style/Text.EV.Secondary" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/label_tire_unit" android:textAppearance="@style/Text.EV.Body" android:layout_marginTop="20dp" />
<com.google.android.material.chip.ChipGroup android:id="@+id/tire_unit_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" app:singleSelection="true" app:selectionRequired="true" app:chipSpacingHorizontal="12dp" app:chipSpacingVertical="8dp" />
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.EV.Dropdown" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp">
<com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/tire_unit_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:inputType="none" android:textSize="20sp" app:simpleItemLayout="@layout/dropdown_item" />
</com.google.android.material.textfield.TextInputLayout>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/label_accent" android:textAppearance="@style/Text.EV.Body" android:layout_marginTop="20dp" />
<com.google.android.material.chip.ChipGroup android:id="@+id/accent_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" app:singleSelection="true" app:selectionRequired="true" app:chipSpacingHorizontal="12dp" app:chipSpacingVertical="8dp" />
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.EV.Dropdown" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp">
<com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/accent_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:inputType="none" android:textSize="20sp" app:simpleItemLayout="@layout/dropdown_item" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_battery_settings_title" android:textAppearance="@style/Text.EV.Eyebrow" />
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- One option of an on-page choice (MainActivity.bindChoices). Chips rather than a drop-down:
a drop-down opens its own window, which is not full screen, so the car's bars came back
while it was open; and one tap is easier than two while driving. -->
<com.google.android.material.chip.Chip xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.EV.Choice"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- One row of a drop-down list (Widget.EV.Dropdown): a full touch target, body text size. -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/touch_target"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:textAppearance="@style/Text.EV.Body"
android:textColor="@color/ev_text_primary"
android:maxLines="1"
android:ellipsize="end" />
+3 -1
View File
@@ -24,7 +24,9 @@
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_service_timing" android:textAppearance="@style/Text.EV.Eyebrow" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/label_frequency" android:textAppearance="@style/Text.EV.Body" android:layout_marginTop="20dp" />
<com.google.android.material.chip.ChipGroup android:id="@+id/interval_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" app:singleSelection="true" app:selectionRequired="true" app:chipSpacingHorizontal="12dp" app:chipSpacingVertical="8dp" />
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.EV.Dropdown" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp">
<com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/interval_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:inputType="none" android:textSize="20sp" app:simpleItemLayout="@layout/dropdown_item" />
</com.google.android.material.textfield.TextInputLayout>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_frequency" android:textAppearance="@style/Text.EV.Secondary" android:layout_marginTop="12dp" />
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/boost_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_boost_low_soc" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
<com.google.android.material.textfield.TextInputLayout android:id="@+id/low_soc_layout" style="@style/Widget.EV.Input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:hint="@string/label_low_soc_threshold">
+6 -2
View File
@@ -8,9 +8,13 @@
<com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/voice_key_switch" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:text="@string/label_voice_key" android:textAppearance="@style/Text.EV.Body" android:paddingTop="8dp" android:paddingBottom="8dp" app:useMaterialThemeColors="true" app:thumbTint="@color/switch_thumb" app:trackTint="@color/switch_track" android:textColor="@color/ev_text_primary" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hint_voice_key" android:textAppearance="@style/Text.EV.Secondary" />
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/label_tire_unit" android:textAppearance="@style/Text.EV.Body" android:layout_marginTop="20dp" />
<com.google.android.material.chip.ChipGroup android:id="@+id/tire_unit_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" app:singleSelection="true" app:selectionRequired="true" app:chipSpacingHorizontal="12dp" app:chipSpacingVertical="8dp" />
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.EV.Dropdown" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp">
<com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/tire_unit_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:inputType="none" android:textSize="20sp" app:simpleItemLayout="@layout/dropdown_item" />
</com.google.android.material.textfield.TextInputLayout>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/label_accent" android:textAppearance="@style/Text.EV.Body" android:layout_marginTop="20dp" />
<com.google.android.material.chip.ChipGroup android:id="@+id/accent_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" app:singleSelection="true" app:selectionRequired="true" app:chipSpacingHorizontal="12dp" app:chipSpacingVertical="8dp" />
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.EV.Dropdown" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp">
<com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/accent_choices" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:inputType="none" android:textSize="20sp" app:simpleItemLayout="@layout/dropdown_item" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" android:background="@drawable/bg_glass" android:layout_marginTop="16dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/design_battery_settings_title" android:textAppearance="@style/Text.EV.Eyebrow" />
+13
View File
@@ -43,6 +43,19 @@
<item name="endIconTint">@color/ev_text_secondary</item>
<item name="helperTextTextAppearance">@style/Text.EV.Secondary</item>
</style>
<!-- A drop-down that keeps the app full screen: an exposed dropdown menu's list does not take
focus from the activity's window, unlike a Spinner's, so the car's bars stay hidden. -->
<style name="Widget.EV.Dropdown" parent="Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu">
<item name="boxBackgroundColor">@color/ev_background</item>
<item name="boxStrokeColor">@color/input_stroke</item>
<item name="boxStrokeWidth">1dp</item>
<item name="boxStrokeWidthFocused">2dp</item>
<item name="boxCornerRadiusTopStart">16dp</item>
<item name="boxCornerRadiusTopEnd">16dp</item>
<item name="boxCornerRadiusBottomStart">16dp</item>
<item name="boxCornerRadiusBottomEnd">16dp</item>
<item name="endIconTint">?attr/evAccent</item>
</style>
<style name="Text.EV.Eyebrow" parent="Text.EV.SectionHeader">
<item name="android:textSize">16sp</item>
<item name="android:textColor">?attr/evAccent</item>
-15
View File
@@ -97,19 +97,4 @@
<item name="cornerSize">18dp</item>
</style>
<!-- On-page single choice (choice_chip.xml): a full touch target, the accent when chosen. -->
<style name="Widget.EV.Choice" parent="Widget.Material3.Chip.Filter">
<item name="android:checkable">true</item>
<item name="checkedIconVisible">false</item>
<item name="chipMinHeight">@dimen/touch_target</item>
<item name="chipMinTouchTargetSize">@dimen/touch_target</item>
<item name="android:textSize">@dimen/text_body</item>
<item name="android:textColor">@color/choice_text</item>
<item name="chipBackgroundColor">@color/choice_background</item>
<item name="chipStrokeColor">@color/choice_stroke</item>
<item name="chipStrokeWidth">1dp</item>
<item name="chipStartPadding">16dp</item>
<item name="chipEndPadding">16dp</item>
<item name="ensureMinTouchTargetSize">false</item>
</style>
</resources>