feat(popup): Redesign connection popup with Apple-inspired layout

Large centered device graphics (64dp), vertically stacked battery info,
adaptive width, rounded card with tonal close button.
This commit is contained in:
darken
2026-02-21 19:10:56 +01:00
committed by Matthias Urhahn
parent 9785b5ea7f
commit 8405406d22
6 changed files with 233 additions and 204 deletions
@@ -5,171 +5,184 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/pod_icon"
style="@style/PodInfoItemIcon.Popup"
android:src="@drawable/devic_earbuds_generic_both"
app:layout_constraintBottom_toBottomOf="@id/pod_label"
app:layout_constraintEnd_toStartOf="@id/pod_label"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/pod_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/pod_label"
style="@style/TextAppearance.Material3.BodyLarge"
android:layout_width="0dp"
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
android:ellipsize="end"
android:gravity="center"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toStartOf="@id/signal"
app:layout_constraintStart_toEndOf="@id/pod_icon"
android:maxLines="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="AirPods Pro" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/signal"
style="@style/TextAppearance.Material3.TitleSmall"
style="@style/TextAppearance.Material3.LabelMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableEnd="@drawable/ic_baseline_signal_cellular_alt_24"
android:gravity="center"
android:minWidth="44dp"
app:layout_constraintBottom_toBottomOf="@+id/pod_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/pod_label"
tools:text="-90%" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@id/pod_left_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toStartOf="@id/pod_case_container"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintEnd_toStartOf="@+id/signal_icon"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/pod_label">
app:layout_constraintTop_toBottomOf="@id/pod_label"
tools:text="29%" />
<ImageView
android:id="@+id/pod_left_icon"
style="@style/PodInfoItemIcon.Popup"
android:layout_gravity="center"
android:src="@drawable/devic_airpods_gen1_left"
app:layout_constraintBottom_toBottomOf="@id/pod_left_battery_label"
app:layout_constraintEnd_toStartOf="@id/pod_left_battery_icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/pod_left_battery_label" />
<ImageView
android:id="@id/pod_left_battery_icon"
style="@style/PodInfoItemIcon.Popup"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintBottom_toBottomOf="@id/pod_left_battery_label"
app:layout_constraintEnd_toStartOf="@id/pod_left_battery_label"
app:layout_constraintStart_toEndOf="@id/pod_left_icon"
app:layout_constraintTop_toTopOf="@id/pod_left_battery_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/pod_left_battery_label"
style="@style/TextAppearance.Material3.BodyLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/pod_left_battery_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="100%" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pod_case_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toStartOf="@id/pod_right_container"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toEndOf="@id/pod_left_container"
app:layout_constraintTop_toBottomOf="@id/pod_label">
<ImageView
android:id="@+id/pod_case_icon"
style="@style/PodInfoItemIcon.Popup"
android:layout_gravity="center"
android:src="@drawable/devic_airpods_gen1_case"
app:layout_constraintBottom_toBottomOf="@id/pod_case_battery_label"
app:layout_constraintEnd_toStartOf="@id/pod_case_battery_icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/pod_case_battery_label" />
<ImageView
android:id="@id/pod_case_battery_icon"
style="@style/PodInfoItemIcon.Popup"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintBottom_toBottomOf="@id/pod_case_battery_label"
app:layout_constraintEnd_toStartOf="@id/pod_case_battery_label"
app:layout_constraintStart_toEndOf="@id/pod_case_icon"
app:layout_constraintTop_toTopOf="@id/pod_case_battery_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/pod_case_battery_label"
style="@style/TextAppearance.Material3.BodyLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/pod_case_battery_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="100%" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@id/pod_right_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
<ImageView
android:id="@+id/signal_icon"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginStart="3dp"
android:src="@drawable/ic_baseline_signal_cellular_alt_24"
app:layout_constraintBottom_toBottomOf="@id/signal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toEndOf="@id/pod_case_container"
app:layout_constraintTop_toBottomOf="@id/pod_label">
app:layout_constraintStart_toEndOf="@id/signal"
app:layout_constraintTop_toTopOf="@id/signal" />
<ImageView
android:id="@+id/pod_right_icon"
style="@style/PodInfoItemIcon.Popup"
android:layout_gravity="center"
android:src="@drawable/devic_airpods_gen1_right"
app:layout_constraintBottom_toBottomOf="@id/pod_right_battery_label"
app:layout_constraintEnd_toStartOf="@id/pod_right_battery_icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/pod_right_battery_label" />
<!-- Pod columns container with LTR direction to prevent RTL mirroring physical L/R -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pods_columns_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layoutDirection="ltr"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/signal">
<ImageView
android:id="@id/pod_right_battery_icon"
style="@style/PodInfoItemIcon.Popup"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintBottom_toBottomOf="@id/pod_right_battery_label"
app:layout_constraintEnd_toStartOf="@id/pod_right_battery_label"
app:layout_constraintStart_toEndOf="@id/pod_right_icon"
app:layout_constraintTop_toTopOf="@id/pod_right_battery_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/pod_right_battery_label"
style="@style/TextAppearance.Material3.BodyLarge"
android:layout_width="wrap_content"
<!-- LEFT POD column -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pod_left_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="@+id/pod_case_container"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/pod_left_icon"
style="@style/PodInfoItemIcon.Popup.Large"
android:src="@drawable/devic_airpods_gen1_left"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/pod_left_battery_icon"
style="@style/PodInfoItemIcon.Popup"
android:layout_marginTop="8dp"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintEnd_toStartOf="@id/pod_left_battery_label"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/pod_left_icon" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/pod_left_battery_label"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="@id/pod_left_battery_icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/pod_left_battery_icon"
app:layout_constraintTop_toTopOf="@id/pod_left_battery_icon"
tools:text="100%" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- CASE column -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pod_case_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="@+id/pod_right_container"
app:layout_constraintStart_toEndOf="@id/pod_left_container"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/pod_case_icon"
style="@style/PodInfoItemIcon.Popup.Large"
android:src="@drawable/devic_airpods_gen1_case"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/pod_case_battery_icon"
style="@style/PodInfoItemIcon.Popup"
android:layout_marginTop="8dp"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintEnd_toStartOf="@id/pod_case_battery_label"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/pod_case_icon" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/pod_case_battery_label"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="@id/pod_case_battery_icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/pod_case_battery_icon"
app:layout_constraintTop_toTopOf="@id/pod_case_battery_icon"
tools:text="100%" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- RIGHT POD column -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pod_right_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/pod_right_battery_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="100%" />
app:layout_constraintStart_toEndOf="@id/pod_case_container"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/pod_right_icon"
style="@style/PodInfoItemIcon.Popup.Large"
android:src="@drawable/devic_airpods_gen1_right"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/pod_right_battery_icon"
style="@style/PodInfoItemIcon.Popup"
android:layout_marginTop="8dp"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintEnd_toStartOf="@id/pod_right_battery_label"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/pod_right_icon" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/pod_right_battery_label"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="@id/pod_right_battery_icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/pod_right_battery_icon"
app:layout_constraintTop_toTopOf="@id/pod_right_battery_icon"
tools:text="100%" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -5,75 +5,84 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/headphones_icon"
style="@style/PodInfoItemIcon.Popup"
android:src="@drawable/devic_earbuds_generic_both"
app:layout_constraintBottom_toBottomOf="@id/headphones_label"
app:layout_constraintEnd_toStartOf="@id/headphones_label"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/headphones_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/headphones_label"
style="@style/TextAppearance.Material3.BodyLarge"
android:layout_width="0dp"
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
android:ellipsize="end"
android:gravity="center"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toStartOf="@id/signal"
app:layout_constraintStart_toEndOf="@id/headphones_icon"
android:maxLines="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="AirPods Max" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/signal"
style="@style/TextAppearance.Material3.TitleSmall"
style="@style/TextAppearance.Material3.LabelMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableEnd="@drawable/ic_baseline_signal_cellular_alt_24"
android:gravity="center"
android:minWidth="44dp"
app:layout_constraintBottom_toBottomOf="@+id/headphones_label"
app:layout_constraintEnd_toStartOf="@+id/signal_icon"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/headphones_label"
tools:text="29%" />
<ImageView
android:id="@+id/signal_icon"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginStart="3dp"
android:src="@drawable/ic_baseline_signal_cellular_alt_24"
app:layout_constraintBottom_toBottomOf="@id/signal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/headphones_label"
tools:text="-90%" />
app:layout_constraintStart_toEndOf="@id/signal"
app:layout_constraintTop_toTopOf="@id/signal" />
<ImageView
android:id="@+id/headphones_icon"
style="@style/PodInfoItemIcon.Popup.Large"
android:layout_marginTop="16dp"
android:src="@drawable/devic_earbuds_generic_both"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/signal" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headphones_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/headphones_label">
app:layout_constraintTop_toBottomOf="@id/headphones_icon">
<ImageView
android:id="@id/headphones_battery_icon"
android:id="@+id/headphones_battery_icon"
style="@style/PodInfoItemIcon.Popup"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintBottom_toBottomOf="@id/headphones_battery_label"
app:layout_constraintEnd_toStartOf="@id/headphones_battery_label"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/headphones_battery_label" />
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/headphones_battery_label"
style="@style/TextAppearance.Material3.BodyLarge"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="@id/headphones_battery_icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/headphones_battery_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toTopOf="@id/headphones_battery_icon"
tools:text="100%" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,37 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="24dp"
app:cardElevation="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="320dp"
android:minHeight="96dp"
android:layout_margin="8dp">
android:layout_height="wrap_content"
android:paddingHorizontal="20dp"
android:paddingTop="20dp"
android:paddingBottom="16dp">
<FrameLayout
android:id="@+id/popup_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/close_action"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/close_action"
style="@style/Widget.Material3.Button.TextButton"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/general_close_action"
app:cornerRadius="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/popup_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.card.MaterialCardView>
+5
View File
@@ -48,6 +48,11 @@
<item name="android:layout_width">24dp</item>
</style>
<style name="PodInfoItemIcon.Popup.Large">
<item name="android:layout_height">64dp</item>
<item name="android:layout_width">64dp</item>
</style>
<style name="PodInfoItemText" parent="TextAppearance.Material3.BodyMedium">
<item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item>