Update Material Components library.

- Introduced the new material date range picker, to be used in the FilterOptionsDialog to select a date range. This was necessary because the old MaterialDatePicker that was used inside DatePickerFragment is no longer available in the latest version of the Material Components library.
develop
Severiano Jaramillo 2021-03-23 22:31:44 -07:00
parent dd1bf98e5d
commit 7e12224795
5 changed files with 46 additions and 163 deletions

View File

@ -78,7 +78,7 @@ dependencies {
// Google
implementation 'com.google.zxing:core:3.4.0'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.google.android.material:material:1.1.0-alpha04'
implementation 'com.google.android.material:material:1.3.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.maps.android:android-maps-utils:0.5'
// AAC Lifecycle

View File

@ -11,8 +11,10 @@ import androidx.core.os.ConfigurationCompat
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.DateValidatorPointBackward
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.firebase.crashlytics.FirebaseCrashlytics
import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.adapters.BalancesDetailsAdapter
import cy.agorise.bitsybitshareswallet.database.joins.BalanceDetail
import cy.agorise.bitsybitshareswallet.databinding.DialogFilterOptionsBinding
@ -20,7 +22,6 @@ import cy.agorise.bitsybitshareswallet.models.FilterOptions
import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.utils.Helper
import cy.agorise.bitsybitshareswallet.viewmodels.BalanceDetailViewModel
import cy.agorise.bitsybitshareswallet.views.DatePickerFragment
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
@ -30,15 +31,11 @@ import kotlin.collections.ArrayList
* Creates a Dialog that communicates with {@link TransactionsActivity} to give it parameters about
* how to filter the list of Transactions
*/
class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListener {
class FilterOptionsDialog : DialogFragment() {
companion object {
private const val TAG = "FilterOptionsDialog"
const val KEY_FILTER_OPTIONS = "key_filter_options"
const val START_DATE_PICKER = 0
const val END_DATE_PICKER = 1
// Container Fragment must implement this interface
interface OnFilterOptionsSelectedListener {
fun onFilterOptionsSelected(filterOptions: FilterOptions)
}
private val viewModel: BalanceDetailViewModel by viewModels()
@ -61,44 +58,6 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
private lateinit var mCurrency: Currency
override fun onDateSet(which: Int, timestamp: Long) {
when (which) {
START_DATE_PICKER -> {
mFilterOptions.startDate = timestamp
updateDateTextViews()
}
END_DATE_PICKER -> {
mFilterOptions.endDate = timestamp
// Make sure there is at least one moth difference between start and end time
val calendar = Calendar.getInstance()
calendar.timeInMillis = mFilterOptions.endDate
calendar.add(Calendar.MONTH, -1)
val tmpTime = calendar.timeInMillis
if (tmpTime < mFilterOptions.startDate)
mFilterOptions.startDate = tmpTime
updateDateTextViews()
}
}
}
private fun updateDateTextViews() {
var date = Date(mFilterOptions.startDate)
binding.tvStartDate.text = dateFormat.format(date)
date = Date(mFilterOptions.endDate)
binding.tvEndDate.text = dateFormat.format(date)
}
// Container Fragment must implement this interface
interface OnFilterOptionsSelectedListener {
fun onFilterOptionsSelected(filterOptions: FilterOptions)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -136,9 +95,9 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
}
binding.cbDateRange.isChecked = mFilterOptions.dateRangeAll
binding.tvStartDate.setOnClickListener(mDateClickListener)
binding.tvStartDate.setOnClickListener { showDateRangePicker() }
binding.tvEndDate.setOnClickListener(mDateClickListener)
binding.tvEndDate.setOnClickListener { showDateRangePicker() }
updateDateTextViews()
@ -220,27 +179,38 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
}
}
private val mDateClickListener = View.OnClickListener { v ->
val calendar = Calendar.getInstance()
private fun updateDateTextViews() {
var date = Date(mFilterOptions.startDate)
binding.tvStartDate.text = dateFormat.format(date)
// Variable used to select that date on the calendar
var currentTime = calendar.timeInMillis
var maxTime = currentTime
date = Date(mFilterOptions.endDate)
binding.tvEndDate.text = dateFormat.format(date)
}
var which = -1
if (v.id == R.id.tvStartDate) {
which = START_DATE_PICKER
currentTime = mFilterOptions.startDate
calendar.timeInMillis = mFilterOptions.endDate
calendar.add(Calendar.MONTH, -1)
maxTime = calendar.timeInMillis
} else if (v.id == R.id.tvEndDate) {
which = END_DATE_PICKER
currentTime = mFilterOptions.endDate
private fun showDateRangePicker() {
// Makes only dates until today selectable.
val constraintsBuilder =
CalendarConstraints.Builder()
.setValidator(DateValidatorPointBackward.now())
val dateRangePicker =
MaterialDatePicker.Builder.dateRangePicker()
.setSelection(
androidx.core.util.Pair(
mFilterOptions.startDate,
mFilterOptions.endDate
)
)
.setCalendarConstraints(constraintsBuilder.build())
.build()
dateRangePicker.addOnPositiveButtonClickListener {
mFilterOptions.startDate = it.first!! // This is safe cause these should never be null
mFilterOptions.endDate = it.second!!
updateDateTextViews()
}
val datePickerFragment = DatePickerFragment.newInstance(which, currentTime, maxTime)
datePickerFragment.show(childFragmentManager, "date-picker")
dateRangePicker.show(childFragmentManager, "date-picker")
}
private fun validateFields() {
@ -283,4 +253,10 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
mCallback!!.onFilterOptionsSelected(mFilterOptions)
dismiss()
}
companion object {
private const val TAG = "FilterOptionsDialog"
const val KEY_FILTER_OPTIONS = "key_filter_options"
}
}

View File

@ -1,93 +0,0 @@
package cy.agorise.bitsybitshareswallet.views
import android.app.DatePickerDialog
import android.app.Dialog
import android.os.Bundle
import android.widget.DatePicker
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import com.google.android.material.picker.MaterialDatePickerDialog
import java.util.*
/**
* Lets the user select a Date and communicates the selection back to the parent fragment
* using the OnDateSetListener interface, which has to be implemented by the parent.
*/
class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener {
companion object {
const val TAG = "DatePickerFragment"
const val KEY_WHICH = "key_which"
const val KEY_CURRENT = "key_current"
const val KEY_MAX = "key_max"
fun newInstance(which: Int, currentTime: Long, maxTime: Long): DatePickerFragment {
val f = DatePickerFragment()
val bundle = Bundle()
bundle.putInt(KEY_WHICH, which)
bundle.putLong(KEY_CURRENT, currentTime)
bundle.putLong(KEY_MAX, maxTime)
f.arguments = bundle
return f
}
}
/**
* Callback used to communicate the date selection back to the parent
*/
private var mCallback: OnDateSetListener? = null
private var which: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
which = arguments!!.getInt(KEY_WHICH)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
onAttachToParentFragment(parentFragment)
val currentTime = arguments!!.getLong(KEY_CURRENT)
val maxTime = arguments!!.getLong(KEY_MAX)
// Use the current date as the default date in the picker
val calendar = Calendar.getInstance()
calendar.timeInMillis = currentTime
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH)
val day = calendar.get(Calendar.DAY_OF_MONTH)
// Create a new instance of DatePickerDialog and return it
val datePicker = MaterialDatePickerDialog(activity!!, this, year, month, day)
// Set maximum date allowed to today
datePicker.datePicker.maxDate = maxTime
return datePicker
}
override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int) {
val calendar = GregorianCalendar()
calendar.set(year, month, day)
mCallback?.onDateSet(which, calendar.time.time)
}
/**
* Attaches the current [DialogFragment] to its [Fragment] parent, to initialize the
* [OnDateSetListener] interface
*/
private fun onAttachToParentFragment(fragment: Fragment?) {
try {
mCallback = fragment as OnDateSetListener
} catch (e: ClassCastException) {
throw ClassCastException("$fragment must implement OnDateSetListener")
}
}
// Container Activity must implement this interface
interface OnDateSetListener {
fun onDateSet(which: Int, timestamp: Long)
}
}

View File

@ -13,7 +13,7 @@ import cy.agorise.bitsybitshareswallet.utils.hideKeyboard
* A TextInputEditText that hides the keyboard when the focus is removed from it and also lets you
* use actions ("Done", "Go", etc.) on multi-line edits.
*/
class MyTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
class MyTextInputEditText(context: Context, attrs: AttributeSet?) : TextInputEditText(context, attrs){
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? {
val connection = super.onCreateInputConnection(outAttrs)

View File

@ -138,7 +138,7 @@
<!-- Ignore Agorise Fees -->
<Switch
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchAgoriseFees"
android:layout_width="match_parent"
android:layout_height="wrap_content"