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.
This commit is contained in:
parent
dd1bf98e5d
commit
7e12224795
5 changed files with 46 additions and 163 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
date = Date(mFilterOptions.endDate)
|
||||
binding.tvEndDate.text = dateFormat.format(date)
|
||||
}
|
||||
|
||||
val datePickerFragment = DatePickerFragment.newInstance(which, currentTime, maxTime)
|
||||
datePickerFragment.show(childFragmentManager, "date-picker")
|
||||
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()
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue