Twelve: Import settings activity from Aperture
Change-Id: Ic0ce8bb09b61b6297212e3d975eef4d1c0c8c956
diff --git a/app/Android.bp b/app/Android.bp
index a9cc7dd..48ceb96 100644
--- a/app/Android.bp
+++ b/app/Android.bp
@@ -61,6 +61,7 @@
"Twelve_androidx.media3_media3-ui",
"androidx.navigation_navigation-fragment-ktx",
"androidx.navigation_navigation-ui-ktx",
+ "androidx.preference_preference",
"androidx.recyclerview_recyclerview",
"androidx.room_room-ktx",
"androidx.room_room-runtime",
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 23cf2b1..5c26ffe 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -93,6 +93,7 @@
implementation(libs.androidx.media3.ui)
implementation(libs.androidx.navigation.fragment.ktx)
implementation(libs.androidx.navigation.ui.ktx)
+ implementation(libs.androidx.preference)
implementation(libs.androidx.recyclerview)
implementation(libs.androidx.room.runtime)
annotationProcessor(libs.androidx.room.compiler)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0361f73..e00670f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -60,6 +60,13 @@
</activity>
<activity
+ android:name=".SettingsActivity"
+ android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize|keyboardHidden"
+ android:exported="false"
+ android:label="@string/title_activity_settings"
+ android:theme="@style/Theme.SettingsLib" />
+
+ <activity
android:name=".ViewActivity"
android:excludeFromRecents="true"
android:exported="true"
diff --git a/app/src/main/java/org/lineageos/twelve/SettingsActivity.kt b/app/src/main/java/org/lineageos/twelve/SettingsActivity.kt
new file mode 100644
index 0000000..13d9a2a
--- /dev/null
+++ b/app/src/main/java/org/lineageos/twelve/SettingsActivity.kt
@@ -0,0 +1,134 @@
+/*
+ * SPDX-FileCopyrightText: 2024 The LineageOS Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.lineageos.twelve
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import androidx.annotation.CallSuper
+import androidx.annotation.Px
+import androidx.annotation.XmlRes
+import androidx.appcompat.app.AppCompatActivity
+import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
+import androidx.preference.PreferenceFragmentCompat
+import com.google.android.material.appbar.AppBarLayout
+import com.google.android.material.appbar.MaterialToolbar
+import org.lineageos.twelve.ext.setOffset
+import kotlin.reflect.safeCast
+
+class SettingsActivity : AppCompatActivity(R.layout.activity_settings) {
+ private val appBarLayout by lazy { findViewById<AppBarLayout>(R.id.appBarLayout) }
+ private val coordinatorLayout by lazy { findViewById<CoordinatorLayout>(R.id.coordinatorLayout) }
+ private val toolbar by lazy { findViewById<MaterialToolbar>(R.id.toolbar) }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // Setup edge-to-edge
+ WindowCompat.setDecorFitsSystemWindows(window, false)
+
+ if (savedInstanceState == null) {
+ supportFragmentManager
+ .beginTransaction()
+ .replace(R.id.settings, RootSettingsFragment())
+ .commit()
+ }
+
+ setSupportActionBar(toolbar)
+ supportActionBar?.apply {
+ setDisplayHomeAsUpEnabled(true)
+ setDisplayShowHomeEnabled(true)
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
+ android.R.id.home -> {
+ onBackPressedDispatcher.onBackPressed()
+ true
+ }
+
+ else -> {
+ super.onOptionsItemSelected(item)
+ }
+ }
+
+ abstract class SettingsFragment(
+ @XmlRes private val preferencesResId: Int,
+ ) : PreferenceFragmentCompat() {
+ private val settingsActivity
+ get() = SettingsActivity::class.safeCast(activity)
+
+ @Px
+ private var appBarOffset = -1
+
+ private val offsetChangedListener = AppBarLayout.OnOffsetChangedListener { _, i ->
+ appBarOffset = -i
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ settingsActivity?.let { settingsActivity ->
+ val appBarLayout = settingsActivity.appBarLayout
+
+ if (appBarOffset != -1) {
+ appBarLayout.setOffset(appBarOffset, settingsActivity.coordinatorLayout)
+ } else {
+ appBarLayout.setExpanded(true, false)
+ }
+
+ appBarLayout.setLiftOnScrollTargetView(listView)
+
+ appBarLayout.addOnOffsetChangedListener(offsetChangedListener)
+ }
+ }
+
+ override fun onDestroyView() {
+ settingsActivity?.appBarLayout?.apply {
+ removeOnOffsetChangedListener(offsetChangedListener)
+
+ setLiftOnScrollTargetView(null)
+ }
+
+ super.onDestroyView()
+ }
+
+ @CallSuper
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(preferencesResId, rootKey)
+ }
+
+ @CallSuper
+ override fun onCreateRecyclerView(
+ inflater: LayoutInflater,
+ parent: ViewGroup,
+ savedInstanceState: Bundle?
+ ) = super.onCreateRecyclerView(inflater, parent, savedInstanceState).apply {
+ clipToPadding = false
+ isVerticalScrollBarEnabled = false
+
+ ViewCompat.setOnApplyWindowInsetsListener(this) { _, windowInsets ->
+ val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+
+ updatePadding(
+ bottom = insets.bottom,
+ left = insets.left,
+ right = insets.right,
+ )
+
+ windowInsets
+ }
+ }
+ }
+
+ class RootSettingsFragment : SettingsFragment(R.xml.root_preferences)
+}
diff --git a/app/src/main/java/org/lineageos/twelve/ext/AppBarLayout.kt b/app/src/main/java/org/lineageos/twelve/ext/AppBarLayout.kt
new file mode 100644
index 0000000..ad12102
--- /dev/null
+++ b/app/src/main/java/org/lineageos/twelve/ext/AppBarLayout.kt
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: 2024 The LineageOS Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.lineageos.twelve.ext
+
+import androidx.annotation.Px
+import androidx.coordinatorlayout.widget.CoordinatorLayout
+import com.google.android.material.appbar.AppBarLayout
+import kotlin.reflect.safeCast
+
+fun AppBarLayout.setOffset(@Px offsetPx: Int, coordinatorLayout: CoordinatorLayout) {
+ val params = CoordinatorLayout.LayoutParams::class.safeCast(layoutParams) ?: return
+ AppBarLayout.Behavior::class.safeCast(params.behavior)?.onNestedPreScroll(
+ coordinatorLayout,
+ this,
+ this,
+ 0,
+ offsetPx,
+ intArrayOf(0, 0),
+ 0
+ )
+}
diff --git a/app/src/main/res/color/settingslib_switch_thumb_color.xml b/app/src/main/res/color/settingslib_switch_thumb_color.xml
new file mode 100644
index 0000000..ce1668d
--- /dev/null
+++ b/app/src/main/res/color/settingslib_switch_thumb_color.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2021 The Android Open Source Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Disabled status of thumb -->
+ <item android:color="?attr/colorOutline" android:state_enabled="false" />
+ <!-- Toggle off status of thumb -->
+ <item android:color="?attr/colorOutline" android:state_checked="false" />
+ <!-- Enabled or toggle on status of thumb -->
+ <item android:color="?attr/colorOnPrimary" />
+</selector>
diff --git a/app/src/main/res/color/settingslib_switch_track_color.xml b/app/src/main/res/color/settingslib_switch_track_color.xml
new file mode 100644
index 0000000..ba62e66
--- /dev/null
+++ b/app/src/main/res/color/settingslib_switch_track_color.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2021 The Android Open Source Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Disabled status of thumb -->
+ <item android:alpha="?android:attr/disabledAlpha" android:color="?attr/colorSurfaceVariant" android:state_enabled="false" />
+ <!-- Toggle off status of thumb -->
+ <item android:color="?attr/colorSurfaceVariant" android:state_checked="false" />
+ <!-- Enabled or toggle on status of thumb -->
+ <item android:color="?attr/colorPrimary" />
+</selector>
diff --git a/app/src/main/res/drawable/settingslib_switch_thumb.xml b/app/src/main/res/drawable/settingslib_switch_thumb.xml
new file mode 100644
index 0000000..35ca08d
--- /dev/null
+++ b/app/src/main/res/drawable/settingslib_switch_thumb.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2021 The Android Open Source Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:bottom="4dp"
+ android:left="4dp"
+ android:right="4dp"
+ android:top="4dp">
+ <shape android:shape="oval">
+ <size
+ android:width="20dp"
+ android:height="20dp" />
+ <solid android:color="@color/settingslib_switch_thumb_color" />
+ </shape>
+ </item>
+</layer-list>
diff --git a/app/src/main/res/drawable/settingslib_switch_track.xml b/app/src/main/res/drawable/settingslib_switch_track.xml
new file mode 100644
index 0000000..52675f5
--- /dev/null
+++ b/app/src/main/res/drawable/settingslib_switch_track.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2021 The Android Open Source Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="52dp"
+ android:height="28dp"
+ android:shape="rectangle">
+
+ <solid android:color="@color/settingslib_switch_track_color" />
+ <corners android:radius="35dp" />
+</shape>
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
new file mode 100644
index 0000000..0765e3c
--- /dev/null
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2022-2023 The LineageOS Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<androidx.coordinatorlayout.widget.CoordinatorLayout 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/coordinatorLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".SettingsActivity">
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/appBarLayout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fitsSystemWindows="true"
+ app:liftOnScrollTargetViewId="@+id/settings">
+
+ <com.google.android.material.appbar.CollapsingToolbarLayout
+ style="?attr/collapsingToolbarLayoutLargeStyle"
+ android:layout_width="match_parent"
+ android:layout_height="179dp"
+ app:collapsedTitleTextAppearance="@style/Theme.SettingsLib.ToolbarCollapsedTextAppearance"
+ app:expandedTitleMarginBottom="31dp"
+ app:expandedTitleMarginStart="24dp"
+ app:expandedTitleTextAppearance="@style/Theme.SettingsLib.ToolbarExpandedTextAppearance"
+ app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
+ app:titleCollapseMode="fade"
+ app:toolbarId="@id/toolbar">
+
+ <com.google.android.material.appbar.MaterialToolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?actionBarSize"
+ android:elevation="0dp"
+ app:layout_collapseMode="pin" />
+
+ </com.google.android.material.appbar.CollapsingToolbarLayout>
+
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <FrameLayout
+ android:id="@+id/settings"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4271651..10b38aa 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -139,6 +139,9 @@
<string name="argument_validation_error_message">Error while parsing the following arguments:\n%1$s</string>
<string name="argument_validation_error_item">%1$s: %2$s</string>
+ <!-- Settings title -->
+ <string name="title_activity_settings">Settings</string>
+
<!-- Now playing widget -->
<string name="now_playing_widget_description">Now playing</string>
<string name="now_playing_widget_dummy_title">Title</string>
diff --git a/app/src/main/res/values/themes_settingslib.xml b/app/src/main/res/values/themes_settingslib.xml
new file mode 100644
index 0000000..740da76
--- /dev/null
+++ b/app/src/main/res/values/themes_settingslib.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2024 The LineageOS Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<resources>
+ <!-- Settings activity theme. -->
+ <style name="Theme.SettingsLib" parent="Theme.Material3.DayNight.NoActionBar">
+ <item name="android:listPreferredItemPaddingLeft">24dp</item>
+ <item name="android:listPreferredItemPaddingStart">24dp</item>
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ <item name="android:switchStyle">@style/Theme.SettingsLib.Switch</item>
+ <item name="android:windowLightStatusBar">?attr/isLightTheme</item>
+ <item name="alertDialogTheme">@style/Theme.SettingsLib.AlertDialog</item>
+ <item name="materialAlertDialogTheme">@style/Theme.SettingsLib.AlertDialog</item>
+ <item name="preferenceTheme">@style/Theme.SettingsLib.PreferenceTheme</item>
+ </style>
+
+ <!-- Settings alert dialog theme. -->
+ <style name="Theme.SettingsLib.AlertDialog" parent="ThemeOverlay.Material3.MaterialAlertDialog">
+ <item name="android:colorBackground">?attr/colorSurface</item>
+ <item name="dialogCornerRadius">16dp</item>
+ </style>
+
+ <!-- Settings switch theme. -->
+ <style name="Theme.SettingsLib.Switch" parent="@android:style/Widget.Material.CompoundButton.Switch">
+ <item name="android:switchMinWidth">52dp</item>
+ <item name="android:minHeight">48dp</item>
+ <item name="android:track">@drawable/settingslib_switch_track</item>
+ <item name="android:thumb">@drawable/settingslib_switch_thumb</item>
+ </style>
+
+ <!-- Settings collapsing toolbar style -->
+ <style name="Theme.SettingsLib.ToolbarCollapsedTextAppearance" parent="TextAppearance.Material3.ActionBar.Title" />
+
+ <style name="Theme.SettingsLib.ToolbarExpandedTextAppearance" parent="TextAppearance.Material3.HeadlineMedium">
+ <item name="android:drawablePadding">10dp</item>
+ <item name="android:textSize">36sp</item>
+ </style>
+
+ <!-- Settings preference style. -->
+ <style name="Theme.SettingsLib.PreferenceTheme" parent="PreferenceThemeOverlay">
+ <item name="android:divider">@android:color/transparent</item>
+ <item name="android:dividerHeight">0dp</item>
+ <item name="android:listPreferredItemPaddingLeft">32dp</item>
+ <item name="android:listPreferredItemPaddingStart">32dp</item>
+ <item name="android:tint">?attr/colorOnSurface</item>
+ </style>
+</resources>
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
new file mode 100644
index 0000000..d6118c0
--- /dev/null
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2024 The LineageOS Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<PreferenceScreen />
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 1411095..e169874 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -20,6 +20,7 @@
navigation = "2.8.0"
nier-visualizer = "v0.1.3"
okhttp = "4.12.0"
+preference = "1.2.1"
recyclerview = "1.3.2"
room = "2.6.1"
viewpager2 = "1.1.0"
@@ -41,6 +42,7 @@
androidx-media3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3" }
androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigation" }
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigation" }
+androidx-preference = { group = "androidx.preference", name = "preference", version.ref = "preference" }
androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }