Preview of Themes in General settings

This commit is contained in:
Jays2Kings 2021-04-10 02:14:33 -04:00
parent 227769e5ec
commit 6b8e4eeb14
10 changed files with 794 additions and 18 deletions

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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) {
}
}
}
}

View File

@ -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,
)
}

View 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>

View 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>

View 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>

View 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>

View 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>

View File

@ -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>