mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 11:51:50 +01:00
Preview of Themes in General settings
This commit is contained in:
parent
227769e5ec
commit
6b8e4eeb14
@ -32,6 +32,10 @@ inline fun PreferenceGroup.preference(block: (@DSL Preference).() -> Unit): Pref
|
||||
return initThenAdd(Preference(context), block)
|
||||
}
|
||||
|
||||
inline fun PreferenceGroup.themePreference(block: (@DSL ThemePreference).() -> Unit): ThemePreference {
|
||||
return initThenAdd(ThemePreference(context), block)
|
||||
}
|
||||
|
||||
inline fun PreferenceGroup.switchPreference(block: (@DSL SwitchPreferenceCompat).() -> Unit): SwitchPreferenceCompat {
|
||||
return initThenAdd(SwitchPreferenceCompat(context), block)
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package eu.kanade.tachiyomi.ui.setting
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
@ -8,7 +10,6 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import eu.kanade.tachiyomi.util.system.ThemeUtil
|
||||
import eu.kanade.tachiyomi.widget.preference.IntListMatPreference
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
||||
|
||||
@ -16,6 +17,8 @@ class SettingsGeneralController : SettingsController() {
|
||||
|
||||
private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER
|
||||
|
||||
var lastThemeX: Int? = null
|
||||
var themePreference: ThemePreference? = null
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||
titleRes = R.string.general
|
||||
|
||||
@ -88,18 +91,12 @@ class SettingsGeneralController : SettingsController() {
|
||||
preferenceCategory {
|
||||
titleRes = R.string.display
|
||||
|
||||
listPreference(activity) {
|
||||
themePreference = themePreference {
|
||||
key = Keys.themeStyle
|
||||
titleRes = R.string.app_theme
|
||||
val enumConstants = ThemeUtil.Themes::class.java.enumConstants
|
||||
entriesRes = enumConstants?.map { it.nameRes }.orEmpty().toTypedArray()
|
||||
entryValues = enumConstants?.map { it.name }.orEmpty()
|
||||
defaultValue = ThemeUtil.Themes.DEFAULT
|
||||
|
||||
onChange {
|
||||
activity?.recreate()
|
||||
true
|
||||
}
|
||||
lastScrollPostion = lastThemeX
|
||||
summaryRes = preferences.theme().get().nameRes
|
||||
activity = this@SettingsGeneralController.activity
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
@ -204,4 +201,20 @@ class SettingsGeneralController : SettingsController() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
themePreference = null
|
||||
}
|
||||
|
||||
override fun onSaveViewState(view: View, outState: Bundle) {
|
||||
outState.putInt(::lastThemeX.name, themePreference?.lastScrollPostion ?: 0)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
|
||||
super.onRestoreViewState(view, savedViewState)
|
||||
lastThemeX = savedViewState.getInt(::lastThemeX.name)
|
||||
themePreference?.lastScrollPostion = lastThemeX
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,164 @@
|
||||
package eu.kanade.tachiyomi.ui.setting
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.ISelectionListener
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter
|
||||
import com.mikepenz.fastadapter.items.AbstractItem
|
||||
import com.mikepenz.fastadapter.select.SelectExtension
|
||||
import com.mikepenz.fastadapter.select.getSelectExtension
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.databinding.ThemeItemBinding
|
||||
import eu.kanade.tachiyomi.databinding.ThemesPreferenceBinding
|
||||
import eu.kanade.tachiyomi.util.system.ThemeUtil
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.view.visInvisIf
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class ThemePreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
Preference(context, attrs) {
|
||||
|
||||
private lateinit var fastAdapter: FastAdapter<ThemeItem>
|
||||
private val itemAdapter = ItemAdapter<ThemeItem>()
|
||||
private lateinit var selectExtension: SelectExtension<ThemeItem>
|
||||
private val preferences: PreferencesHelper by injectLazy()
|
||||
var activity: Activity? = null
|
||||
var lastScrollPostion: Int? = null
|
||||
lateinit var binding: ThemesPreferenceBinding
|
||||
val manager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
init {
|
||||
layoutResource = R.layout.themes_preference
|
||||
fastAdapter = FastAdapter.with(itemAdapter)
|
||||
fastAdapter.setHasStableIds(true)
|
||||
val enumConstants = ThemeUtil.Themes::class.java.enumConstants
|
||||
val currentTheme = preferences.theme().get()
|
||||
selectExtension = fastAdapter.getSelectExtension().apply {
|
||||
isSelectable = true
|
||||
multiSelect = false
|
||||
selectionListener = object : ISelectionListener<ThemeItem> {
|
||||
override fun onSelectionChanged(item: ThemeItem, selected: Boolean) {
|
||||
preferences.theme().set(item.theme)
|
||||
activity?.recreate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemAdapter.set(enumConstants?.map(::ThemeItem).orEmpty())
|
||||
itemAdapter.adapterItems.forEach { item ->
|
||||
item.isSelected = currentTheme == item.theme
|
||||
}
|
||||
isSelectable = false
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
binding = ThemesPreferenceBinding.bind(holder.itemView)
|
||||
|
||||
binding.themePrefTitle.text = title
|
||||
binding.themeRecycler.setHasFixedSize(true)
|
||||
binding.themeRecycler.layoutManager = manager
|
||||
|
||||
binding.themeRecycler.adapter = fastAdapter
|
||||
|
||||
binding.themeRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
lastScrollPostion =
|
||||
recyclerView.computeHorizontalScrollOffset() // (lastScrollPostion ?: 0) + dx
|
||||
}
|
||||
})
|
||||
|
||||
val enumConstants = ThemeUtil.Themes::class.java.enumConstants
|
||||
val currentTheme = preferences.theme().get()
|
||||
if (lastScrollPostion != null) {
|
||||
val lX = lastScrollPostion!!
|
||||
(binding.themeRecycler.layoutManager as LinearLayoutManager).apply {
|
||||
scrollToPositionWithOffset(
|
||||
lX / 110.dpToPx,
|
||||
-lX % 110.dpToPx + binding.themeRecycler.paddingStart
|
||||
)
|
||||
}
|
||||
lastScrollPostion = binding.themeRecycler.computeHorizontalScrollOffset()
|
||||
} else {
|
||||
binding.themeRecycler.scrollToPosition(
|
||||
enumConstants?.indexOf(currentTheme) ?: 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
inner class ThemeItem(val theme: ThemeUtil.Themes) : AbstractItem<FastAdapter.ViewHolder<ThemeItem>>() {
|
||||
|
||||
/** defines the type defining this item. must be unique. preferably an id */
|
||||
override val type: Int = R.id.theme_card_view
|
||||
|
||||
/** defines the layout which will be used for this item in the list */
|
||||
override val layoutRes: Int = R.layout.theme_item
|
||||
|
||||
override var identifier = theme.hashCode().toLong()
|
||||
|
||||
override fun getViewHolder(v: View): FastAdapter.ViewHolder<ThemeItem> {
|
||||
return ViewHolder(v)
|
||||
}
|
||||
|
||||
val colors = theme.getColors()
|
||||
val darkColors = if (theme.nightMode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
|
||||
theme.getColors(AppCompatDelegate.MODE_NIGHT_YES)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
inner class ViewHolder(view: View) : FastAdapter.ViewHolder<ThemeItem>(view) {
|
||||
|
||||
val binding = ThemeItemBinding.bind(view)
|
||||
override fun bindView(item: ThemeItem, payloads: List<Any>) {
|
||||
binding.themeNameText.setText(item.theme.nameRes)
|
||||
|
||||
binding.checkbox.isVisible = item.isSelected
|
||||
binding.themeSelected.visInvisIf(item.isSelected)
|
||||
binding.themeToolbar.setBackgroundColor(item.colors.appBar)
|
||||
binding.themeAppBarText.imageTintList = ColorStateList.valueOf(item.colors.appBarText)
|
||||
binding.themeHeroImage.imageTintList = ColorStateList.valueOf(item.colors.primaryText)
|
||||
binding.themePrimaryText.imageTintList = ColorStateList.valueOf(item.colors.primaryText)
|
||||
binding.themeAccentedButton.imageTintList = ColorStateList.valueOf(item.colors.colorAccent)
|
||||
binding.themeSecondaryText.imageTintList = ColorStateList.valueOf(item.colors.secondaryText)
|
||||
binding.themeSecondaryText2.imageTintList = ColorStateList.valueOf(item.colors.secondaryText)
|
||||
|
||||
binding.themeBottomBar.setBackgroundColor(item.colors.bottomBar)
|
||||
binding.themeItem1.imageTintList = ColorStateList.valueOf(item.colors.inactiveTab)
|
||||
binding.themeItem2.imageTintList = ColorStateList.valueOf(item.colors.activeTab)
|
||||
binding.themeItem3.imageTintList = ColorStateList.valueOf(item.colors.inactiveTab)
|
||||
|
||||
binding.themeLayout.setBackgroundColor(item.colors.colorBackground)
|
||||
binding.darkThemeLayout.isVisible = item.darkColors != null
|
||||
|
||||
if (binding.darkThemeLayout.isVisible && item.darkColors != null) {
|
||||
binding.darkThemeToolbar.setBackgroundColor(item.darkColors.appBar)
|
||||
binding.darkThemeAppBarText.imageTintList = ColorStateList.valueOf(item.darkColors.appBarText)
|
||||
binding.darkThemeLayout.setBackgroundColor(item.darkColors.colorBackground)
|
||||
binding.darkThemePrimaryText.imageTintList = ColorStateList.valueOf(item.darkColors.primaryText)
|
||||
binding.darkThemeHeroImage.imageTintList = ColorStateList.valueOf(item.darkColors.primaryText)
|
||||
binding.darkThemeAccentedButton.imageTintList = ColorStateList.valueOf(item.darkColors.colorAccent)
|
||||
binding.darkThemeSecondaryText.imageTintList = ColorStateList.valueOf(item.darkColors.secondaryText)
|
||||
|
||||
binding.darkThemeBottomBar.setBackgroundColor(item.darkColors.bottomBar)
|
||||
binding.darkThemeItem2.imageTintList = ColorStateList.valueOf(item.darkColors.activeTab)
|
||||
binding.darkThemeItem3.imageTintList = ColorStateList.valueOf(item.darkColors.inactiveTab)
|
||||
}
|
||||
}
|
||||
|
||||
override fun unbindView(item: ThemeItem) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,11 +2,14 @@ package eu.kanade.tachiyomi.util.system
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object ThemeUtil {
|
||||
|
||||
@ -46,15 +49,179 @@ object ThemeUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
enum class Themes(@StyleRes val styleRes: Int, val nightMode: Int, @StringRes val nameRes: Int) {
|
||||
PURE_WHITE(R.style.Theme_Tachiyomi, AppCompatDelegate.MODE_NIGHT_NO, R.string.white_theme),
|
||||
LIGHT_BLUE(R.style.Theme_Tachiyomi_AllBlue, AppCompatDelegate.MODE_NIGHT_NO, R.string.light_blue),
|
||||
LIGHT_BLUE(
|
||||
R.style.Theme_Tachiyomi_AllBlue,
|
||||
AppCompatDelegate.MODE_NIGHT_NO,
|
||||
R.string.light_blue
|
||||
),
|
||||
DARK(R.style.Theme_Tachiyomi, AppCompatDelegate.MODE_NIGHT_YES, R.string.dark),
|
||||
AMOLED(R.style.Theme_Tachiyomi_Amoled, AppCompatDelegate.MODE_NIGHT_YES, R.string.amoled_black),
|
||||
DARK_BLUE(R.style.Theme_Tachiyomi_AllBlue, AppCompatDelegate.MODE_NIGHT_YES, R.string.dark_blue),
|
||||
DEFAULT(R.style.Theme_Tachiyomi, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, R.string.system_default),
|
||||
DEFAULT_AMOLED(R.style.Theme_Tachiyomi_Amoled, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, R.string.system_default_amoled),
|
||||
ALL_BLUE(R.style.Theme_Tachiyomi_AllBlue, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, R.string.system_default_all_blue),
|
||||
AMOLED(
|
||||
R.style.Theme_Tachiyomi_Amoled,
|
||||
AppCompatDelegate.MODE_NIGHT_YES,
|
||||
R.string.amoled_black
|
||||
),
|
||||
DARK_BLUE(
|
||||
R.style.Theme_Tachiyomi_AllBlue,
|
||||
AppCompatDelegate.MODE_NIGHT_YES,
|
||||
R.string.dark_blue
|
||||
),
|
||||
DEFAULT(
|
||||
R.style.Theme_Tachiyomi,
|
||||
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,
|
||||
R.string.system_default
|
||||
),
|
||||
DEFAULT_AMOLED(
|
||||
R.style.Theme_Tachiyomi_Amoled,
|
||||
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,
|
||||
R.string.system_default_amoled
|
||||
),
|
||||
ALL_BLUE(
|
||||
R.style.Theme_Tachiyomi_AllBlue,
|
||||
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,
|
||||
R.string.system_default_all_blue
|
||||
);
|
||||
|
||||
fun getColors(mode: Int = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM): Colors {
|
||||
return when (nightMode) {
|
||||
AppCompatDelegate.MODE_NIGHT_YES -> darkColors()
|
||||
AppCompatDelegate.MODE_NIGHT_NO -> lightColors()
|
||||
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> when (mode) {
|
||||
AppCompatDelegate.MODE_NIGHT_YES -> darkColors()
|
||||
else -> lightColors()
|
||||
}
|
||||
else -> lightColors()
|
||||
}
|
||||
}
|
||||
|
||||
private fun lightColors(): Colors {
|
||||
return Colors(
|
||||
lightPrimaryText,
|
||||
lightSecondaryText,
|
||||
lightBackground,
|
||||
lightAccent,
|
||||
lightAppBar,
|
||||
lightAppBarText,
|
||||
lightBottomBar,
|
||||
lightInactiveTab,
|
||||
lightActiveTab,
|
||||
)
|
||||
}
|
||||
|
||||
private fun darkColors(): Colors {
|
||||
return Colors(
|
||||
darkPrimaryText,
|
||||
darkSecondaryText,
|
||||
darkBackground,
|
||||
darkAccent,
|
||||
darkAppBar,
|
||||
darkAppBarText,
|
||||
darkBottomBar,
|
||||
darkInactiveTab,
|
||||
darkActiveTab,
|
||||
)
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val lightPrimaryText: Int = Color.parseColor("#DE000000")
|
||||
|
||||
@ColorInt
|
||||
val darkPrimaryText: Int = Color.parseColor("#FFFFFFFF")
|
||||
|
||||
@ColorInt
|
||||
val lightSecondaryText: Int = ColorUtils.setAlphaComponent(lightPrimaryText, (0.54f * 255f).roundToInt())
|
||||
|
||||
@ColorInt
|
||||
val darkSecondaryText: Int = ColorUtils.setAlphaComponent(darkPrimaryText, (0.54f * 255f).roundToInt())
|
||||
|
||||
@ColorInt
|
||||
val lightBackground: Int = Color.parseColor("#FAFAFA")
|
||||
|
||||
@ColorInt
|
||||
val darkBackground: Int = Color.parseColor(
|
||||
when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_Amoled -> "#000000"
|
||||
else -> "#1C1C1D"
|
||||
}
|
||||
)
|
||||
|
||||
@ColorInt
|
||||
val lightAccent: Int = Color.parseColor("#2979FF")
|
||||
|
||||
@ColorInt
|
||||
val darkAccent: Int = Color.parseColor("#3399FF")
|
||||
|
||||
@ColorInt
|
||||
val lightAppBar: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#54759E")
|
||||
else -> lightBackground
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val darkAppBar: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#54759E")
|
||||
else -> darkBackground
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val lightAppBarText: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#FFFFFF")
|
||||
else -> lightPrimaryText
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val darkAppBarText: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#FFFFFF")
|
||||
else -> darkPrimaryText
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val lightBottomBar: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#54759E")
|
||||
else -> Color.parseColor("#FFFFFF")
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val darkBottomBar: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#54759E")
|
||||
else -> Color.parseColor("#212121")
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val lightInactiveTab: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#80FFFFFF")
|
||||
else -> Color.parseColor("#C2424242")
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val darkInactiveTab: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> Color.parseColor("#80FFFFFF")
|
||||
else -> Color.parseColor("#C2FFFFFF")
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val lightActiveTab: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> lightAppBarText
|
||||
else -> lightAccent
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
val darkActiveTab: Int = when (styleRes) {
|
||||
R.style.Theme_Tachiyomi_AllBlue -> darkAppBarText
|
||||
else -> darkAccent
|
||||
}
|
||||
}
|
||||
|
||||
data class Colors(
|
||||
@ColorInt val primaryText: Int,
|
||||
@ColorInt val secondaryText: Int,
|
||||
@ColorInt val colorBackground: Int,
|
||||
@ColorInt val colorAccent: Int,
|
||||
@ColorInt val appBar: Int,
|
||||
@ColorInt val appBarText: Int,
|
||||
@ColorInt val bottomBar: Int,
|
||||
@ColorInt val inactiveTab: Int,
|
||||
@ColorInt val activeTab: 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>
|
7
app/src/main/res/drawable/right_half_oval.xml
Normal file
7
app/src/main/res/drawable/right_half_oval.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:topRightRadius="20dp"
|
||||
android:bottomRightRadius="20dp"/>
|
||||
<solid android:color="?android:attr/colorBackground" />
|
||||
</shape>
|
10
app/src/main/res/drawable/theme_selected_border.xml
Normal file
10
app/src/main/res/drawable/theme_selected_border.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle"
|
||||
android:thicknessRatio="2">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<corners android:radius="20dp"/>
|
||||
<stroke
|
||||
android:width="4dp"
|
||||
android:color="?colorAccent" />
|
||||
</shape>
|
355
app/src/main/res/layout/theme_item.xml
Normal file
355
app/src/main/res/layout/theme_item.xml
Normal file
@ -0,0 +1,355 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="110dp"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<View
|
||||
android:id="@+id/theme_selected"
|
||||
android:layout_height="140dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:background="@drawable/theme_selected_border"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/theme_name_text" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/theme_card_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="6dp"
|
||||
app:layout_constraintTop_toTopOf="@id/theme_selected"
|
||||
app:layout_constraintStart_toStartOf="@id/theme_selected"
|
||||
app:layout_constraintBottom_toBottomOf="@id/theme_selected"
|
||||
app:layout_constraintEnd_toEndOf="@id/theme_selected"
|
||||
app:cardElevation="4dp"
|
||||
app:cardCornerRadius="16dp">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:background="?android:attr/colorBackground"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/theme_layout"
|
||||
android:layout_width="0dp"
|
||||
android:background="?android:attr/colorBackground"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_height="0dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/theme_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_app_bar_preview"
|
||||
android:background="?attr/colorSecondary"
|
||||
android:elevation="2dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_app_bar_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_gravity="start|center"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="@dimen/theme_app_bar_margin_end"
|
||||
android:src="@drawable/oval"
|
||||
app:tint="?actionBarTintColor"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_hero_image"
|
||||
android:src="@drawable/oval"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_hero_preview"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
android:alpha="0.70"
|
||||
android:layout_marginTop="@dimen/theme_padding_preview"
|
||||
android:layout_marginStart="@dimen/theme_padding_preview"
|
||||
android:layout_marginEnd="@dimen/theme_padding_preview"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/theme_toolbar"
|
||||
app:layout_constraintBottom_toTopOf="@id/theme_primary_text"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_primary_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_marginStart="@dimen/theme_padding_preview"
|
||||
android:layout_marginEnd="@dimen/theme_primary_margin_end"
|
||||
android:layout_marginTop="@dimen/theme_text_padding_preview"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/theme_hero_image"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_accented_button"
|
||||
android:src="@drawable/oval"
|
||||
android:layout_width="@dimen/theme_accent_width_preview"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
app:tint="?colorAccent"
|
||||
android:layout_marginStart="3dp"
|
||||
app:layout_constraintTop_toTopOf="@id/theme_primary_text"
|
||||
app:layout_constraintBottom_toBottomOf="@id/theme_primary_text"
|
||||
app:layout_constraintStart_toEndOf="@id/theme_primary_text"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_secondary_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_marginStart="@dimen/theme_padding_preview"
|
||||
android:layout_marginTop="@dimen/theme_text_padding_preview"
|
||||
android:layout_marginEnd="@dimen/theme_secondary_margin_end"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintEnd_toStartOf="@id/theme_secondary_text_2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/theme_primary_text"
|
||||
app:tint="?android:attr/textColorSecondary"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_secondary_text_2"
|
||||
android:layout_width="27dp"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_marginStart="6dp"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintBottom_toBottomOf="@id/theme_secondary_text"
|
||||
app:layout_constraintStart_toEndOf="@id/theme_secondary_text"
|
||||
app:layout_constraintTop_toTopOf="@id/theme_secondary_text"
|
||||
app:tint="?android:attr/textColorSecondary"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/theme_bottom_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_bottom_bar_preview"
|
||||
android:background="?colorPrimaryVariant"
|
||||
android:elevation="2dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_item_1"
|
||||
android:layout_width="@dimen/theme_bottom_item_preview"
|
||||
android:layout_height="@dimen/theme_bottom_item_preview"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/theme_item_2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/tabBarIconInactive"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_item_2"
|
||||
android:layout_width="@dimen/theme_bottom_item_preview"
|
||||
android:layout_height="@dimen/theme_bottom_item_preview"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/theme_item_3"
|
||||
app:layout_constraintStart_toEndOf="@id/theme_item_1"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/tabBarIconColor"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/theme_item_3"
|
||||
android:layout_width="@dimen/theme_bottom_item_preview"
|
||||
android:layout_height="@dimen/theme_bottom_item_preview"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/theme_item_2"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/tabBarIconInactive"
|
||||
tools:ignore="ContentDescription" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/dark_theme_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?android:attr/colorBackground"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintWidth_percent="0.50">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/dark_theme_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_app_bar_preview"
|
||||
android:background="?attr/colorSecondary"
|
||||
android:elevation="2dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dark_theme_app_bar_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_gravity="start|center"
|
||||
android:layout_marginEnd="@dimen/theme_app_bar_margin_end"
|
||||
android:src="@drawable/right_half_oval"
|
||||
app:tint="?actionBarTintColor"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dark_theme_hero_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_hero_preview"
|
||||
android:layout_marginTop="@dimen/theme_padding_preview"
|
||||
android:layout_marginEnd="@dimen/theme_padding_preview"
|
||||
android:alpha="0.70"
|
||||
android:src="@drawable/right_half_oval"
|
||||
app:layout_constraintBottom_toTopOf="@id/dark_theme_hero_image"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/dark_theme_toolbar"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dark_theme_primary_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_marginTop="@dimen/theme_text_padding_preview"
|
||||
android:layout_marginEnd="@dimen/theme_primary_margin_end"
|
||||
android:src="@drawable/right_half_oval"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/dark_theme_hero_image"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dark_theme_accented_button"
|
||||
android:layout_width="@dimen/theme_accent_width_preview"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_marginStart="3dp"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintBottom_toBottomOf="@id/dark_theme_primary_text"
|
||||
app:layout_constraintStart_toEndOf="@id/dark_theme_primary_text"
|
||||
app:layout_constraintTop_toTopOf="@id/dark_theme_primary_text"
|
||||
app:tint="?colorAccent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dark_theme_secondary_text"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="@dimen/theme_text_preview"
|
||||
android:layout_marginTop="@dimen/theme_text_padding_preview"
|
||||
android:src="@drawable/right_half_oval"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/dark_theme_primary_text"
|
||||
app:tint="?android:attr/textColorSecondary"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/dark_theme_bottom_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/theme_bottom_bar_preview"
|
||||
android:background="?colorPrimaryVariant"
|
||||
android:elevation="2dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dark_theme_item_2"
|
||||
android:layout_width="@dimen/theme_bottom_item_half_preview"
|
||||
android:layout_height="@dimen/theme_bottom_item_preview"
|
||||
android:src="@drawable/right_half_oval"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/dark_theme_item_3"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/tabBarIconColor"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dark_theme_item_3"
|
||||
android:layout_width="@dimen/theme_bottom_item_preview"
|
||||
android:layout_height="@dimen/theme_bottom_item_preview"
|
||||
android:src="@drawable/oval"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/dark_theme_item_gap"
|
||||
app:layout_constraintStart_toEndOf="@id/dark_theme_item_2"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/tabBarIconInactive"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<Space
|
||||
android:id="@+id/dark_theme_item_gap"
|
||||
android:layout_width="0dp"
|
||||
app:layout_constraintWidth_percent="0.0"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/right_half_oval"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/dark_theme_item_3"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/tabBarIconColor"
|
||||
tools:ignore="ContentDescription" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/checkbox"
|
||||
android:background="@drawable/oval"
|
||||
android:backgroundTint="@android:color/white"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:contentDescription="@string/select_all"
|
||||
android:src="@drawable/ic_check_circle_24dp"
|
||||
app:tint="?attr/colorAccent"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/theme_name_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50sp"
|
||||
android:maxLines="3"
|
||||
android:layout_marginTop="2dp"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
|
||||
app:layout_constraintTop_toBottomOf="@id/theme_selected"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
tools:text="Theme Name" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
35
app/src/main/res/layout/themes_preference.xml
Normal file
35
app/src/main/res/layout/themes_preference.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/theme_pref_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/theme_recycler"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Menu"
|
||||
android:text="@string/app_theme"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/theme_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:listitem="@layout/theme_item"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/theme_pref_title"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:itemCount="2"
|
||||
android:clipToPadding="false"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -9,4 +9,19 @@
|
||||
<!--Nav header-->
|
||||
|
||||
<dimen name="bottom_sheet_width">0dp</dimen>
|
||||
|
||||
<dimen name="theme_padding_preview">6dp</dimen>
|
||||
<dimen name="theme_text_padding_preview">6dp</dimen>
|
||||
<dimen name="theme_text_preview">10dp</dimen>
|
||||
<dimen name="theme_hero_preview">20dp</dimen>
|
||||
<dimen name="theme_app_bar_margin_end">30dp</dimen>
|
||||
<dimen name="theme_primary_margin_end">32dp</dimen>
|
||||
<dimen name="theme_secondary_margin_end">56dp</dimen>
|
||||
<dimen name="theme_app_bar_preview">20dp</dimen>
|
||||
<dimen name="theme_bottom_bar_preview">26dp</dimen>
|
||||
<dimen name="theme_bottom_item_preview">12dp</dimen>
|
||||
<dimen name="theme_bottom_item_half_preview">6dp</dimen>
|
||||
<dimen name="theme_accent_width_preview">16dp</dimen>
|
||||
|
||||
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user