Implement viewBindings

This commit is contained in:
2020-12-16 21:20:36 +01:00
parent 7c338acf81
commit ce94cfb566
12 changed files with 158 additions and 101 deletions

View File

@@ -1,7 +1,6 @@
plugins {
id("com.android.application")
id("kotlin-android")
id("kotlin-android-extensions")
id("kotlin-kapt")
id("com.google.gms.google-services")
id("com.mikepenz.aboutlibraries.plugin")
@@ -38,8 +37,8 @@ android {
kotlinOptions {
jvmTarget = "1.8"
}
androidExtensions {
isExperimental = true
buildFeatures {
viewBinding = true
}
}

View File

@@ -38,8 +38,8 @@ import androidx.preference.PreferenceManager
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.snackbar.Snackbar
import com.mikepenz.aboutlibraries.LibsBuilder
import kotlinx.android.synthetic.main.activity_main.*
import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.databinding.ActivityMainBinding
import net.underdesk.circolapp.utils.DownloadableFile
import net.underdesk.circolapp.works.PollWork
@@ -49,6 +49,8 @@ class MainActivity : AppCompatActivity(), CircularLetterAdapter.AdapterCallback
internal const val PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 10
}
private lateinit var binding: ActivityMainBinding
var searchCallback: SearchCallback? = null
var refreshCallback: RefreshCallback? = null
override var fileToDownload: DownloadableFile? = null
@@ -56,8 +58,9 @@ class MainActivity : AppCompatActivity(), CircularLetterAdapter.AdapterCallback
override fun onCreate(savedInstanceState: Bundle?) {
loadDarkTheme()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(main_toolbar)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.mainToolbar)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
@@ -134,7 +137,7 @@ class MainActivity : AppCompatActivity(), CircularLetterAdapter.AdapterCallback
downloadFile()
} else {
Snackbar.make(
container,
binding.container,
resources.getString(R.string.snackbar_write_permission_not_granted),
Snackbar.LENGTH_LONG
).show()
@@ -161,7 +164,7 @@ class MainActivity : AppCompatActivity(), CircularLetterAdapter.AdapterCallback
(getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager).enqueue(request)
Snackbar.make(
container,
binding.container,
resources.getString(R.string.snackbar_circular_downloaded),
Snackbar.LENGTH_LONG
).show()

View File

@@ -24,7 +24,7 @@ import android.text.InputType
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.*
import kotlinx.android.synthetic.main.settings_activity.*
import net.underdesk.circolapp.databinding.SettingsActivityBinding
import net.underdesk.circolapp.push.FirebaseTopicUtils
import net.underdesk.circolapp.server.AndroidServerApi
import net.underdesk.circolapp.shared.server.ServerAPI
@@ -32,10 +32,14 @@ import net.underdesk.circolapp.works.PollWork
class SettingsActivity : AppCompatActivity() {
private lateinit var binding: SettingsActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_activity)
setSupportActionBar(settings_toolbar)
binding = SettingsActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.settingsToolbar)
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())

View File

@@ -20,13 +20,11 @@ package net.underdesk.circolapp.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_attachment.view.*
import net.underdesk.circolapp.R
import net.underdesk.circolapp.databinding.ItemAttachmentBinding
import net.underdesk.circolapp.utils.DownloadableFile
import net.underdesk.circolapp.utils.FileUtils
@@ -38,18 +36,17 @@ class AttachmentAdapter(
RecyclerView.Adapter<AttachmentAdapter.AttachmentViewHolder>() {
private lateinit var context: Context
inner class AttachmentViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var title: TextView = view.attachment_title_textview
var viewButton: ImageButton = view.attachment_view_button
var downloadButton: ImageButton = view.attachment_download_button
inner class AttachmentViewHolder(binding: ItemAttachmentBinding) : RecyclerView.ViewHolder(binding.root) {
var title: TextView = binding.attachmentTitleTextview
var viewButton: ImageButton = binding.attachmentViewButton
var downloadButton: ImageButton = binding.attachmentDownloadButton
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AttachmentViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.item_attachment, parent, false)
val binding = ItemAttachmentBinding.inflate(LayoutInflater.from(parent.context), parent, false)
context = parent.context
return AttachmentViewHolder(itemView)
return AttachmentViewHolder(binding)
}
override fun onBindViewHolder(holder: AttachmentViewHolder, position: Int) {

View File

@@ -31,12 +31,12 @@ import androidx.core.content.ContextCompat.getDrawable
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_circular.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import net.underdesk.circolapp.AlarmBroadcastReceiver
import net.underdesk.circolapp.R
import net.underdesk.circolapp.data.AndroidDatabase
import net.underdesk.circolapp.databinding.ItemCircularBinding
import net.underdesk.circolapp.fragments.NewReminderFragment
import net.underdesk.circolapp.shared.data.Circular
import net.underdesk.circolapp.utils.DownloadableFile
@@ -55,17 +55,17 @@ class CircularLetterAdapter(
setHasStableIds(true)
}
inner class CircularLetterViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var card: CardView = view.circular_card
var title: TextView = view.circular_title_textview
var number: TextView = view.circular_number_textview
var date: TextView = view.circular_date_textview
var collapseButton: ImageButton = view.circular_collapse_button
var viewButton: ImageButton = view.circular_view_button
var downloadButton: ImageButton = view.circular_download_button
var favouriteButton: ImageButton = view.circular_favourite_button
var reminderButton: ImageButton = view.circular_reminder_button
var attachmentsList: RecyclerView = view.circulars_attachments_list
inner class CircularLetterViewHolder(binding: ItemCircularBinding) : RecyclerView.ViewHolder(binding.root) {
var card: CardView = binding.circularCard
var title: TextView = binding.circularTitleTextview
var number: TextView = binding.circularNumberTextview
var date: TextView = binding.circularDateTextview
var collapseButton: ImageButton = binding.circularCollapseButton
var viewButton: ImageButton = binding.circularViewButton
var downloadButton: ImageButton = binding.circularDownloadButton
var favouriteButton: ImageButton = binding.circularFavouriteButton
var reminderButton: ImageButton = binding.circularReminderButton
var attachmentsList: RecyclerView = binding.circularsAttachmentsList
init {
attachmentsList.layoutManager = LinearLayoutManager(context)
@@ -73,11 +73,10 @@ class CircularLetterAdapter(
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CircularLetterViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.item_circular, parent, false)
val binding = ItemCircularBinding.inflate(LayoutInflater.from(parent.context), parent, false)
context = parent.context
return CircularLetterViewHolder(itemView)
return CircularLetterViewHolder(binding)
}
override fun onBindViewHolder(holder: CircularLetterViewHolder, position: Int) {

View File

@@ -28,12 +28,11 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_circular_letters.*
import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R
import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.data.AndroidCircularRepository
import net.underdesk.circolapp.databinding.FragmentCircularLettersBinding
import net.underdesk.circolapp.viewmodels.CircularLetterViewModel
import net.underdesk.circolapp.viewmodels.CircularLetterViewModelFactory
@@ -42,6 +41,10 @@ class CircularLetterFragment :
MainActivity.SearchCallback,
MainActivity.RefreshCallback {
private var _binding: FragmentCircularLettersBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private val circularLetterViewModel: CircularLetterViewModel by viewModels {
CircularLetterViewModelFactory(
AndroidCircularRepository.getInstance(requireContext()),
@@ -53,19 +56,19 @@ class CircularLetterFragment :
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_circular_letters, container, false)
): View {
_binding = FragmentCircularLettersBinding.inflate(inflater, container, false)
root.circulars_list.layoutManager = LinearLayoutManager(context)
binding.circularsList.layoutManager = LinearLayoutManager(context)
circularLetterViewModel.circulars.observe(
viewLifecycleOwner,
{
if (root.circulars_list.adapter == null) {
root.circulars_list.adapter =
if (binding.circularsList.adapter == null) {
binding.circularsList.adapter =
CircularLetterAdapter(it, activity as MainActivity, lifecycleScope)
} else {
(root.circulars_list.adapter as CircularLetterAdapter).changeDataSet(it)
(binding.circularsList.adapter as CircularLetterAdapter).changeDataSet(it)
}
}
)
@@ -87,18 +90,23 @@ class CircularLetterFragment :
viewLifecycleOwner,
{
if (it) {
root.circulars_refresh.isRefreshing = false
binding.circularsRefresh.isRefreshing = false
circularLetterViewModel.showMessage.postValue(false)
}
}
)
root.circulars_refresh.setOnRefreshListener { circularLetterViewModel.updateCirculars() }
binding.circularsRefresh.setOnRefreshListener { circularLetterViewModel.updateCirculars() }
(activity as MainActivity).searchCallback = this
(activity as MainActivity).refreshCallback = this
return root
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun search(query: String) {
@@ -106,7 +114,7 @@ class CircularLetterFragment :
}
override fun refresh() {
circulars_refresh.isRefreshing = true
binding.circularsRefresh.isRefreshing = true
circularLetterViewModel.updateCirculars()
}
}

View File

@@ -26,16 +26,19 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R
import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.data.AndroidCircularRepository
import net.underdesk.circolapp.databinding.FragmentCircularLettersBinding
import net.underdesk.circolapp.viewmodels.FavouritesViewModel
import net.underdesk.circolapp.viewmodels.FavouritesViewModelFactory
class FavouritesFragment : Fragment(), MainActivity.SearchCallback {
private var _binding: FragmentCircularLettersBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private val favouritesViewModel: FavouritesViewModel by viewModels {
FavouritesViewModelFactory(
AndroidCircularRepository.getInstance(requireContext()),
@@ -47,27 +50,32 @@ class FavouritesFragment : Fragment(), MainActivity.SearchCallback {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_circular_letters, container, false)
): View {
_binding = FragmentCircularLettersBinding.inflate(inflater, container, false)
root.circulars_list.layoutManager = LinearLayoutManager(context)
root.circulars_refresh.isEnabled = false
binding.circularsList.layoutManager = LinearLayoutManager(context)
binding.circularsRefresh.isEnabled = false
favouritesViewModel.circulars.observe(
viewLifecycleOwner,
{
if (root.circulars_list.adapter == null) {
root.circulars_list.adapter =
if (binding.circularsList.adapter == null) {
binding.circularsList.adapter =
CircularLetterAdapter(it, activity as MainActivity, lifecycleScope)
} else {
(root.circulars_list.adapter as CircularLetterAdapter).changeDataSet(it)
(binding.circularsList.adapter as CircularLetterAdapter).changeDataSet(it)
}
}
)
(activity as MainActivity).searchCallback = this
(activity as MainActivity).refreshCallback = null
return root
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun search(query: String) {

View File

@@ -30,11 +30,11 @@ import android.view.ViewGroup
import androidx.core.app.AlarmManagerCompat
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.dialog_reminder.*
import kotlinx.coroutines.launch
import net.underdesk.circolapp.AlarmBroadcastReceiver
import net.underdesk.circolapp.R
import net.underdesk.circolapp.data.AndroidDatabase
import net.underdesk.circolapp.databinding.DialogReminderBinding
import net.underdesk.circolapp.shared.data.Circular
import java.util.*
@@ -48,6 +48,10 @@ class NewReminderFragment : DialogFragment() {
}
}
private var _binding: DialogReminderBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private var dateNotChosen = true
lateinit var circular: Circular
@@ -56,44 +60,50 @@ class NewReminderFragment : DialogFragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.dialog_reminder, container)
_binding = DialogReminderBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
dialog_time_picker.setIs24HourView(true)
binding.dialogTimePicker.setIs24HourView(true)
dialog_ok_button.setOnClickListener { next() }
dialog_back_button.setOnClickListener { back() }
dialog_cancel_button.setOnClickListener { dismiss() }
binding.dialogOkButton.setOnClickListener { next() }
binding.dialogBackButton.setOnClickListener { back() }
binding.dialogCancelButton.setOnClickListener { dismiss() }
}
fun next() {
if (dateNotChosen) {
dialog_date_picker.visibility = View.GONE
dialog_time_picker.visibility = View.VISIBLE
dialog_back_button.visibility = View.VISIBLE
dialog_ok_button.text = getString(R.string.dialog_ok)
binding.dialogDatePicker.visibility = View.GONE
binding.dialogTimePicker.visibility = View.VISIBLE
binding.dialogBackButton.visibility = View.VISIBLE
binding.dialogOkButton.text = getString(R.string.dialog_ok)
dateNotChosen = false
} else {
val calendar = Calendar.getInstance()
val hour = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
dialog_time_picker.hour
binding.dialogTimePicker.hour
} else {
dialog_time_picker.currentHour
binding.dialogTimePicker.currentHour
}
val minute = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
dialog_time_picker.minute
binding.dialogTimePicker.minute
} else {
dialog_time_picker.currentMinute
binding.dialogTimePicker.currentMinute
}
calendar.set(
dialog_date_picker.year,
dialog_date_picker.month,
dialog_date_picker.dayOfMonth,
binding.dialogDatePicker.year,
binding.dialogDatePicker.month,
binding.dialogDatePicker.dayOfMonth,
hour,
minute
)
@@ -127,10 +137,10 @@ class NewReminderFragment : DialogFragment() {
}
private fun back() {
dialog_date_picker.visibility = View.VISIBLE
dialog_time_picker.visibility = View.GONE
dialog_back_button.visibility = View.GONE
dialog_ok_button.text = getString(R.string.dialog_next)
binding.dialogDatePicker.visibility = View.VISIBLE
binding.dialogTimePicker.visibility = View.GONE
binding.dialogBackButton.visibility = View.GONE
binding.dialogOkButton.text = getString(R.string.dialog_next)
dateNotChosen = true
}
}

View File

@@ -26,16 +26,19 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R
import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.data.AndroidCircularRepository
import net.underdesk.circolapp.databinding.FragmentCircularLettersBinding
import net.underdesk.circolapp.viewmodels.RemindersViewModel
import net.underdesk.circolapp.viewmodels.RemindersViewModelFactory
class RemindersFragment : Fragment(), MainActivity.SearchCallback {
private var _binding: FragmentCircularLettersBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private val remindersViewModel: RemindersViewModel by viewModels {
RemindersViewModelFactory(
AndroidCircularRepository.getInstance(requireContext()),
@@ -47,27 +50,32 @@ class RemindersFragment : Fragment(), MainActivity.SearchCallback {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_circular_letters, container, false)
): View {
_binding = FragmentCircularLettersBinding.inflate(inflater, container, false)
root.circulars_list.layoutManager = LinearLayoutManager(context)
root.circulars_refresh.isEnabled = false
binding.circularsList.layoutManager = LinearLayoutManager(context)
binding.circularsRefresh.isEnabled = false
remindersViewModel.circulars.observe(
viewLifecycleOwner,
{
if (root.circulars_list.adapter == null) {
root.circulars_list.adapter =
if (binding.circularsList.adapter == null) {
binding.circularsList.adapter =
CircularLetterAdapter(it, activity as MainActivity, lifecycleScope)
} else {
(root.circulars_list.adapter as CircularLetterAdapter).changeDataSet(it)
(binding.circularsList.adapter as CircularLetterAdapter).changeDataSet(it)
}
}
)
(activity as MainActivity).searchCallback = this
(activity as MainActivity).refreshCallback = null
return root
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun search(query: String) {

View File

@@ -8,37 +8,50 @@ import android.view.ViewGroup
import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment
import com.github.appintro.SlidePolicy
import kotlinx.android.synthetic.main.fragment_legal.view.*
import net.underdesk.circolapp.R
import net.underdesk.circolapp.databinding.FragmentLegalBinding
class LegalFragment : Fragment(), SlidePolicy {
private var _binding: FragmentLegalBinding? = 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? = inflater.inflate(R.layout.fragment_legal, container, false)
): View {
_binding = FragmentLegalBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.legal_text.text = HtmlCompat.fromHtml(
binding.legalText.text = HtmlCompat.fromHtml(
getString(R.string.activity_intro_legal_text),
HtmlCompat.FROM_HTML_MODE_COMPACT
)
view.legal_text.movementMethod = LinkMovementMethod.getInstance()
binding.legalText.movementMethod = LinkMovementMethod.getInstance()
view.legal_checkbox.setOnCheckedChangeListener { checkBox, checked ->
binding.legalCheckbox.setOnCheckedChangeListener { checkBox, checked ->
if (checked)
checkBox.error = null
}
}
override val isPolicyRespected: Boolean
get() = view?.legal_checkbox?.isChecked ?: false
get() = binding.legalCheckbox.isChecked
override fun onUserIllegallyRequestedNextPage() {
view?.legal_checkbox?.error =
binding.legalCheckbox.error =
getString(R.string.activity_intro_legal_error)
}

View File

@@ -10,12 +10,17 @@ import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import com.github.appintro.SlidePolicy
import com.tiper.MaterialSpinner
import kotlinx.android.synthetic.main.fragment_school_selection.view.*
import net.underdesk.circolapp.R
import net.underdesk.circolapp.databinding.FragmentSchoolSelectionBinding
import net.underdesk.circolapp.server.AndroidServerApi
import net.underdesk.circolapp.shared.server.ServerAPI
class SchoolSelectionFragment : Fragment(), SlidePolicy, MaterialSpinner.OnItemSelectedListener {
private var _binding: FragmentSchoolSelectionBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
private lateinit var preferenceManager: SharedPreferences
private var schoolSelected = false
@@ -23,7 +28,11 @@ class SchoolSelectionFragment : Fragment(), SlidePolicy, MaterialSpinner.OnItemS
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_school_selection, container, false)
): View {
_binding = FragmentSchoolSelectionBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -34,8 +43,8 @@ class SchoolSelectionFragment : Fragment(), SlidePolicy, MaterialSpinner.OnItemS
val adapter =
ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, items)
view.school_selection_spinner.adapter = adapter
view.school_selection_spinner.onItemSelectedListener = this
binding.schoolSelectionSpinner.adapter = adapter
binding.schoolSelectionSpinner.onItemSelectedListener = this
}
private fun getSchoolListArray(): ArrayList<String> {
@@ -68,7 +77,7 @@ class SchoolSelectionFragment : Fragment(), SlidePolicy, MaterialSpinner.OnItemS
get() = schoolSelected
override fun onUserIllegallyRequestedNextPage() {
view?.school_selection_spinner?.error =
binding.schoolSelectionSpinner.error =
getString(R.string.activity_intro_school_selection_error)
}