mirror of
https://github.com/Michatec/Radio.git
synced 2026-05-31 06:52:40 +02:00
Add support for Android TV and update dependencies
* Implement initial Android TV support, including `LEANBACK_LAUNCHER` intent filter, hardware feature declarations, and television-specific layouts for the player, search results, and dialogs. * Add a splash/loading screen for the TV interface and a dedicated `SplashTheme`. * Improve DPAD navigation by adding `OnKeyListener` for station cards and allowing focus on internal elements. * Update `LayoutHolder` and `PlayerFragment` to handle TV layouts and add previous/next station navigation buttons. * Adjust `PreferencesHelper` to disable station editing by default on TV devices. * Update `androidx.media3` to v1.10.0, `work-runtime-ktx` to v2.11.2, and add `androidx.leanback` dependency. * Bump `versionCode` to 144 and `versionName` to 14.4. * Refactor `PlayerService` to simplify sleep timer cancellation logic. * Remove stale copyright headers and license comments from several Kotlin files.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/list_card_stroke_focused" android:state_focused="true" />
|
||||
<item android:color="@color/list_card_stroke_background" />
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/search_result_background_selected" android:state_focused="true" />
|
||||
<item android:drawable="@android:color/transparent" />
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/list_card_stroke_focused" android:state_focused="true" />
|
||||
<item android:color="@color/list_card_stroke_background" />
|
||||
</selector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#80FFFFFF" />
|
||||
<corners android:radius="8dp" />
|
||||
<stroke android:width="3dp" android:color="@color/default_neutral_white" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:drawable="@android:color/transparent" />
|
||||
</selector>
|
||||
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- View is "selected" -->
|
||||
<!-- View is "selected" or "focused" (for TV) -->
|
||||
<item android:drawable="@drawable/shape_search_result_item_selected" android:state_selected="true" />
|
||||
<item android:drawable="@drawable/shape_search_result_item_selected" android:state_focused="true" />
|
||||
|
||||
<!-- Default state. -->
|
||||
<item android:drawable="@drawable/shape_search_result_item" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/default_neutral_lighter" />
|
||||
android:width="4dp"
|
||||
android:color="@color/default_neutral_white" />
|
||||
<size
|
||||
android:width="56dp"
|
||||
android:height="56dp" />
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/splashBackgroundColor" />
|
||||
<item
|
||||
android:width="160dp"
|
||||
android:height="160dp"
|
||||
android:gravity="center">
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/bottom_sheet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/shape_player_sheet_background"
|
||||
android:padding="24dp">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/station_icon"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:background="@drawable/shape_cover_small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearanceOverlay="@style/RoundedCorners"
|
||||
app:srcCompat="@drawable/ic_default_station_image_72dp" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/player_station_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium"
|
||||
android:textColor="@color/player_sheet_text_main"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@+id/player_play_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/station_icon"
|
||||
app:layout_constraintTop_toTopOf="@+id/station_icon"
|
||||
tools:text="Station Name" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/player_station_metadata"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:textColor="@color/player_sheet_text_main"
|
||||
app:layout_constraintEnd_toEndOf="@+id/player_station_name"
|
||||
app:layout_constraintStart_toStartOf="@+id/player_station_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/player_station_name"
|
||||
tools:text="Metadata Info" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_play_button"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:background="@drawable/selector_play_button"
|
||||
android:focusable="true"
|
||||
android:scaleType="center"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/station_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/station_icon"
|
||||
app:srcCompat="@drawable/ic_player_play_symbol_42dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/detailed_controls_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@+id/station_icon">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sheet_previous_metadata_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
app:srcCompat="@drawable/ic_chevron_left_24dp" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/sheet_metadata_history"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:textColor="@color/player_sheet_text_main"
|
||||
tools:text="Metadata History" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sheet_next_metadata_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
app:srcCompat="@drawable/ic_chevron_right_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/copy_station_metadata_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
app:srcCompat="@drawable/ic_copy_content_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sleep_timer_start_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
app:srcCompat="@drawable/ic_sleep_timer_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sleep_timer_cancel_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
android:visibility="gone"
|
||||
app:srcCompat="@drawable/ic_clear_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/sleep_timer_remaining_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/player_sheet_text_main"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/detailed_controls_row"
|
||||
tools:text="15:00" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="1000dp"
|
||||
android:layout_height="500dp"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/station_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.7" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dialog_button_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/dialog_positive_button"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dialog_find_station_button_add" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/dialog_negative_button"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/dialog_generic_button_cancel" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="1000dp"
|
||||
android:layout_height="500dp"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.appcompat.widget.SearchView
|
||||
android:id="@+id/station_search_box_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:iconifiedByDefault="false"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:queryHint="@string/dialog_find_station_hint" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/search_request_progress_indicator"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="@+id/station_search_box_view"
|
||||
app:layout_constraintStart_toStartOf="@+id/station_search_box_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/station_search_box_view" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/no_results_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dialog_find_station_no_results"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search_request_progress_indicator" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/station_search_result_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/no_results_text_view" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.7" />
|
||||
|
||||
<!-- Right side: Actions -->
|
||||
<LinearLayout
|
||||
android:id="@+id/dialog_button_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/dialog_positive_button"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dialog_find_station_button_add" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/dialog_negative_button"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/dialog_generic_button_cancel" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="800dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/dialog_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dialog_error_message_default"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
|
||||
android:textColor="@color/text_default"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/dialog_error_message_default" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/dialog_details_link"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="8dp"
|
||||
android:text="@string/dialog_generic_details_button"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/text_default"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dialog_message"
|
||||
tools:text="@string/dialog_generic_details_button" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/dialog_details"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:scrollbars="vertical"
|
||||
android:text="@string/dialog_opml_import_details_default"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:textColor="@color/text_default"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dialog_details_link"
|
||||
tools:text="@string/dialog_opml_import_details_default" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:nextFocusRight="@+id/dialog_positive_button"
|
||||
android:background="@drawable/selector_search_result_item">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/station_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleLarge"
|
||||
android:textColor="@color/text_default"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Station Name" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/station_url"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:textColor="@color/text_lightweight"
|
||||
app:layout_constraintEnd_toEndOf="@+id/station_name"
|
||||
app:layout_constraintStart_toStartOf="@+id/station_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/station_name"
|
||||
tools:text="http://stream.url" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/station_bitrate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/text_lightweight"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/station_url"
|
||||
app:layout_constraintStart_toStartOf="@+id/station_url"
|
||||
app:layout_constraintTop_toBottomOf="@+id/station_url"
|
||||
tools:text="128 kbps" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,206 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/station_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<include
|
||||
layout="@layout/element_onboarding"
|
||||
android:visibility="gone" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1.2"
|
||||
android:background="@color/player_sheet_background"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/player_ui"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/station_icon"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="160dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/shape_cover_small"
|
||||
android:contentDescription="@string/descr_player_station_image"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearanceOverlay="@style/RoundedCorners"
|
||||
app:srcCompat="@drawable/ic_default_station_image_72dp" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/player_station_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium"
|
||||
android:textColor="@color/player_sheet_text_main"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/station_icon"
|
||||
tools:text="Station Name" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/player_station_metadata"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
|
||||
android:textColor="@color/player_sheet_text_main"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/player_station_name"
|
||||
tools:text="Artist - Title" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/controls_row"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/player_station_metadata">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_prev_button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:contentDescription="@string/descr_expanded_player_metadata_previous_button"
|
||||
android:focusable="true"
|
||||
android:padding="12dp"
|
||||
app:srcCompat="@drawable/ic_chevron_left_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_play_button"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:background="@drawable/selector_play_button"
|
||||
android:contentDescription="@string/descr_player_playback_button"
|
||||
android:focusable="true"
|
||||
android:scaleType="center"
|
||||
app:srcCompat="@drawable/ic_player_play_symbol_42dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_next_button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:contentDescription="@string/descr_expanded_player_metadata_next_button"
|
||||
android:focusable="true"
|
||||
android:padding="12dp"
|
||||
app:srcCompat="@drawable/ic_chevron_right_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/secondary_controls_row"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/controls_row">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/copy_station_metadata_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
app:srcCompat="@drawable/ic_copy_content_24dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sleep_timer_start_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
app:srcCompat="@drawable/ic_sleep_timer_24dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sleep_timer_cancel_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/selector_generic_button_focus"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone"
|
||||
app:srcCompat="@drawable/ic_clear_24dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/player_buffering_indicator"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:indeterminateTint="@color/player_button_buffering"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/controls_row"
|
||||
app:layout_constraintEnd_toEndOf="@+id/controls_row"
|
||||
app:layout_constraintStart_toStartOf="@+id/controls_row"
|
||||
app:layout_constraintTop_toTopOf="@+id/controls_row" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/sleep_timer_remaining_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:textColor="@color/player_sheet_text_main"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/secondary_controls_row"
|
||||
tools:text="15:00" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -29,4 +29,49 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/main_toolbar"
|
||||
app:navGraph="@navigation/nav_graph_main" />
|
||||
|
||||
<!-- SPLASH / LOADING SCREEN -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/loading_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/splashBackgroundColor"
|
||||
android:elevation="10dp"
|
||||
android:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/loading_logo"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="160dp"
|
||||
android:contentDescription="@string/icon_launcher"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.4" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/loading"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
|
||||
android:textColor="@color/default_neutral_white"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loading_logo" />
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loading_logo"
|
||||
android:visibility="invisible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -12,6 +12,8 @@
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:stateListAnimator="@null"
|
||||
app:backgroundTint="@color/list_card_background"
|
||||
app:icon="@drawable/ic_add_24dp"
|
||||
@@ -28,6 +30,8 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:stateListAnimator="@null"
|
||||
app:backgroundTint="@color/list_card_background"
|
||||
app:icon="@drawable/ic_settings_24dp"
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<item name="colorSurface">@color/player_sheet_background</item>
|
||||
<item name="materialAlertDialogBodyTextStyle">@style/TextAppearance.MaterialComponents.Body1</item>
|
||||
<item name="android:backgroundDimAmount">0.64</item>
|
||||
<item name="colorControlActivated">#FFDAE2FF</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.App.TimePicker" parent="ThemeOverlay.MaterialComponents.TimePicker">
|
||||
@@ -49,5 +50,10 @@
|
||||
<item name="android:background">@color/player_sheet_background</item>
|
||||
<item name="dialogCornerRadius">28dp</item>
|
||||
<item name="checkedTextViewStyle">@style/AlertDialog.TextColor</item>
|
||||
<item name="colorControlActivated">#FFDAE2FF</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
<style name="AlertDialog.TextColor" parent="@style/TextAppearance.MaterialComponents.Body1">
|
||||
<item name="android:textColor">?attr/colorControlNormal</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<resources>
|
||||
<!-- NIGHT THEME COLORS -->
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="SplashTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<item name="android:windowBackground">@drawable/splash_screen</item>
|
||||
<item name="android:statusBarColor">@color/splashBackgroundColor</item>
|
||||
<item name="android:navigationBarColor">@color/splashBackgroundColor</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<resources>
|
||||
<!-- DAY THEME COLORS -->
|
||||
|
||||
@@ -16,6 +15,7 @@
|
||||
<!-- list -->
|
||||
<color name="list_card_background">#FFFEFBFF</color>
|
||||
<color name="list_card_stroke_background">#FFC0C6DD</color>
|
||||
<color name="list_card_stroke_focused">#FF495D92</color>
|
||||
<color name="list_card_cover_background">#FFE7E0EC</color>
|
||||
<color name="list_card_delete_background">#FFB3261E</color>
|
||||
<color name="list_card_delete_icon">#FFFFFFFF</color>
|
||||
|
||||
@@ -140,4 +140,6 @@
|
||||
<string name="snackbar_url_app_home_page" translatable="false">https://github.com/michatec/Radio/releases/latest</string>
|
||||
<string name="snackbar_github_update_check_url" translatable="false">https://api.github.com/repos/michatec/Radio/releases/latest</string>
|
||||
<string name="app_name" translatable="false">Radio</string>
|
||||
<string name="icon_launcher" translatable="false">Icon launcher.</string>
|
||||
<string name="loading">Loading...</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,29 +2,21 @@
|
||||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Set AppCompat’s colors -->
|
||||
<item name="colorPrimary">#FF495D92</item>
|
||||
<item name="colorAccent">#FF495D92</item>
|
||||
<item name="android:textColorHighlight">#FF495D92</item>
|
||||
|
||||
<!-- Do not use primary colored elevation overlays to present a visual hierarchy - TOO COLORFUL -->
|
||||
<item name="elevationOverlayEnabled">false</item>
|
||||
|
||||
<!-- Switch Theming -->
|
||||
<item name="colorControlActivated">#FFDAE2FF</item>
|
||||
<item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat.Material3</item>
|
||||
|
||||
<!-- Material Alert Dialog Theming -->
|
||||
<item name="materialAlertDialogTheme">@style/ThemeOverlay.App.MaterialAlertDialog</item>
|
||||
<item name="alertDialogTheme">@style/ThemeOverlay.App.AlertDialogTheme</item>
|
||||
|
||||
<!-- Material Time Picker Theming -->
|
||||
<item name="materialTimePickerTheme">@style/ThemeOverlay.App.TimePicker</item>
|
||||
|
||||
<!-- Use "light" Status Bar -->
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="SplashTheme" parent="AppTheme" />
|
||||
|
||||
<style name="Preference.SwitchPreferenceCompat.Material3" parent="@style/Preference.SwitchPreferenceCompat.Material">
|
||||
<item name="widgetLayout">@layout/preference_switch</item>
|
||||
</style>
|
||||
@@ -38,7 +30,11 @@
|
||||
<style name="ThemeOverlay.App.AlertDialogTheme" parent="@style/ThemeOverlay.Material3.MaterialAlertDialog">
|
||||
<item name="android:background">@color/list_card_background</item>
|
||||
<item name="dialogCornerRadius">28dp</item>
|
||||
<item name="checkedTextViewStyle">@style/AlertDialog.TextColor</item>
|
||||
<!-- TV Fix: Explicitly set accent color for radio buttons/checkboxes -->
|
||||
<item name="colorAccent">@color/icon_default</item>
|
||||
<item name="colorControlActivated">@color/icon_default</item>
|
||||
<item name="android:textColorPrimary">@color/text_default</item>
|
||||
<item name="android:textColorSecondary">@color/text_lightweight</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.App.TimePicker" parent="ThemeOverlay.MaterialComponents.TimePicker">
|
||||
@@ -46,13 +42,16 @@
|
||||
</style>
|
||||
|
||||
<style name="AlertDialog.TextColor" parent="@style/TextAppearance.MaterialComponents.Body1">
|
||||
<item name="android:textColor">?attr/colorControlNormal</item>
|
||||
<item name="android:textColor">@color/text_default</item>
|
||||
</style>
|
||||
|
||||
<style name="App.Widget.Material3.CardView.Outlined" parent="@style/Widget.Material3.CardView.Outlined">
|
||||
<item name="strokeColor">@color/list_card_stroke_background</item>
|
||||
<item name="strokeWidth">3dp</item>
|
||||
<item name="strokeColor">@color/selector_card_station_stroke</item>
|
||||
<item name="strokeWidth">4dp</item>
|
||||
<item name="cardCornerRadius">24dp</item>
|
||||
<item name="android:focusable">true</item>
|
||||
<item name="android:clickable">true</item>
|
||||
<item name="android:descendantFocusability">afterDescendants</item>
|
||||
</style>
|
||||
|
||||
<style name="App.Widget.MaterialComponents.TextView" parent="@style/Widget.MaterialComponents.TextView">
|
||||
|
||||
Reference in New Issue
Block a user