Compare commits

..

2 Commits

Author SHA1 Message Date
fgerber
6e5e5c944f Push the long-awaited changes
- Apply consistent blue theming, including setting to switch between dark/light modes
- Hide edit button and all checkboxes in front of continents
- Use material design for clickable buttons and checkboxes
- Show percentages of visited countries per continent (possibly enable/disable in settings?)
2024-01-17 22:56:51 +01:00
fgerber
44b0cccbd9 Perform some layout changes
The idea is to make it as practical as possible for the user:
- I would use the long click for something else, maybe a small menu about the continent/country
- The edit button at the top should enable/disable the checkboxes (but it should be aligned on the right)
- Issue: When enabling a country, then the whole continent it belongs to, and then disabling the continent again, there is no undetermined state anymore, the box is unchecked
2024-01-17 22:56:51 +01:00
22 changed files with 386 additions and 78 deletions

View File

@ -5,12 +5,12 @@ plugins {
android { android {
namespace 'net.helcel.beendroid' namespace 'net.helcel.beendroid'
compileSdk 33 compileSdk 34
defaultConfig { defaultConfig {
applicationId 'net.helcel.beendroid' applicationId 'net.helcel.beendroid'
minSdk 28 minSdk 28
targetSdk 33 targetSdk 34
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"

View File

@ -16,14 +16,21 @@
> >
<activity <activity
android:name=".activity.MainActivity" android:name=".activity.MainActivity"
android:exported="true" android:exported="true" >
android:theme="@style/Theme.Beendroid.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".activity.SettingsActivity"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </application>
</manifest> </manifest>

View File

@ -1,17 +1,24 @@
package net.helcel.beendroid.activity package net.helcel.beendroid.activity
import android.content.Context import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources.getDrawable
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.google.android.material.checkbox.MaterialCheckBox import com.google.android.material.checkbox.MaterialCheckBox
import net.helcel.beendroid.R import net.helcel.beendroid.R
import net.helcel.beendroid.countries.GeoLoc import net.helcel.beendroid.countries.GeoLoc
import net.helcel.beendroid.countries.LocType
import net.helcel.beendroid.countries.Visited import net.helcel.beendroid.countries.Visited
import java.util.* import java.util.*
@ -61,15 +68,14 @@ class FoldingListAdapter(
private val visited: Visited, private val visited: Visited,
) : RecyclerView.ViewHolder(itemView) { ) : RecyclerView.ViewHolder(itemView) {
private val textView: TextView private val textView: TextView
private val expand: ImageView //private val expand: MaterialButton
private val checkBox: MaterialCheckBox private val checkBox: MaterialCheckBox
private val subItemView: View private val subItemView: View
private val list: RecyclerView private val list: RecyclerView
init { init {
textView = itemView.findViewById(R.id.textView) textView = itemView.findViewById(R.id.textView)
expand = itemView.findViewById(R.id.expand) //expand = itemView.findViewById(R.id.expand)
expand.setImageDrawable(AppCompatResources.getDrawable(ctx,R.drawable.chevron_right_solid))
checkBox = itemView.findViewById(R.id.checkBox) checkBox = itemView.findViewById(R.id.checkBox)
subItemView = itemView.findViewById(R.id.sub_item) subItemView = itemView.findViewById(R.id.sub_item)
list = itemView.findViewById(R.id.list_list) list = itemView.findViewById(R.id.list_list)
@ -77,13 +83,42 @@ class FoldingListAdapter(
} }
fun bind(el: Pair<GeoLoc, Boolean>, parentLambda: () -> Unit) { fun bind(el: Pair<GeoLoc, Boolean>, parentLambda: () -> Unit) {
expand.rotation = if(el.second) 90f else 0f //expand.rotation = if(el.second) 90f else 0f
subItemView.visibility = if (el.second) View.VISIBLE else View.GONE subItemView.visibility = if (el.second) View.VISIBLE else View.GONE
expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.GONE //expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.INVISIBLE
textView.text = el.first.fullName textView.text = el.first.fullName
if (el.first.type == LocType.GROUP) {
textView.setTypeface(null, Typeface.BOLD)
val colorGrayTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.textColorTertiary, colorGrayTyped, true)
val color = Color.valueOf(colorGrayTyped.data)
textView.setBackgroundColor(Color.valueOf(color.red(), color.green(), color.blue(), 0.5f).toArgb())
checkBox.visibility = View.INVISIBLE
el.first.children.apply {
val nbCountries = this.size
val nbVisited = this.map { if (visited.visited(it)) 1 else 0 }.reduce{ a, b -> (a + b) }
val ratio = nbVisited.toFloat() / nbCountries.toFloat()
val percentage = (ratio * 100).toInt()
textView.text = "${textView.text as String} (${percentage}%)"
}
} else {
val colorBackgroundTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true)
textView.backgroundTintList = null
textView.background = ColorDrawable(colorBackgroundTyped.data)
textView.isActivated = false
val layoutParam = checkBox.layoutParams
layoutParam.width = 125
checkBox.layoutParams = layoutParam
checkBox.visibility = View.VISIBLE
}
checkBox.checkedState = checkBox.checkedState =
if(visited.visited(el.first)) MaterialCheckBox.STATE_CHECKED if (visited.visited(el.first)) MaterialCheckBox.STATE_CHECKED
else if (el.first.children.any { visited.visited(it) }) MaterialCheckBox.STATE_INDETERMINATE else if (el.first.children.any { visited.visited(it) }) MaterialCheckBox.STATE_INDETERMINATE
else MaterialCheckBox.STATE_UNCHECKED else MaterialCheckBox.STATE_UNCHECKED
@ -93,13 +128,13 @@ class FoldingListAdapter(
fun addListeners(expandLambda: ()->Boolean, visitedLambda: (Boolean)->Unit) { fun addListeners(expandLambda: ()->Boolean, visitedLambda: (Boolean)->Unit) {
textView.setOnClickListener { checkBox.toggle() } textView.setOnClickListener { expandLambda() }
checkBox.addOnCheckedStateChangedListener { _, e -> checkBox.addOnCheckedStateChangedListener { _, e ->
visitedLambda(e == MaterialCheckBox.STATE_CHECKED) visitedLambda(e == MaterialCheckBox.STATE_CHECKED)
} }
textView.setOnLongClickListener{ expandLambda() } //textView.setOnLongClickListener{ checkBox.toggle(); true }
expand.setOnClickListener { expandLambda() } //expand.setOnClickListener { expandLambda() }
} }
} }

View File

@ -1,9 +1,20 @@
package net.helcel.beendroid.activity package net.helcel.beendroid.activity
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.MenuProvider
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.caverock.androidsvg.RenderOptions import com.caverock.androidsvg.RenderOptions
@ -17,6 +28,8 @@ import net.helcel.beendroid.svg.PSVGWrapper
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var sharedPreferences: SharedPreferences
private lateinit var map : SVGImageView private lateinit var map : SVGImageView
private lateinit var list : RecyclerView private lateinit var list : RecyclerView
@ -30,26 +43,70 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
canvas.drawRGB(255, 255, 255) // Create action bar
val colorPrimaryTyped = TypedValue()
theme.resolveAttribute(android.R.attr.colorPrimary, colorPrimaryTyped, true)
supportActionBar?.setBackgroundDrawable(ColorDrawable(colorPrimaryTyped.data))
// Fetch shared preferences to restore app theme upon startup
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
SettingsFragment.setTheme(this, sharedPreferences.getString(getString(R.string.key_theme), getString(R.string.system)))
// Create menu in action bar
addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.menu_main, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.action_edit -> {
// TODO: Enable editing selected countries
true
}
R.id.action_settings -> {
// Open settings
startActivity(Intent(this@MainActivity, SettingsActivity::class.java))
true
}
else -> {
false
}
}
}
})
// Restore visited countries
visited = Visited(this) visited = Visited(this)
visited.load() visited.load()
// Wrap lists of countries
psvg = PSVGWrapper(this) psvg = PSVGWrapper(this)
css = CSSWrapper(visited) css = CSSWrapper(visited)
// Populate map from list of countries
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
map = findViewById(R.id.map) map = findViewById(R.id.map)
map.setImageBitmap(bitmap) map.setImageBitmap(bitmap)
refreshMap() refreshMap()
// Populate list below the map
list = findViewById(R.id.list) list = findViewById(R.id.list)
list.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) list.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { refreshMap() } list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { refreshMap() }
} }
private fun refreshMap(){ private fun refreshMap(){
psvg.get().renderToCanvas(canvas,RenderOptions.create().css(css.get())) // Set or reset background (replaces canvas.drawColor(0, 0, 0))
val colorBackgroundTyped = TypedValue()
theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true)
canvas.drawColor(colorBackgroundTyped.data)
// Render all countries and visited ones
psvg.getFill().renderToCanvas(canvas, RenderOptions.create().css(css.get()))
// Render all contours in the same color as the background to make them much clearer
psvg.getDraw().renderToCanvas(canvas)
} }
} }

View File

@ -0,0 +1,39 @@
package net.helcel.beendroid.activity
import android.graphics.drawable.ColorDrawable
import android.content.Intent
import android.os.Bundle
import android.os.PersistableBundle
import android.util.TypedValue
import android.view.MenuItem
import androidx.activity.addCallback
import androidx.appcompat.app.AppCompatActivity
import net.helcel.beendroid.R
class SettingsActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Bind activity to XML layout with fragment view
setContentView(R.layout.activity_settings)
// Create action bar
val colorPrimaryTyped = TypedValue()
theme.resolveAttribute(android.R.attr.colorPrimary, colorPrimaryTyped, true)
supportActionBar?.setBackgroundDrawable(ColorDrawable(colorPrimaryTyped.data))
supportActionBar?.title = getString(R.string.action_settings)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
// Populate activity with settings fragment
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_view, SettingsFragment())
.commit()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Configure on back pressed
finish()
return super.onOptionsItemSelected(item)
}
}

View File

@ -0,0 +1,54 @@
package net.helcel.beendroid.activity
import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.TypedValue
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.ListPreference
import androidx.preference.PreferenceFragmentCompat
import net.helcel.beendroid.R
class SettingsFragment: PreferenceFragmentCompat() {
private lateinit var themePreference: ListPreference
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.fragment_settings, rootKey)
// Select Light/Dark/System Mode
themePreference = findPreference(getString(R.string.key_theme))!!
themePreference.setOnPreferenceChangeListener { _, key ->
setTheme(requireContext(), key as String)
}
}
companion object {
fun setTheme(context: Context, key: String?): Boolean {
when (key) {
context.getString(R.string.system) -> {
// Set SYSTEM Theme
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
return true
}
context.getString(R.string.light) -> {
// Set LIGHT Theme
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
return true
}
context.getString(R.string.dark) -> {
// Set DARK Theme
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
return true
}
else -> {
return false
}
}
}
}
}

View File

@ -10,13 +10,13 @@ class Visited(ctx: Context) {
fun load() { fun load() {
Group.values().forEach { Group.entries.forEach {
locs[it] = pref.getBoolean(it.code, false) locs[it] = pref.getBoolean(it.code, false)
} }
Country.values().forEach { Country.entries.forEach {
locs[it] = pref.getBoolean(it.code, false) locs[it] = pref.getBoolean(it.code, false)
} }
State.values().forEach { State.entries.forEach {
locs[it] = pref.getBoolean(it.code, false) locs[it] = pref.getBoolean(it.code, false)
} }
editor.apply() editor.apply()

View File

@ -1,20 +1,23 @@
package net.helcel.beendroid.svg package net.helcel.beendroid.svg
import android.util.TypedValue
import net.helcel.beendroid.countries.Visited import net.helcel.beendroid.countries.Visited
import net.helcel.beendroid.countries.World import net.helcel.beendroid.countries.World
class CSSWrapper(private val visited: Visited) { class CSSWrapper(private val visited: Visited) {
private val colorPrimary = "#0187FF"
fun get() : String { fun get() : String {
return listOf(World.WWW.children return listOf(World.WWW.children
.filter { visited.visited(it)} .filter { visited.visited(it)}
.map { ".${it.code}{fill:blue;}"} .map { ".${it.code}{fill:$colorPrimary;}"}
.fold(""){acc, s-> acc + s}, .fold(""){acc, s-> acc + s},
World.WWW.children World.WWW.children
.filter { !visited.visited(it) } .filter { !visited.visited(it) }
.map { cg -> cg.children .map { cg -> cg.children
.filter { visited.visited(it) } .filter { visited.visited(it) }
.map { ".${it.code}{fill:blue;}"} .map { ".${it.code}{fill:$colorPrimary;}"}
.fold(""){acc, s-> acc + s} .fold(""){acc, s-> acc + s}
}.fold(""){acc,s->acc+s}, }.fold(""){acc,s->acc+s},
).fold(""){acc,s-> acc+s} ).fold(""){acc,s-> acc+s}

View File

@ -1,7 +1,12 @@
package net.helcel.beendroid.svg package net.helcel.beendroid.svg
import android.content.Context import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.util.Log
import android.util.TypedValue
import com.caverock.androidsvg.SVG import com.caverock.androidsvg.SVG
import net.helcel.beendroid.R
import net.helcel.beendroid.countries.Country import net.helcel.beendroid.countries.Country
import net.helcel.beendroid.countries.GeoLoc import net.helcel.beendroid.countries.GeoLoc
import net.helcel.beendroid.countries.World import net.helcel.beendroid.countries.World
@ -11,8 +16,20 @@ class PSVGWrapper(ctx: Context) {
private val cm = HashMap<GeoLoc, PSVGLoader>() private val cm = HashMap<GeoLoc, PSVGLoader>()
private var fm = "" private var fm = ""
private val colorForeground: String
private val colorBackground: String
init { init {
Country.values().forEach { val colorSecondaryTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.textColorTertiary, colorSecondaryTyped, true)
colorForeground = "\"#${Integer.toHexString(colorSecondaryTyped.data).subSequence(2, 8)}\""
val colorBackgroundTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true)
colorBackground = "\"#${Integer.toHexString(colorBackgroundTyped.data).subSequence(2, 8)}\""
Country.entries.forEach {
cm[it] = PSVGLoader(ctx, it, Level.ZERO).load() cm[it] = PSVGLoader(ctx, it, Level.ZERO).load()
} }
build() build()
@ -31,12 +48,12 @@ class PSVGWrapper(ctx: Context) {
}.fold("") { acc, e -> acc + e } }.fold("") { acc, e -> acc + e }
} }
fun get(): SVG { fun getFill(): SVG {
return SVG.getFromString("<svg id=\"map\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"1200\" x=\"0\" y=\"0\" >$fm</svg>") return SVG.getFromString("<svg id=\"map\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"1200\" x=\"0\" y=\"0\" fill=${colorForeground}>$fm</svg>")
} }
fun getDraw(): SVG {
return SVG.getFromString("<svg id=\"map\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"1200\" x=\"0\" y=\"0\" fill-opacity=\"0\" stroke=${colorBackground}>$fm</svg>")
}
} }

View File

@ -4,6 +4,6 @@
android:viewportWidth="320" android:viewportWidth="320"
android:viewportHeight="512"> android:viewportHeight="512">
<path <path
android:fillColor="#FFFFFFFF" android:fillColor="?attr/colorOnBackground"
android:pathData="M310.6,233.4c12.5,12.5 12.5,32.8 0,45.3l-192,192c-12.5,12.5 -32.8,12.5 -45.3,0s-12.5,-32.8 0,-45.3L242.7,256 73.4,86.6c-12.5,-12.5 -12.5,-32.8 0,-45.3s32.8,-12.5 45.3,0l192,192z"/> android:pathData="M310.6,233.4c12.5,12.5 12.5,32.8 0,45.3l-192,192c-12.5,12.5 -32.8,12.5 -45.3,0s-12.5,-32.8 0,-45.3L242.7,256 73.4,86.6c-12.5,-12.5 -12.5,-32.8 0,-45.3s32.8,-12.5 45.3,0l192,192z"/>
</vector> </vector>

View File

@ -0,0 +1,10 @@
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="@color/white"
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android" >
<path
android:fillColor="?attr/colorPrimary"
android:pathData="M12,2C6.49,2 2,6.49 2,12s4.49,10 10,10c1.38,0 2.5,-1.12 2.5,-2.5c0,-0.61 -0.23,-1.2 -0.64,-1.67c-0.08,-0.1 -0.13,-0.21 -0.13,-0.33c0,-0.28 0.22,-0.5 0.5,-0.5H16c3.31,0 6,-2.69 6,-6C22,6.04 17.51,2 12,2zM17.5,13c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5C19,12.33 18.33,13 17.5,13zM14.5,9C13.67,9 13,8.33 13,7.5C13,6.67 13.67,6 14.5,6S16,6.67 16,7.5C16,8.33 15.33,9 14.5,9zM5,11.5C5,10.67 5.67,10 6.5,10S8,10.67 8,11.5C8,12.33 7.33,13 6.5,13S5,12.33 5,11.5zM11,7.5C11,8.33 10.33,9 9.5,9S8,8.33 8,7.5C8,6.67 8.67,6 9.5,6S11,6.67 11,7.5z" />
</vector>

View File

@ -2,10 +2,11 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:theme="@style/Theme.Beendroid"
android:layout_height="fill_parent"> android:layout_width="match_parent"
android:layout_height="match_parent">
<com.caverock.androidsvg.SVGImageView <com.caverock.androidsvg.SVGImageView
android:id="@+id/map" android:id="@+id/map"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -15,7 +16,8 @@
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/sv" android:id="@+id/sv"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:scrollbars="vertical"
android:layout_weight="1"> android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView

View File

@ -0,0 +1,16 @@
<?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:orientation="vertical"
android:theme="@style/Theme.Beendroid"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.SettingsActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -9,54 +9,61 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ImageView <com.google.android.material.button.MaterialButton
android:id="@+id/expand" android:id="@+id/textView"
android:layout_width="48dp" android:layout_width="0dp"
android:layout_height="48dp" android:layout_height="50dp"
android:contentDescription=">" app:cornerRadius="0dp"
android:scaleX="0.5" android:gravity="start|center_vertical"
android:scaleY="0.5" android:textColor="?attr/colorOnBackground"
android:visibility="visible" android:textAllCaps="false"
app:layout_constraintEnd_toStartOf="@+id/textView" android:textAppearance="?attr/textAppearanceBody2"
android:clickable="true"
android:focusable="true"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:insetTop="4dp"
android:insetBottom="4dp"
app:layout_constraintBottom_toBottomOf="@id/text2checkbox"
app:layout_constraintEnd_toStartOf="@id/text2checkbox"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" /> app:layout_constraintVertical_bias="1.0" />
<Space
android:id="@+id/text2checkbox"
android:layout_width="0.01dp"
android:layout_height="50dp"
android:gravity="start|center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="@id/textView"
app:layout_constraintEnd_toStartOf="@id/checkBox"
app:layout_constraintStart_toEndOf="@id/textView" />
<com.google.android.material.checkbox.MaterialCheckBox <com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkBox" android:id="@+id/checkBox"
android:layout_width="wrap_content" android:layout_width="0.01dp"
android:layout_height="wrap_content" android:layout_height="50dp"
app:checkedState="indeterminate" app:checkedState="indeterminate"
app:layout_constraintBottom_toBottomOf="@+id/textView" android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/textView"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1" app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toEndOf="@+id/textView" app:layout_constraintStart_toEndOf="@id/textView"
app:layout_constraintTop_toTopOf="@+id/textView" app:layout_constraintTop_toTopOf="@id/textView"
app:layout_constraintVertical_bias="0.5" /> app:layout_constraintVertical_bias="0.5" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="start|center_vertical"
android:textColor="@color/design_default_color_on_primary"
app:layout_constraintBottom_toBottomOf="@id/checkBox"
app:layout_constraintEnd_toStartOf="@+id/checkBox"
app:layout_constraintStart_toEndOf="@+id/expand"
app:layout_constraintTop_toTopOf="@+id/expand"
app:layout_constraintVertical_bias="1.0" />
<LinearLayout <LinearLayout
android:id="@+id/sub_item" android:id="@+id/sub_item"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="32dp" android:layout_marginStart="0dp"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/checkBox"> app:layout_constraintTop_toBottomOf="@id/checkBox">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_list" android:id="@+id/list_list"

View File

@ -1,7 +1,16 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context="net.helcel.beendroid.activity.MainActivity"> tools:context="net.helcel.beendroid.activity.MainActivity" >
<item
android:id="@+id/action_edit"
android:orderInCategory="100"
android:icon="@drawable/edit"
android:visible="false"
android:title="@string/action_edit"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/action_settings" android:id="@+id/action_settings"
android:orderInCategory="100" android:orderInCategory="100"

View File

@ -1,5 +1,9 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Beendroid" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Theme.Beendroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimary">@color/teal_700</item>
<item name="android:colorPrimary">@color/teal_700</item>
<item name="android:textColorTertiary">@color/darkgray</item>
<item name="android:statusBarColor">?attr/colorPrimary</item> <item name="android:statusBarColor">?attr/colorPrimary</item>
<item name="colorAccent">?attr/colorPrimary</item>
</style> </style>
</resources> </resources>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="entries_theme" >
<item>@string/system</item>
<item>@string/light</item>
<item>@string/dark</item>
</string-array>
</resources>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03AFFF</color>
<color name="teal_700">#FF0187FF</color>
<color name="yellowish">#FFFFDD00</color>
<color name="black">#FF000000</color>
<color name="darkgray">#FF555555</color>
<color name="lightgray">#FFBBBBBB</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Beendroid</string> <string name="app_name">BeenDroid</string>
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="action_edit">Edit</string>
<string name="welcome">Welcome!</string> <string name="welcome">Welcome!</string>
<string name="change_lang">Change language</string> <string name="change_lang">Change language</string>
<string name="key_theme">App theme</string>
<string name="system">Same as system</string>
<string name="light">Light theme</string>
<string name="dark">Dark theme</string>
</resources> </resources>

View File

@ -1,14 +1,9 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Beendroid" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Theme.Beendroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimary">@color/teal_700</item>
<item name="android:colorPrimary">@color/teal_700</item>
<item name="android:textColorTertiary">@color/lightgray</item>
<item name="android:statusBarColor">?attr/colorPrimary</item> <item name="android:statusBarColor">?attr/colorPrimary</item>
<item name="colorAccent">?attr/colorPrimary</item>
</style> </style>
<style name="Theme.Beendroid.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="Theme.Beendroid.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="Theme.Beendroid.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources> </resources>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@style/Theme.Beendroid">
<ListPreference
app:enabled="true"
app:key="@string/key_theme"
app:icon="@drawable/palette"
app:title="@string/key_theme"
app:useSimpleSummaryProvider="true"
app:entries="@array/entries_theme"
app:entryValues="@array/entries_theme"
app:defaultValue="@string/system" />
</PreferenceScreen>