Update app theme preference UI
Heavily influenced by TachiyomiJ2K.
This commit is contained in:
parent
beb7f90908
commit
6240fe1dfc
@ -18,8 +18,13 @@ abstract class BaseThemedActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun AppCompatActivity.applyAppTheme(preferences: PreferencesHelper) {
|
fun AppCompatActivity.applyAppTheme(preferences: PreferencesHelper) {
|
||||||
|
getThemeResIds(preferences.appTheme().get(), preferences.themeDarkAmoled().get())
|
||||||
|
.forEach { setTheme(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getThemeResIds(appTheme: PreferenceValues.AppTheme, isAmoled: Boolean): List<Int> {
|
||||||
val resIds = mutableListOf<Int>()
|
val resIds = mutableListOf<Int>()
|
||||||
when (preferences.appTheme().get()) {
|
when (appTheme) {
|
||||||
PreferenceValues.AppTheme.MONET -> {
|
PreferenceValues.AppTheme.MONET -> {
|
||||||
resIds += R.style.Theme_Tachiyomi_Monet
|
resIds += R.style.Theme_Tachiyomi_Monet
|
||||||
}
|
}
|
||||||
@ -53,13 +58,11 @@ abstract class BaseThemedActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preferences.themeDarkAmoled().get()) {
|
if (isAmoled) {
|
||||||
resIds += R.style.ThemeOverlay_Tachiyomi_Amoled
|
resIds += R.style.ThemeOverlay_Tachiyomi_Amoled
|
||||||
}
|
}
|
||||||
|
|
||||||
resIds.forEach {
|
return resIds
|
||||||
setTheme(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||||
import eu.kanade.tachiyomi.util.preference.defaultValue
|
import eu.kanade.tachiyomi.util.preference.defaultValue
|
||||||
import eu.kanade.tachiyomi.util.preference.entriesRes
|
import eu.kanade.tachiyomi.util.preference.entriesRes
|
||||||
|
import eu.kanade.tachiyomi.util.preference.initThenAdd
|
||||||
import eu.kanade.tachiyomi.util.preference.intListPreference
|
import eu.kanade.tachiyomi.util.preference.intListPreference
|
||||||
import eu.kanade.tachiyomi.util.preference.listPreference
|
import eu.kanade.tachiyomi.util.preference.listPreference
|
||||||
import eu.kanade.tachiyomi.util.preference.onChange
|
import eu.kanade.tachiyomi.util.preference.onChange
|
||||||
@ -17,6 +18,7 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
|||||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||||
import eu.kanade.tachiyomi.util.system.isTablet
|
import eu.kanade.tachiyomi.util.system.isTablet
|
||||||
|
import eu.kanade.tachiyomi.widget.preference.ThemesPreference
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
||||||
@ -146,7 +148,7 @@ class SettingsGeneralController : SettingsController() {
|
|||||||
|
|
||||||
summary = "%s"
|
summary = "%s"
|
||||||
}
|
}
|
||||||
listPreference {
|
initThenAdd(ThemesPreference(context)) {
|
||||||
key = Keys.appTheme
|
key = Keys.appTheme
|
||||||
titleRes = R.string.pref_app_theme
|
titleRes = R.string.pref_app_theme
|
||||||
|
|
||||||
@ -158,10 +160,8 @@ class SettingsGeneralController : SettingsController() {
|
|||||||
}
|
}
|
||||||
it.titleResId != null && monetFilter
|
it.titleResId != null && monetFilter
|
||||||
}
|
}
|
||||||
entriesRes = appThemes.map { it.titleResId!! }.toTypedArray()
|
entries = appThemes
|
||||||
entryValues = appThemes.map { it.name }.toTypedArray()
|
|
||||||
defaultValue = appThemes[0].name
|
defaultValue = appThemes[0].name
|
||||||
summary = "%s"
|
|
||||||
|
|
||||||
onChange {
|
onChange {
|
||||||
activity?.recreate()
|
activity?.recreate()
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package eu.kanade.tachiyomi.widget.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.PreferenceViewHolder
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
||||||
|
|
||||||
|
class ThemesPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
ListPreference(context, attrs),
|
||||||
|
ThemesPreferenceAdapter.OnItemClickListener {
|
||||||
|
|
||||||
|
private val adapter = ThemesPreferenceAdapter(this)
|
||||||
|
|
||||||
|
init {
|
||||||
|
layoutResource = R.layout.pref_themes_list
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||||
|
super.onBindViewHolder(holder)
|
||||||
|
|
||||||
|
val themesList = holder.findViewById(R.id.themes_list) as RecyclerView
|
||||||
|
themesList.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
themesList.adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClick(position: Int) {
|
||||||
|
value = entries[position].name
|
||||||
|
callChangeListener(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var entries: List<PreferenceValues.AppTheme> = emptyList()
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
adapter.setItems(value)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package eu.kanade.tachiyomi.widget.preference
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.databinding.PrefThemeItemBinding
|
||||||
|
import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
class ThemesPreferenceAdapter(private val clickListener: OnItemClickListener) :
|
||||||
|
RecyclerView.Adapter<ThemesPreferenceAdapter.ThemeViewHolder>() {
|
||||||
|
|
||||||
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
|
private var themes = emptyList<PreferenceValues.AppTheme>()
|
||||||
|
|
||||||
|
private lateinit var binding: PrefThemeItemBinding
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ThemeViewHolder {
|
||||||
|
val themeResIds = BaseThemedActivity.getThemeResIds(themes[viewType], preferences.themeDarkAmoled().get())
|
||||||
|
val themedContext = themeResIds.fold(parent.context) {
|
||||||
|
context, themeResId -> ContextThemeWrapper(context, themeResId)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding = PrefThemeItemBinding.inflate(LayoutInflater.from(themedContext), parent, false)
|
||||||
|
return ThemeViewHolder(binding.root)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int = position
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = themes.size
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ThemesPreferenceAdapter.ThemeViewHolder, position: Int) {
|
||||||
|
holder.bind(themes[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setItems(themes: List<PreferenceValues.AppTheme>) {
|
||||||
|
this.themes = themes
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ThemeViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
fun bind(appTheme: PreferenceValues.AppTheme) {
|
||||||
|
binding.name.text = view.context.getString(appTheme.titleResId!!)
|
||||||
|
|
||||||
|
// Rounded corners
|
||||||
|
binding.coverContainer1.clipToOutline = true
|
||||||
|
binding.coverContainer2.clipToOutline = true
|
||||||
|
|
||||||
|
binding.themeCard.isChecked = preferences.appTheme().get() == appTheme
|
||||||
|
|
||||||
|
listOf(binding.root, binding.themeCard).forEach {
|
||||||
|
it.setOnClickListener {
|
||||||
|
clickListener.onItemClick(bindingAdapterPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onItemClick(position: Int)
|
||||||
|
}
|
||||||
|
}
|
6
app/src/main/res/drawable/oval.xml
Normal file
6
app/src/main/res/drawable/oval.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="20dp" />
|
||||||
|
<solid android:color="?android:attr/colorBackground" />
|
||||||
|
</shape>
|
187
app/src/main/res/layout/pref_theme_item.xml
Normal file
187
app/src/main/res/layout/pref_theme_item.xml
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
<?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="110dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="4dp">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/theme_card"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checkable="true"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
app:cardCornerRadius="@dimen/card_radius"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="176dp"
|
||||||
|
android:background="?android:attr/colorBackground">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/top_nav"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:background="?attr/colorToolbar"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/top_nav_text"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:src="@drawable/oval"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/top_nav"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/top_nav"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/top_nav"
|
||||||
|
app:tint="?attr/colorOnToolbar" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/heading"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="8dp"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:src="@drawable/oval"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/top_nav"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/top_nav"
|
||||||
|
app:tint="?attr/colorAccent" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/cover_container1"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginEnd="2dp"
|
||||||
|
android:background="@drawable/rounded_rectangle"
|
||||||
|
app:layout_constraintDimensionRatio="2:3"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/cover_container2"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/heading">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:alpha="0.5"
|
||||||
|
android:background="?attr/colorOnSurface" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/cover_badge"
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:background="?attr/colorAccent"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/cover_container1"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/cover_container1" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/cover_container2"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:background="@drawable/rounded_rectangle"
|
||||||
|
app:layout_constraintDimensionRatio="2:3"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/cover_container1"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/heading">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:alpha="0.5"
|
||||||
|
android:background="?attr/colorOnSurface" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/bottom_nav"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:background="?attr/colorToolbar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bottom_nav_selected_item"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@drawable/oval"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/bottom_nav"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/bottom_nav_unselected_item1"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/bottom_nav"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/bottom_nav"
|
||||||
|
app:tint="?attr/colorPrimary" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bottom_nav_unselected_item1"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@drawable/oval"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/bottom_nav"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/bottom_nav_unselected_item2"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/bottom_nav_selected_item"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/bottom_nav"
|
||||||
|
app:tint="?attr/colorOnToolbar" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bottom_nav_unselected_item2"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@drawable/oval"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/bottom_nav"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/bottom_nav_unselected_item3"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/bottom_nav_unselected_item1"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/bottom_nav"
|
||||||
|
app:tint="?attr/colorOnToolbar" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bottom_nav_unselected_item3"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@drawable/oval"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/bottom_nav"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/bottom_nav_unselected_item4"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/bottom_nav_unselected_item2"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/bottom_nav"
|
||||||
|
app:tint="?attr/colorOnToolbar" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bottom_nav_unselected_item4"
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@drawable/oval"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/bottom_nav"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/bottom_nav_unselected_item3"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/bottom_nav"
|
||||||
|
app:tint="?attr/colorOnToolbar" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="32sp"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
|
||||||
|
tools:text="Theme Name" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
26
app/src/main/res/layout/pref_themes_list.xml
Normal file
26
app/src/main/res/layout/pref_themes_list.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Menu"
|
||||||
|
tools:text="App theme" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/themes_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingVertical="8dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
tools:listitem="@layout/pref_theme_item" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
Loading…
Reference in New Issue
Block a user