Skip to content

Commit

Permalink
Merge pull request #21 from Abrynos/view-binding
Browse files Browse the repository at this point in the history
Migrate kotlin synthetics to Android view binding
  • Loading branch information
Abrynos authored Feb 18, 2023
2 parents d4723da + a531776 commit f5b3bbe
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 64 deletions.
18 changes: 12 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "kotlin-android-extensions"
id "kotlin-kapt"
}

Expand All @@ -47,7 +46,10 @@ android {

javaCompileOptions {
annotationProcessorOptions {
arguments["room.incremental"] = "true"
arguments += [
"room.schemaLocation": "$projectDir/schemas",
"room.incremental" : "true"
]
}
}
signingConfig signingConfigs.debug
Expand All @@ -62,11 +64,14 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "1.8"
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
jvmToolchain(11)
}
buildFeatures {
viewBinding true
Expand Down Expand Up @@ -98,6 +103,7 @@ dependencies {

def room_version = "2.5.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation fileTree(include: ["*.jar"], dir: "libs")

Expand Down
36 changes: 36 additions & 0 deletions app/src/main/java/pl/edu/pjwstk/s999844/shoppinglist/Extensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* _____ _ _ _ _ _
* / ___| | (_) | | (_) | |
* \ `--.| |__ ___ _ __ _ __ _ _ __ __ _| | _ ___| |_
* `--. \ '_ \ / _ \| '_ \| '_ \| | '_ \ / _` | | | / __| __|
* /\__/ / | | | (_) | |_) | |_) | | | | | (_| | |___| \__ \ |_
* \____/|_| |_|\___/| .__/| .__/|_|_| |_|\__, \_____/_|___/\__|
* | | | | __/ |
* |_| |_| |___/
*
* Copyright (C) 2021-2021 Sebastian Göls
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package pl.edu.pjwstk.s999844.shoppinglist

import android.view.LayoutInflater
import androidx.viewbinding.ViewBinding
import pl.edu.pjwstk.s999844.shoppinglist.activities.AbstractShoppingActivity


inline fun <T : ViewBinding> AbstractShoppingActivity.viewBinding(crossinline bindingInflater: (LayoutInflater) -> T) = lazy(LazyThreadSafetyMode.NONE) {
bindingInflater.invoke(layoutInflater)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_add_item.*
import pl.edu.pjwstk.s999844.shoppinglist.R
import pl.edu.pjwstk.s999844.shoppinglist.dal.ShoppingListDao
import pl.edu.pjwstk.s999844.shoppinglist.dal.ShoppingListDatabase
import pl.edu.pjwstk.s999844.shoppinglist.databinding.ActivityAddItemBinding
import pl.edu.pjwstk.s999844.shoppinglist.models.RequiredItem
import pl.edu.pjwstk.s999844.shoppinglist.viewBinding
import java.util.*

class AddItemActivity : AbstractShoppingActivity() {
Expand All @@ -48,14 +49,16 @@ class AddItemActivity : AbstractShoppingActivity() {
const val AmountParameterName = "amount"
}

private val binding by viewBinding(ActivityAddItemBinding::inflate)

private val inputMethodManager: InputMethodManager by lazy { getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }

private val currentLocale: Locale
get() = baseContext.resources.configuration.locales.get(0)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_item)
setContentView(binding.root)
}


Expand All @@ -64,9 +67,9 @@ class AddItemActivity : AbstractShoppingActivity() {

// german-speaking people capitalize nouns - as a shopping list usually contains nouns we capitalize the first letter automatically. They can still use lowercase manually if they need a pronoun
when (currentLocale.language) {
Locale.GERMAN.language -> addItemNameInput.inputType = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or addItemNameInput.inputType
Locale.GERMAN.language -> binding.addItemNameInput.inputType = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or binding.addItemNameInput.inputType
}
addItemNameInput.requestFocus()
binding.addItemNameInput.requestFocus()

title = getString(R.string.addTitleBarText)

Expand All @@ -79,7 +82,7 @@ class AddItemActivity : AbstractShoppingActivity() {
return
}

addItemNameInput.setText(nameParameter, TextView.BufferType.EDITABLE)
binding.addItemNameInput.setText(nameParameter, TextView.BufferType.EDITABLE)

val amountParameter = data.getQueryParameter(AmountParameterName) ?: return
if (amountParameter.isEmpty() || amountParameter.isBlank()) {
Expand All @@ -93,7 +96,7 @@ class AddItemActivity : AbstractShoppingActivity() {
}

if (amount > 1) {
addItemAmountInput.setText(amount.toString(), TextView.BufferType.EDITABLE)
binding.addItemAmountInput.setText(amount.toString(), TextView.BufferType.EDITABLE)
}
}

Expand All @@ -106,13 +109,13 @@ class AddItemActivity : AbstractShoppingActivity() {
}

private fun createAndValidateItem(): RequiredItem? {
val name: String = addItemNameInput.text.toString().trim()
val name: String = binding.addItemNameInput.text.toString().trim()
if (name.isEmpty()) {
warnError(getString(R.string.addNameIsEmptyMessage))
return null
}

val amountString = addItemAmountInput.text.toString().trim()
val amountString = binding.addItemAmountInput.text.toString().trim()
val amount: Int = if (amountString.isEmpty() || amountString.isBlank()) {
1
} else {
Expand Down Expand Up @@ -148,7 +151,7 @@ class AddItemActivity : AbstractShoppingActivity() {

@Suppress("UNUSED_PARAMETER")
fun addItem(view: View) {
inputMethodManager.hideSoftInputFromWindow(addItemNameInput.windowToken, 0)
inputMethodManager.hideSoftInputFromWindow(binding.addItemNameInput.windowToken, 0)

val item = createAndValidateItem() ?: return

Expand All @@ -164,5 +167,5 @@ class AddItemActivity : AbstractShoppingActivity() {
finish()
}

private fun warnError(message: String) = Snackbar.make(saveButton, message, Snackbar.LENGTH_SHORT).show()
private fun warnError(message: String) = Snackbar.make(binding.saveButton, message, Snackbar.LENGTH_SHORT).show()
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,28 @@ import android.view.View
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import pl.edu.pjwstk.s999844.shoppinglist.R
import pl.edu.pjwstk.s999844.shoppinglist.adapters.ShoppingListAdapter
import pl.edu.pjwstk.s999844.shoppinglist.dal.ShoppingListDao
import pl.edu.pjwstk.s999844.shoppinglist.dal.ShoppingListDatabase
import pl.edu.pjwstk.s999844.shoppinglist.databinding.ActivityMainBinding
import pl.edu.pjwstk.s999844.shoppinglist.models.RequiredItem
import pl.edu.pjwstk.s999844.shoppinglist.settings.Settings
import pl.edu.pjwstk.s999844.shoppinglist.viewBinding

class MainActivity : AbstractShoppingActivity() {
private val binding by viewBinding(ActivityMainBinding::inflate)

private val shoppingListDao: ShoppingListDao by lazy { ShoppingListDatabase.getInstance(applicationContext).getShoppingListDao() }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentView(binding.root)

mainListRecyclerView.layoutManager = LinearLayoutManager(this)
mainListRecyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
binding.mainListRecyclerView.layoutManager = LinearLayoutManager(this)
binding.mainListRecyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))

shoppingListDao.findAllItems().observe(this, this::observeDatabaseChange)
mainListRecyclerView.adapter = ShoppingListAdapter(this::changeItemCallback)
binding.mainListRecyclerView.adapter = ShoppingListAdapter(this::changeItemCallback)
}

override fun onStart() {
Expand Down Expand Up @@ -97,14 +99,9 @@ class MainActivity : AbstractShoppingActivity() {
}

private fun observeDatabaseChange(items: List<RequiredItem>) {
val orderedItems = when (settings.order) {
Settings.Order.Alphabetical -> items.sortedBy { it.name.lowercase() }
Settings.Order.AmountAscending -> items.sortedBy { it.amount }
Settings.Order.AmountDescending -> items.sortedByDescending { it.amount }
else -> items
}
(mainListRecyclerView.adapter as ShoppingListAdapter).setItems(orderedItems)
mainEmptyTextView.isVisible = items.isEmpty()
mainListRecyclerView.isVisible = items.isNotEmpty()
(binding.mainListRecyclerView.adapter as ShoppingListAdapter).setItems(items)

binding.mainEmptyTextView.isVisible = items.isEmpty()
binding.mainListRecyclerView.isVisible = items.isNotEmpty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.Spinner
import kotlinx.android.synthetic.main.activity_options.*
import pl.edu.pjwstk.s999844.shoppinglist.BuildConfig
import pl.edu.pjwstk.s999844.shoppinglist.R
import pl.edu.pjwstk.s999844.shoppinglist.adapters.DescriptiveSettingSpinnerAdapter
import pl.edu.pjwstk.s999844.shoppinglist.adapters.SpinnerItemSelectedListener
import pl.edu.pjwstk.s999844.shoppinglist.databinding.ActivityOptionsBinding
import pl.edu.pjwstk.s999844.shoppinglist.settings.Settings
import pl.edu.pjwstk.s999844.shoppinglist.viewBinding

class OptionsActivity : AbstractShoppingActivity() {
companion object {
Expand All @@ -49,21 +50,23 @@ class OptionsActivity : AbstractShoppingActivity() {
private val LATEST_RELEASE_URI: Uri = Uri.parse(LATEST_RELEASE_LINK)
}

private val binding by viewBinding(ActivityOptionsBinding::inflate)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_options)
setContentView(binding.root)

listOrderDropdown.adapter = DescriptiveSettingSpinnerAdapter(this, Settings.Order.values())
listOrderDropdown.onItemSelectedListener = SpinnerItemSelectedListener<Settings.Order>(listOrderDropdown) {
binding.listOrderDropdown.adapter = DescriptiveSettingSpinnerAdapter(this, Settings.Order.values())
binding.listOrderDropdown.onItemSelectedListener = SpinnerItemSelectedListener<Settings.Order>(binding.listOrderDropdown) {
if (settings.order == it) {
return@SpinnerItemSelectedListener
}

settings.order = it
}

accentColorDropdown.adapter = DescriptiveSettingSpinnerAdapter(this, Settings.AccentColor.values())
accentColorDropdown.onItemSelectedListener = SpinnerItemSelectedListener<Settings.AccentColor>(accentColorDropdown) {
binding.accentColorDropdown.adapter = DescriptiveSettingSpinnerAdapter(this, Settings.AccentColor.values())
binding.accentColorDropdown.onItemSelectedListener = SpinnerItemSelectedListener<Settings.AccentColor>(binding.accentColorDropdown) {
if (settings.accentColor == it) {
return@SpinnerItemSelectedListener
}
Expand All @@ -73,31 +76,19 @@ class OptionsActivity : AbstractShoppingActivity() {
}
}

private fun <T> getIndex(spinner: Spinner, order: T): Int {
for (i in 0..spinner.count) {
@Suppress("UNCHECKED_CAST")
val valueAtPosition: T = spinner.getItemAtPosition(i) as T
if (valueAtPosition == order) {
return i
}
}

return -1
}

override fun onStart() {
super.onStart()

optionsThemeSwitch.isChecked = settings.darkThemeActive
listOrderDropdown.setSelection(getIndex(listOrderDropdown, settings.order))
accentColorDropdown.setSelection(getIndex(accentColorDropdown, settings.accentColor))
binding.optionsThemeSwitch.isChecked = settings.darkThemeActive
binding.listOrderDropdown.setSelection(getIndex(binding.listOrderDropdown, settings.order))
binding.accentColorDropdown.setSelection(getIndex(binding.accentColorDropdown, settings.accentColor))

title = getString(R.string.optionsTitleBarText)
}

@Suppress("UNUSED_PARAMETER")
fun onClickThemeSwitch(view: View) {
val isDark = optionsThemeSwitch.isChecked
val isDark = binding.optionsThemeSwitch.isChecked
settings.darkThemeActive = isDark
setDark(isDark)
}
Expand All @@ -109,4 +100,16 @@ class OptionsActivity : AbstractShoppingActivity() {
fun onClickLatestRelease(view: View) = openUriInBrowser(LATEST_RELEASE_URI)

private fun openUriInBrowser(uri: Uri) = startActivity(Intent(Intent.ACTION_VIEW, uri))

private fun <T> getIndex(spinner: Spinner, order: T): Int {
for (i in 0..spinner.count) {
@Suppress("UNCHECKED_CAST")
val valueAtPosition: T = spinner.getItemAtPosition(i) as T
if (valueAtPosition == order) {
return i
}
}

return -1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.shopping_list_item.view.*
import pl.edu.pjwstk.s999844.shoppinglist.databinding.ShoppingListItemBinding
import pl.edu.pjwstk.s999844.shoppinglist.models.RequiredItem
import java.util.function.BiConsumer
Expand All @@ -48,19 +47,19 @@ class ShoppingListAdapter(private val changeAmountCallback: BiConsumer<RequiredI
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item: RequiredItem = items[position]

val binding = holder.shoppingListItem
val binding = holder.binding
binding.amountTextView.text = item.amount.toString()
binding.amountTextView.isVisible = item.amount > 1

binding.nameTextView.text = item.name

binding.buttonLayout.addButton.setOnClickListener {
binding.addButton.setOnClickListener {
changeAmountCallback.accept(item, 1)
}
binding.buttonLayout.subtractButton.setOnClickListener {
binding.subtractButton.setOnClickListener {
changeAmountCallback.accept(item, -1)
}
binding.buttonLayout.deleteButton.setOnClickListener {
binding.deleteButton.setOnClickListener {
changeAmountCallback.accept(item, -item.amount)
}
}
Expand All @@ -73,5 +72,5 @@ class ShoppingListAdapter(private val changeAmountCallback: BiConsumer<RequiredI
notifyDataSetChanged()
}

class ViewHolder(val shoppingListItem: ShoppingListItemBinding) : RecyclerView.ViewHolder(shoppingListItem.root)
class ViewHolder(val binding: ShoppingListItemBinding) : RecyclerView.ViewHolder(binding.root)
}
Loading

0 comments on commit f5b3bbe

Please sign in to comment.