Layout Changes (#25)

Co-authored-by: fgerber <frederic.gerber@mydoli.ch>
Co-authored-by: soraefir <soraefir+git@pm.me>
Reviewed-on: helcel/beendroid#25
Co-authored-by: fgerber <fred@mydoli.ch>
Co-committed-by: fgerber <fred@mydoli.ch>
This commit is contained in:
fgerber 2024-01-20 01:21:41 +01:00 committed by sora
parent c0cc1e5649
commit 3c1080e8c2
31 changed files with 668 additions and 287 deletions

View File

@ -1,16 +1,17 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.mikepenz.aboutlibraries.plugin' version '10.10.0'
}
android {
namespace 'net.helcel.beendroid'
compileSdk 33
compileSdk 34
defaultConfig {
applicationId 'net.helcel.beendroid'
minSdk 28
targetSdk 33
targetSdk 34
versionCode 1
versionName "1.0"
@ -50,5 +51,6 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'com.caverock:androidsvg-aar:1.4'
implementation "com.mikepenz:aboutlibraries:10.10.0"
}

View File

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

View File

@ -0,0 +1,31 @@
package net.helcel.beendroid.activity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import net.helcel.beendroid.databinding.FragmentAboutBinding
class AboutFragment: Fragment() {
private var _binding: FragmentAboutBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAboutBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -1,17 +1,20 @@
package net.helcel.beendroid.activity
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.checkbox.MaterialCheckBox
import net.helcel.beendroid.R
import net.helcel.beendroid.countries.GeoLoc
import net.helcel.beendroid.countries.LocType
import net.helcel.beendroid.countries.Visited
import java.util.*
@ -36,10 +39,7 @@ class FoldingListAdapter(
override fun onBindViewHolder(holder: FoldingListViewHolder, position: Int) {
val el = cg.toList()[position]
holder.bind(el) {
notifyItemChanged(position)
parentLambda()
}
holder.bind(el) { parentLambda() }
holder.addListeners( {
if (!el.first.isEnd) {
@ -60,46 +60,52 @@ class FoldingListAdapter(
class FoldingListViewHolder(private val ctx: Context, itemView: View,
private val visited: Visited,
) : RecyclerView.ViewHolder(itemView) {
private val textView: TextView
private val expand: ImageView
private val checkBox: MaterialCheckBox
private val subItemView: View
private val list: RecyclerView
private val textView: TextView = itemView.findViewById(R.id.textView)
private val checkBox: MaterialCheckBox = itemView.findViewById(R.id.checkBox)
private val subItemView: View = itemView.findViewById(R.id.sub_item)
private val list: RecyclerView = itemView.findViewById(R.id.list_list)
init {
textView = itemView.findViewById(R.id.textView)
expand = itemView.findViewById(R.id.expand)
expand.setImageDrawable(AppCompatResources.getDrawable(ctx,R.drawable.chevron_right_solid))
checkBox = itemView.findViewById(R.id.checkBox)
subItemView = itemView.findViewById(R.id.sub_item)
list = itemView.findViewById(R.id.list_list)
list.layoutManager = LinearLayoutManager(ctx, RecyclerView.VERTICAL, false)
}
fun bind(el: Pair<GeoLoc, Boolean>, parentLambda: () -> Unit) {
expand.rotation = if(el.second) 90f else 0f
subItemView.visibility = if (el.second) View.VISIBLE else View.GONE
expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.GONE
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.panelColorBackground, colorGrayTyped, true)
val color = Color.valueOf(colorGrayTyped.data)
textView.setBackgroundColor(Color.valueOf(color.red(), color.green(), color.blue(), 0.5f).toArgb())
list.adapter = FoldingListAdapter(ctx, el.first.children,visited, parentLambda)
textView.parent.parent.requestChildFocus(textView,textView)
} 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 =
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 MaterialCheckBox.STATE_UNCHECKED
textView.parent.parent.requestChildFocus(textView,textView)
list.adapter = FoldingListAdapter(ctx, el.first.children,visited, parentLambda)
}
fun addListeners(expandLambda: ()->Boolean, visitedLambda: (Boolean)->Unit) {
textView.setOnClickListener { checkBox.toggle() }
textView.setOnClickListener { expandLambda() }
checkBox.addOnCheckedStateChangedListener { _, e ->
visitedLambda(e == MaterialCheckBox.STATE_CHECKED)
}
textView.setOnLongClickListener{ expandLambda() }
expand.setOnClickListener { expandLambda() }
}
}

View File

@ -0,0 +1,41 @@
package net.helcel.beendroid.activity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import net.helcel.beendroid.R
import net.helcel.beendroid.databinding.FragmentLicenseBinding
import com.mikepenz.aboutlibraries.LibsBuilder
class LicenseFragment: Fragment() {
private var _binding: FragmentLicenseBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentLicenseBinding.inflate(inflater, container, false)
val librariesFragment = LibsBuilder()
.withLicenseShown(true)
.supportFragment()
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.license_fragment_view, librariesFragment)
.commit()
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -1,9 +1,19 @@
package net.helcel.beendroid.activity
import kotlinx.coroutines.*
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.TypedValue
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.MenuProvider
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.caverock.androidsvg.RenderOptions
@ -17,6 +27,8 @@ import net.helcel.beendroid.svg.PSVGWrapper
class MainActivity : AppCompatActivity() {
private lateinit var sharedPreferences: SharedPreferences
private lateinit var map : SVGImageView
private lateinit var list : RecyclerView
@ -24,32 +36,103 @@ class MainActivity : AppCompatActivity() {
private lateinit var psvg : PSVGWrapper
private lateinit var css : CSSWrapper
private var processor: ImageProcessor = ImageProcessor({ refreshMapCompute() },{ refreshMapDisplay(it) })
private val bitmap: Bitmap = Bitmap.createBitmap(1200,900, Bitmap.Config.ARGB_8888)
private val canvas = Canvas(bitmap)
override fun onCreate(savedInstanceState: Bundle?) {
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_stats -> {
// TODO: Write stats activity
true
}
R.id.action_settings -> {
// Open settings
startActivity(Intent(this@MainActivity, SettingsActivity::class.java))
true
}
else -> {
false
}
}
}
})
// Restore visited countries
visited = Visited(this)
visited.load()
// Wrap lists of countries
psvg = PSVGWrapper(this)
css = CSSWrapper(visited)
// Populate map from list of countries
setContentView(R.layout.activity_main)
map = findViewById(R.id.map)
map.setImageBitmap(bitmap)
refreshMapDisplay(refreshMapCompute())
refreshMap()
// Populate list below the map
list = findViewById(R.id.list)
list.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { refreshMap() }
list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { processor.process() }
}
private fun refreshMap(){
psvg.get().renderToCanvas(canvas,RenderOptions.create().css(css.get()))
private fun refreshMapDisplay(css_value: String){
// 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_value))
// Render all contours in the same color as the background to make them much clearer
psvg.getDraw().renderToCanvas(canvas)
}
private fun refreshMapCompute() : String {
return css.get()
}
class ImageProcessor(private val refreshMapCompute: ()->String, private val refreshMapDisplay: (String)->Unit) {
private var currentJob : Job? = null
fun process() {
currentJob?.cancel()
currentJob = CoroutineScope(Dispatchers.Main).launch {
try {
refreshMapDisplay(refreshMapCompute())
} catch (_: CancellationException) {
}
}
}
}
}

View File

@ -0,0 +1,62 @@
package net.helcel.beendroid.activity
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.TypedValue
import android.view.MenuItem
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(), getString(R.string.action_settings))
.commit()
// Change title in action bar according to current fragment
supportFragmentManager.addFragmentOnAttachListener { _, _ ->
supportActionBar?.title = supportFragmentManager.findFragmentById(R.id.fragment_view).let {
when (it) {
is LicenseFragment -> getString(R.string.licenses)
is AboutFragment -> getString(R.string.about)
else -> getString(R.string.action_settings)
}
}
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Configure on back pressed
supportFragmentManager.findFragmentById(R.id.fragment_view).let {
when (it) {
is LicenseFragment, is AboutFragment -> {
supportFragmentManager.beginTransaction()
.remove(it)
.commit()
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_view, SettingsFragment(), getString(R.string.action_settings))
.commit()
supportActionBar?.title = getString(R.string.action_settings)
}
else -> {
finish()
}
}
}
return super.onOptionsItemSelected(item)
}
}

View File

@ -0,0 +1,70 @@
package net.helcel.beendroid.activity
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.ListPreference
import androidx.preference.Preference
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)
}
val aboutPreference = findPreference<Preference>(getString(R.string.about))
aboutPreference?.setOnPreferenceClickListener {
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.fragment_view, AboutFragment(), getString(R.string.about))
.commit()
true
}
val licensesPreference = findPreference<Preference>(getString(R.string.licenses))
licensesPreference?.setOnPreferenceClickListener {
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.fragment_view, LicenseFragment(), getString(R.string.licenses))
.commit()
true
}
}
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() {
Group.values().forEach {
Group.entries.forEach {
locs[it] = pref.getBoolean(it.code, false)
}
Country.values().forEach {
Country.entries.forEach {
locs[it] = pref.getBoolean(it.code, false)
}
State.values().forEach {
State.entries.forEach {
locs[it] = pref.getBoolean(it.code, false)
}
editor.apply()

View File

@ -5,16 +5,18 @@ import net.helcel.beendroid.countries.World
class CSSWrapper(private val visited: Visited) {
private val colorPrimary = "#0187FF"
fun get() : String {
return listOf(World.WWW.children
.filter { visited.visited(it)}
.map { ".${it.code}{fill:blue;}"}
.map { ".${it.code}{fill:$colorPrimary;}"}
.fold(""){acc, s-> acc + s},
World.WWW.children
.filter { !visited.visited(it) }
.map { cg -> cg.children
.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}

View File

@ -1,6 +1,7 @@
package net.helcel.beendroid.svg
import android.content.Context
import android.util.TypedValue
import com.caverock.androidsvg.SVG
import net.helcel.beendroid.countries.Country
import net.helcel.beendroid.countries.GeoLoc
@ -11,8 +12,20 @@ class PSVGWrapper(ctx: Context) {
private val cm = HashMap<GeoLoc, PSVGLoader>()
private var fm = ""
private val colorForeground: String
private val colorBackground: String
init {
Country.values().forEach {
val colorSecondaryTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.panelColorBackground, 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()
}
build()
@ -31,12 +44,12 @@ class PSVGWrapper(ctx: Context) {
}.fold("") { acc, e -> acc + e }
}
fun get(): SVG {
return SVG.getFromString("<svg id=\"map\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"1200\" x=\"0\" y=\"0\" >$fm</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\" 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

@ -1,30 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
android:width="12dp"
android:height="12dp"
android:viewportWidth="1600"
android:viewportHeight="1600" >
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:pathData="m800,1200q-83,0 -156,-31.5Q571,1137 517,1083 463,1029 431.5,956 400,883 400,800 400,717 431.5,644 463,571 517,517 571,463 644,431.5 717,400 800,400q83,0 156,31.5 73,31.5 127,85.5 54,54 85.5,127 31.5,73 31.5,156 0,83 -31.5,156 -31.5,73 -85.5,127 -54,54 -127,85.5 -73,31.5 -156,31.5zM800,1120q134,0 227,-93 93,-93 93,-227 0,-7 -0.5,-14.5 -0.5,-7.5 -0.5,-12.5 -5,29 -27,48 -22,19 -52,19L960,840Q927,840 903.5,816.5 880,793 880,760L880,720L720,720v-80q0,-33 23.5,-56.5Q767,560 800,560h40v0q0,-23 12.5,-40.5Q865,502 883,491q-20,-5 -40.5,-8 -20.5,-3 -42.5,-3 -134,0 -227,93 -93,93 -93,227 0,0 0,0 0,0 0,0h200q66,0 113,47 47,47 47,113v40L720,1000v110q20,5 39.5,7.5 19.5,2.5 40.5,2.5z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="M22,7h-9v2h9V7zM22,15h-9v2h9V15z"/>
<path
android:fillColor="?attr/colorPrimary"
android:pathData="M5.54,11L2,7.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L5.54,11z"/>
<path
android:fillColor="?attr/colorPrimary"
android:pathData="M5.54,19L2,15.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L5.54,19z"/>
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="320"
android:viewportHeight="512">
<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"/>
</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

@ -2,169 +2,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
android:fillColor="#FF0187FF"
android:pathData="M0,0h960v960h-960z" />
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="M80,160Q80,127 103.5,103.5Q127,80 160,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L240,720L80,880ZM206,640L800,640Q800,640 800,640Q800,640 800,640L800,160Q800,160 800,160Q800,160 800,160L160,160Q160,160 160,160Q160,160 160,160L160,685L206,640ZM160,640L160,640L160,160Q160,160 160,160Q160,160 160,160L160,160Q160,160 160,160Q160,160 160,160L160,640Q160,640 160,640Q160,640 160,640L160,640Z" />
<path
android:fillColor="?attr/colorPrimary"
android:pathData="M480,280Q497,280 508.5,268.5Q520,257 520,240Q520,223 508.5,211.5Q497,200 480,200Q463,200 451.5,211.5Q440,223 440,240Q440,257 451.5,268.5Q463,280 480,280ZM440,600L520,600L520,360L440,360L440,600ZM80,880L80,160" />
</vector>

View File

@ -0,0 +1,14 @@
<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/colorOnBackground"
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" />
<path
android:fillColor="?attr/colorPrimary"
android:pathData="M17.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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
android:theme="@style/Theme.Beendroid"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.caverock.androidsvg.SVGImageView
<com.caverock.androidsvg.SVGImageView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -15,7 +16,8 @@
<androidx.core.widget.NestedScrollView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:layout_weight="1">
<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

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.AboutFragment" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
<ImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginTop="40dp"
android:layout_marginBottom="30dp"
android:src="@mipmap/ic_launcher_round" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:text="@string/app_name"
android:textStyle="bold"
android:textSize="30sp"
android:textAlignment="center" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="15dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:text="@string/app_version"
android:textSize="25sp"
android:textAlignment="center" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:text="@string/beendroid_is_foss"
android:textAlignment="center" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:autoLink="web"
android:text="@string/beendroid_repo"
android:textAlignment="center" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.LicenseFragment" >
<fragment
android:id="@+id/license_fragment_view"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -9,54 +8,61 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/expand"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription=">"
android:scaleX="0.5"
android:scaleY="0.5"
android:visibility="visible"
app:layout_constraintEnd_toStartOf="@+id/textView"
<com.google.android.material.button.MaterialButton
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="50dp"
app:cornerRadius="0dp"
android:gravity="start|center_vertical"
android:textColor="?attr/colorOnBackground"
android:textAllCaps="false"
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_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
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="0.01dp"
android:layout_height="50dp"
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_constraintHorizontal_bias="1"
app:layout_constraintStart_toEndOf="@+id/textView"
app:layout_constraintTop_toTopOf="@+id/textView"
app:layout_constraintStart_toEndOf="@id/textView"
app:layout_constraintTop_toTopOf="@id/textView"
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
android:id="@+id/sub_item"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="32dp"
android:layout_marginStart="0dp"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/checkBox">
app:layout_constraintTop_toBottomOf="@id/checkBox">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_list"

View File

@ -1,10 +1,26 @@
<menu 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"
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
android:id="@+id/action_stats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orderInCategory="100"
android:title="@string/action_stats"
app:showAsAction="never" />
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>

View File

@ -1,5 +1,9 @@
<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:panelColorBackground">@color/darkgray</item>
<item name="android:statusBarColor">?attr/colorPrimary</item>
<item name="colorAccent">?attr/colorPrimary</item>
</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,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Beendroid</string>
<string name="app_name">BeenDroid</string>
<string name="app_version">1.0</string>
<string name="action_settings">Settings</string>
<string name="action_stats">Stats</string>
<string name="action_edit">Edit</string>
<string name="welcome">Welcome!</string>
<string name="change_lang">Change language</string>
<string name="key_theme">App theme</string>
<string name="system">System</string>
<string name="light">Light</string>
<string name="dark">Dark</string>
<string name="licenses">Licenses</string>
<string name="about">About</string>
<string name="beendroid_is_foss">BeenDroid is free and open source software, licensed under the GNU General Public License (version 3 or later)</string>
<string name="beendroid_repo">Project repository: https://git.helcel.net/helcel/beendroid\n Feel free to report issues or contribute to the project.</string>
<string name="foss_licenses">Free and open source dependencies and licenses</string>
<string name="about_beendroid">About the BeenDroid application</string>
</resources>

View File

@ -1,14 +1,9 @@
<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:panelColorBackground">@color/lightgray</item>
<item name="android:statusBarColor">?attr/colorPrimary</item>
<item name="colorAccent">?attr/colorPrimary</item>
</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>

View File

@ -0,0 +1,31 @@
<?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" />
<Preference
app:enabled="true"
app:key="@string/licenses"
app:icon="@drawable/checklist"
app:title="@string/licenses"
android:summary="@string/foss_licenses"/>
<Preference
app:enabled="true"
app:key="@string/about"
app:icon="@drawable/info"
app:title="@string/about"
android:summary="@string/about_beendroid"/>
</PreferenceScreen>

View File

@ -14,5 +14,5 @@ dependencyResolutionManagement {
maven { url 'https://jitpack.io' }
}
}
rootProject.name = "beendroid"
rootProject.name = "BeenDroid"
include ':app'