Removed old settings fragment; added licences button; added ColorPickerView dependency, to be used to pick colours for text and highlight; removed transparency settings in favour of ColorPickerView

This commit is contained in:
denizk0461
2023-05-16 11:38:04 +02:00
parent eca9594a7e
commit 4dfc2a2df6
16 changed files with 239 additions and 1112 deletions
@@ -3,6 +3,7 @@ package com.denizd.textbasic.fragment
import android.content.Context
import androidx.annotation.LayoutRes
import androidx.fragment.app.Fragment
import com.denizd.textbasic.sheet.AppSheet
open class BaseFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) {
@@ -14,4 +15,13 @@ open class BaseFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) {
}
override fun getContext(): Context = _context
/**
* Opens a bottom sheet. Sheet must be a subclass of [com.denizd.textbasic.sheet.AppSheet].
*
* @param sheet element that will be displayed
*/
protected fun openBottomSheet(sheet: AppSheet) {
sheet.show(childFragmentManager, sheet.javaClass.simpleName)
}
}
@@ -2,17 +2,10 @@ package com.denizd.textbasic.fragment
import android.os.Bundle
import com.denizd.textbasic.R
import com.google.android.material.transition.MaterialSharedAxis
class GuideFragment : BaseFragment(R.layout.fragment_guide) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
}
}
@@ -1,286 +0,0 @@
package com.denizd.textbasic.fragment
import android.graphics.Color
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.annotation.ColorInt
import com.denizd.textbasic.util.ColorTransparentUtils
import com.denizd.textbasic.db.QuoteStorage
import com.denizd.textbasic.R
import com.denizd.textbasic.databinding.FragmentSettingsBinding
import com.denizd.textbasic.util.viewBinding
import com.denizd.textbasic.widget.CanvasText
import com.google.android.material.transition.MaterialSharedAxis
import java.lang.reflect.Field
import kotlin.math.abs
class SettingsFragment : BaseFragment(R.layout.fragment_settings) {
private lateinit var storage: QuoteStorage
private lateinit var gravityButtons: Array<ImageButton>
private var widgetGravity = 4
private var backgroundIndex = 0
private var typefaceIndex = 0
private var typefaceStyleIndex = 0
private val binding: FragmentSettingsBinding by viewBinding(FragmentSettingsBinding::bind)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// binding.animationLl.animateLayoutChanges(true)
// TODO a lot of the buttons don't at all do what they're supposed to do!
storage = QuoteStorage.getInstance(context)
gravityButtons = arrayOf(
binding.buttonTopLeft, binding.buttonTopMiddle, binding.buttonTopRight,
binding.buttonMiddleLeft, binding.buttonMiddleMiddle, binding.buttonMiddleRight,
binding.buttonBottomLeft, binding.buttonBottomMiddle, binding.buttonBottomRight
)
widgetGravity = storage.getWidgetGravity()
binding.textSizePicker.apply {
minValue = 1
maxValue = 168
descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
wrapSelectorWheel = false
value = storage.getTextSize()
setOnValueChangedListener { _, _, _ ->
updatePreview()
}
}
binding.textTransparencyPicker.apply {
minValue = 0
maxValue = 20
val formatter = NumberPicker.Formatter { value ->
val temp = value * 5
"" + temp
}
setFormatter(formatter)
descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
wrapSelectorWheel = false
value = storage.getBackgroundTransparency()
// Do not touch - fix for value on spinner not showing up until touched
val f: Field = NumberPicker::class.java.getDeclaredField("mInputText")
f.isAccessible = true
val inputText: EditText = f.get(binding.textTransparencyPicker) as EditText
inputText.filters = arrayOfNulls(0)
setOnValueChangedListener { _, _, _ ->
updatePreview()
}
}
binding.bgTransparencyPicker.apply {
minValue = 0
maxValue = 20
val formatter = NumberPicker.Formatter { value ->
val temp = value * 5
"" + temp
}
setFormatter(formatter)
descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
wrapSelectorWheel = false
value = storage.getBackgroundTransparency()
// Do not touch - fix for value on spinner not showing up until touched
val f: Field = NumberPicker::class.java.getDeclaredField("mInputText")
f.isAccessible = true
val inputText: EditText = f.get(binding.bgTransparencyPicker) as EditText
inputText.filters = arrayOfNulls(0)
setOnValueChangedListener { _, _, _ ->
updatePreview()
}
}
binding.outlinePicker.apply {
minValue = 0
maxValue = 64
descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
wrapSelectorWheel = false
value = storage.getOutlineSize().toInt()
setOnValueChangedListener { _, _, _ ->
updatePreview()
}
}
////////////////////////////////////////////
binding.switchInvert.apply {
isChecked = storage.isInvertedEnabled()
setOnCheckedChangeListener { _, _ ->
updatePreview()
}
}
binding.switchRandom.apply {
isChecked = storage.isOrderRandom()
setOnCheckedChangeListener { _, _ ->
updatePreview()
}
}
binding.typefaceToggleButton.apply {
typefaceIndex = storage.getTypefaceIndex()
check(when (typefaceStyleIndex) {
2 -> R.id.button3_monospace
1 -> R.id.button2_serif
else -> R.id.button1_sansserif
})
addOnButtonCheckedListener { group, checkedId, isChecked ->
typefaceIndex = when (checkedId) {
R.id.button3_monospace -> 2
R.id.button2_serif -> 1
else -> 0
}
updatePreview()
}
}
binding.typefaceStyleToggleButton.apply {
typefaceStyleIndex = storage.getTypefaceStyle()
check(when (typefaceStyleIndex) {
3 -> R.id.button4_bold_italics
2 -> R.id.button3_italics
1 -> R.id.button2_bold
else -> R.id.button1_normal
})
addOnButtonCheckedListener { group, checkedId, isChecked ->
typefaceStyleIndex = when (checkedId) {
R.id.button4_bold_italics -> 3
R.id.button3_italics -> 2
R.id.button2_bold -> 1
else -> 0
}
updatePreview()
}
}
binding.backgroundToggleButton.apply {
backgroundIndex = storage.getBackgroundType()
check(when (backgroundIndex) {
2 -> R.id.button3_shadow
1 -> R.id.button2_outline
else -> R.id.button1_background
})
addOnButtonCheckedListener { group, checkedId, isChecked ->
backgroundIndex = when (checkedId) {
R.id.button3_shadow -> 2
R.id.button2_outline -> 1
else -> 0
}
updatePreview()
}
}
gravityButtons.forEachIndexed { index, button ->
button.setOnClickListener {
widgetGravity = index
setGravityButtons()
updatePreview()
}
}
setGravityButtons()
updatePreview()
}
private fun setGravityButtons() {
val transparent = context.getColor(android.R.color.transparent)
gravityButtons.forEach { button ->
button.setBackgroundColor(transparent)
}
val typedValue = TypedValue()
context.theme.resolveAttribute(R.attr.colorSecContainer, typedValue, true)
@ColorInt val colorTertiary = typedValue.data
gravityButtons[widgetGravity].setBackgroundColor(colorTertiary)
}
private fun updatePreview() {
save()
if (backgroundIndex == 0) {
binding.outlineTextview.visibility = View.GONE
binding.outlinePicker.visibility = View.GONE
} else {
binding.outlineTextview.visibility = View.VISIBLE
binding.outlinePicker.visibility = View.VISIBLE
if (backgroundIndex == 1) {
binding.outlineTextview.text = getString(R.string.thickness)
} else {
binding.outlineTextview.text = getString(R.string.intensity)
}
}
binding.textPreviewBackgroundDark.setBackgroundColor(
Color.parseColor(
ColorTransparentUtils.transparentColor(
context.getColor(R.color.md_theme_dark_background),
if (storage.isInvertedEnabled()) {
abs((storage.getBackgroundTransparency() * 5))
} else {
abs((storage.getBackgroundTransparency() * 5) - 100)
}
))
)
val bitmap = CanvasText.drawText(context, true)
binding.textPreview.setImageBitmap(bitmap)
}
private fun save() {
storage.saveSettings(
textSize = binding.textSizePicker.value,
inverted = binding.switchInvert.isChecked,
textTransparency = binding.textTransparencyPicker.value,
bgTransparency = binding.bgTransparencyPicker.value,
random = binding.switchRandom.isChecked,
widgetPosition = widgetGravity,
backgroundType = backgroundIndex,
typefaceIndex = typefaceIndex,
typefaceStyleIndex = typefaceStyleIndex,
outlineSize = binding.outlinePicker.value.toFloat()
)
}
override fun onPause() {
save()
super.onPause()
}
}
@@ -4,18 +4,22 @@ import android.annotation.SuppressLint
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.PopupMenu
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.transition.TransitionManager
import com.denizd.textbasic.BuildConfig
import com.denizd.textbasic.R
import com.denizd.textbasic.databinding.FragmentSettingsNewBinding
import com.denizd.textbasic.db.QuoteStorage
import com.denizd.textbasic.sheet.TextSheet
import com.denizd.textbasic.util.SettingsPreference
import com.denizd.textbasic.util.viewBinding
import com.denizd.textbasic.widget.CanvasText
import com.google.android.material.button.MaterialButton
import java.util.Calendar
class SettingsNewFragment : BaseFragment(R.layout.fragment_settings_new) {
@@ -142,42 +146,6 @@ class SettingsNewFragment : BaseFragment(R.layout.fragment_settings_new) {
SettingsPreference.TEXT_SIZE,
)
// --- text transparency --- //
binding.textTransparency.text = storage.getInt(SettingsPreference.TEXT_TRANSPARENCY, 100).toString()
binding.buttonTextTransparencyDecreaseFast.setOnClickAction(
0,
100,
isPositive = false,
isFast = true,
binding.textTransparency,
SettingsPreference.TEXT_TRANSPARENCY,
)
binding.buttonTextTransparencyDecrease.setOnClickAction(
0,
100,
isPositive = false,
isFast = false,
binding.textTransparency,
SettingsPreference.TEXT_TRANSPARENCY,
)
binding.buttonTextTransparencyIncrease.setOnClickAction(
0,
100,
isPositive = true,
isFast = false,
binding.textTransparency,
SettingsPreference.TEXT_TRANSPARENCY,
)
binding.buttonTextTransparencyIncreaseFast.setOnClickAction(
0,
100,
isPositive = true,
isFast = true,
binding.textTransparency,
SettingsPreference.TEXT_TRANSPARENCY,
)
// --- highlight style --- //
binding.toggleGroupHighlightStyle.apply {
check(checkBackgroundIntensity(storage.getBackgroundType()))
@@ -244,42 +212,6 @@ class SettingsNewFragment : BaseFragment(R.layout.fragment_settings_new) {
SettingsPreference.HIGHLIGHT_INTENSITY,
)
// --- text highlight transparency --- //
binding.textHighlightTransparency.text = storage.getInt(SettingsPreference.HIGHLIGHT_TRANSPARENCY, 100).toString()
binding.buttonHighlightTransparencyDecreaseFast.setOnClickAction(
0,
100,
isPositive = false,
isFast = true,
binding.textHighlightTransparency,
SettingsPreference.HIGHLIGHT_TRANSPARENCY,
)
binding.buttonHighlightTransparencyDecrease.setOnClickAction(
0,
100,
isPositive = false,
isFast = false,
binding.textHighlightTransparency,
SettingsPreference.HIGHLIGHT_TRANSPARENCY,
)
binding.buttonHighlightTransparencyIncrease.setOnClickAction(
0,
100,
isPositive = true,
isFast = false,
binding.textHighlightTransparency,
SettingsPreference.HIGHLIGHT_TRANSPARENCY,
)
binding.buttonHighlightTransparencyIncreaseFast.setOnClickAction(
0,
100,
isPositive = true,
isFast = true,
binding.textHighlightTransparency,
SettingsPreference.HIGHLIGHT_TRANSPARENCY,
)
// --- randomise order entries --- //
binding.switchOrderRandom.apply {
isChecked = storage.isOrderRandom()
@@ -306,6 +238,21 @@ class SettingsNewFragment : BaseFragment(R.layout.fragment_settings_new) {
}
}
// Set click listener for showing licences dialogue
binding.buttonLicences.setOnClickListener {
openBottomSheet(
TextSheet().also { sheet ->
val bundle = Bundle()
bundle.putString("header", getString(R.string.sheet_licences_header))
bundle.putString("content", getString(
R.string.sheet_licences_content,
Calendar.getInstance().get(Calendar.YEAR).toString(),
))
sheet.arguments = bundle
}
)
}
/*
* Display the app's version as set in the build.gradle. Also display if the app is a
* development version, and if so, display build timestamp.
@@ -335,22 +282,28 @@ class SettingsNewFragment : BaseFragment(R.layout.fragment_settings_new) {
* Retrieves which button to check for the highlight, and sets the visibility of the intensity
* modifying layout accordingly.
*/
private fun checkBackgroundIntensity(index: Int): Int = when (index) {
0 -> { // background
binding.layoutIntensity.visibility = View.GONE
R.id.toggle_button_highlight_background
}
1 -> { // stroke
binding.layoutIntensity.visibility = View.VISIBLE
R.id.toggle_button_highlight_stroke
}
2 -> { // shadow
binding.layoutIntensity.visibility = View.VISIBLE
R.id.toggle_button_highlight_shadow
}
else -> { // none
binding.layoutIntensity.visibility = View.GONE
R.id.toggle_button_highlight_none
private fun checkBackgroundIntensity(index: Int): Int {
TransitionManager.beginDelayedTransition(binding.root.parent as ViewGroup)
return when (index) {
0 -> { // background
binding.layoutIntensity.visibility = View.GONE
R.id.toggle_button_highlight_background
}
1 -> { // stroke
binding.layoutIntensity.visibility = View.VISIBLE
R.id.toggle_button_highlight_stroke
}
2 -> { // shadow
binding.layoutIntensity.visibility = View.VISIBLE
R.id.toggle_button_highlight_shadow
}
else -> { // none
binding.layoutIntensity.visibility = View.GONE
R.id.toggle_button_highlight_none
}
}
}
@@ -0,0 +1,34 @@
package com.denizd.textbasic.sheet
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
/**
* Bottom sheet super class providing common functionality. All bottom sheets should inherit from
* this.
*
* @param layoutId ID of the layout of the bottom sheet
*/
open class AppSheet(@LayoutRes private val layoutId: Int) : BottomSheetDialogFragment() {
// Internal context object
private lateinit var _context: Context
/**
* Get non-null context. Only valid after onAttach().
*/
override fun getContext(): Context = _context
override fun onAttach(context: Context) {
super.onAttach(context)
_context = context
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
LayoutInflater.from(context).inflate(layoutId, container, false)
}
@@ -0,0 +1,35 @@
package com.denizd.textbasic.sheet
import android.os.Bundle
import android.view.View
import com.denizd.textbasic.R
import com.denizd.textbasic.databinding.SheetTextBinding
import com.denizd.textbasic.util.viewBinding
/**
* Bottom sheet used for displaying any sort of text to the user.
*/
class TextSheet : AppSheet(R.layout.sheet_text) {
// View binding
private val binding: SheetTextBinding by viewBinding(SheetTextBinding::bind)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Retrieve headline for the window
val header = arguments?.getString("header") ?: ""
// Check whether an ID has passed to use LiveData
val content = arguments?.getString("content") ?: ""
binding.textHeader.text = header
binding.textContent.text = content
// Set up a simple X button to be able to close the sheet
binding.buttonCancel.setOnClickListener {
// Do nothing and dismiss the sheet
dismiss()
}
}
}
@@ -5,7 +5,9 @@ import com.denizd.textbasic.db.QuoteStorage
enum class SettingsPreference(val key: String) {
TEXT_SIZE(QuoteStorage.KEY_TEXT_SIZE),
TEXT_TRANSPARENCY(QuoteStorage.KEY_TEXT_TRANSPARENCY),
HIGHLIGHT_INTENSITY(QuoteStorage.KEY_OUTLINE_SIZE_NEW), // TODO
TEXT_COLOUR("textcolour"),
HIGHLIGHT_INTENSITY(QuoteStorage.KEY_OUTLINE_SIZE_NEW),
HIGHLIGHT_TRANSPARENCY(QuoteStorage.KEY_BG_TRANSPARENCY),
HIGHLIGHT_COLOUR("highlightcolour"),
;
}