Improve custom field management

dev
Aurelien Hubert 7 years ago
parent 7d17287e65
commit 89730eae9c
  1. 3
      app/src/main/java/net/pokeranalytics/android/ui/adapter/RowRepresentableAdapter.kt
  2. 86
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt
  3. 1
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt
  4. 2
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  5. 9
      app/src/main/res/drawable/ic_list.xml
  6. 31
      app/src/main/res/layout/fragment_custom_view.xml

@ -55,10 +55,13 @@ class RowRepresentableAdapter(
return return
} }
/*
val index = this.dataSource.indexForRow(row) val index = this.dataSource.indexForRow(row)
if (index >= 0) { if (index >= 0) {
notifyItemChanged(index) notifyItemChanged(index)
} }
*/
notifyDataSetChanged()
} }
/** /**

@ -7,12 +7,14 @@ import android.view.ViewGroup
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.chip.ChipGroup
import kotlinx.android.synthetic.main.fragment_custom_view.* import kotlinx.android.synthetic.main.fragment_custom_view.*
import net.pokeranalytics.android.R import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.CustomField import net.pokeranalytics.android.model.realm.CustomField
import net.pokeranalytics.android.model.realm.CustomFieldEntry import net.pokeranalytics.android.model.realm.CustomFieldEntry
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.extensions.ChipGroupExtension
import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
@ -22,6 +24,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.NULL_TEXT
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
import kotlin.collections.ArrayList
/** /**
* Custom EditableDataFragment to manage the Transaction data * Custom EditableDataFragment to manage the Transaction data
@ -35,7 +38,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
} }
private val oldRows: ArrayList<RowRepresentable> = ArrayList() private val oldRows: ArrayList<RowRepresentable> = ArrayList()
private val currentEntriesOrder: ArrayList<CustomFieldEntry> = ArrayList()
private val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() { private val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
@ -54,6 +57,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
} }
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
if (target.adapterPosition <= 2) { if (target.adapterPosition <= 2) {
return false return false
} }
@ -147,7 +151,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
is CustomFieldEntry -> { is CustomFieldEntry -> {
val data = customField.editDescriptors(row) val data = customField.editDescriptors(row)
Timber.d("data: $data") Timber.d("data: $data")
BottomSheetFragment.create(fragmentManager, row, this, data, false) BottomSheetFragment.create(fragmentManager, row, this, data, isClearable = false, isDeletable = true)
} }
else -> super.onRowSelected(position, row, fromAction) else -> super.onRowSelected(position, row, fromAction)
} }
@ -158,16 +162,26 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
when (row) { when (row) {
is CustomFieldEntry -> { is CustomFieldEntry -> {
row.value = value as String? ?: "" row.value = value as String? ?: ""
rowRepresentableAdapter.refreshRow(row) customField.updateRowRepresentation()
rowRepresentableAdapter.notifyDataSetChanged()
} }
CustomFieldRow.TYPE -> { CustomFieldRow.TYPE -> {
customField.updateValue(value, row) customField.updateValue(value, row)
updateUI() updateUI()
updateAdapterUI() rowRepresentableAdapter.notifyDataSetChanged()
} }
else -> super.onRowValueChanged(value, row) else -> super.onRowValueChanged(value, row)
} }
}
override fun onRowDeleted(row: RowRepresentable) {
super.onRowDeleted(row)
when (row) {
is CustomFieldEntry -> {
customField.deleteEntry(row)
rowRepresentableAdapter.notifyDataSetChanged()
}
}
} }
/** /**
@ -178,15 +192,50 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
bottomBar.translationY = 72f.px bottomBar.translationY = 72f.px
bottomBar.visibility = View.VISIBLE bottomBar.visibility = View.VISIBLE
itemTouchHelper.attachToRecyclerView(recyclerView) if (customField.sortCondition == CustomField.Sort.DEFAULT.uniqueIdentifier) {
itemTouchHelper.attachToRecyclerView(recyclerView)
} else {
itemTouchHelper.attachToRecyclerView(null)
}
when(customField.sortCondition) {
CustomField.Sort.DEFAULT.uniqueIdentifier -> sortDefault.isChecked = true
CustomField.Sort.ASCENDING.uniqueIdentifier -> sortAscending.isChecked = true
CustomField.Sort.DESCENDING.uniqueIdentifier -> sortDescending.isChecked = true
}
addItem.setOnClickListener { addItem.setOnClickListener {
customField.addEntry() customField.addEntry()
updateAdapterUI() rowRepresentableAdapter.notifyDataSetChanged()
} }
sortChoices.setOnCheckedChangeListener(object : ChipGroupExtension.SingleSelectionOnCheckedListener() {
override fun onCheckedChanged(group: ChipGroup, checkedId: Int) {
super.onCheckedChanged(group, checkedId)
@SuppressWarnings
if (checkedId < 0) { // when unchecked, checkedId returns -1, causing a crash
return
}
when(checkedId) {
R.id.sortDefault -> customField.sortCondition = CustomField.Sort.DEFAULT.uniqueIdentifier
R.id.sortAscending -> customField.sortCondition = CustomField.Sort.ASCENDING.uniqueIdentifier
R.id.sortDescending -> customField.sortCondition = CustomField.Sort.DESCENDING.uniqueIdentifier
}
if (customField.sortCondition == CustomField.Sort.DEFAULT.uniqueIdentifier) {
itemTouchHelper.attachToRecyclerView(recyclerView)
} else {
itemTouchHelper.attachToRecyclerView(null)
}
rowRepresentableAdapter.notifyDataSetChanged()
}
})
updateUI() updateUI()
updateAdapterUI() rowRepresentableAdapter.notifyDataSetChanged()
} }
/** /**
@ -204,27 +253,4 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
} }
} }
/**
* Update adapter UI
*/
private fun updateAdapterUI() {
rowRepresentableAdapter.notifyDataSetChanged()
/*
//TODO: Code to animate changes
// Test:
// not really, i agree with your part about performance but notifyDataSetChanged() does not kill animations,
// to animate using notifyDataSetChanged(), a) call setHasStableIds(true) on your RecyclerView.Adapter object and b)
// override getItemId inside your Adapter to return a unique long value for each row and check it out, the animations do work
customField.adapterRows()?.let {
val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(it, oldRows))
rowRepresentableAdapter.updateRows(diffResult)
oldRows.clear()
oldRows.addAll(it)
}
*/
}
} }

@ -123,6 +123,7 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate {
val dataSource = getDataSource() val dataSource = getDataSource()
this.rowRepresentableAdapter = RowRepresentableAdapter(getDataSource(), this) this.rowRepresentableAdapter = RowRepresentableAdapter(getDataSource(), this)
this.rowRepresentableAdapter.setHasStableIds(true)
this.recyclerView.adapter = rowRepresentableAdapter this.recyclerView.adapter = rowRepresentableAdapter
// When creating an object, open automatically the keyboard for the first row // When creating an object, open automatically the keyboard for the first row

@ -188,6 +188,7 @@ enum class RowViewType(private var layoutRes: Int) {
// Icon // Icon
itemView.findViewById<AppCompatImageView?>(R.id.icon)?.let { imageView -> itemView.findViewById<AppCompatImageView?>(R.id.icon)?.let { imageView ->
imageView.setImageDrawable(null)
row.imageRes?.let { imageRes -> row.imageRes?.let { imageRes ->
imageView.setImageResource(imageRes) imageView.setImageResource(imageRes)
} }
@ -195,6 +196,7 @@ enum class RowViewType(private var layoutRes: Int) {
// Action // Action
itemView.findViewById<AppCompatImageView>(R.id.action)?.let { imageView -> itemView.findViewById<AppCompatImageView>(R.id.action)?.let { imageView ->
imageView.setImageDrawable(null)
row.imageRes?.let { imageRes -> row.imageRes?.let { imageRes ->
imageView.visibility = View.VISIBLE imageView.visibility = View.VISIBLE
imageView.setImageResource(imageRes) imageView.setImageResource(imageRes)

@ -0,0 +1,9 @@
<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="#FF000000"
android:pathData="M3,13h2v-2L3,11v2zM3,17h2v-2L3,15v2zM3,9h2L5,7L3,7v2zM7,13h14v-2L7,11v2zM7,17h14v-2L7,15v2zM7,7v2h14L21,7L7,7z"/>
</vector>

@ -65,6 +65,7 @@
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:visibility="gone" android:visibility="gone"
app:contentInsetStart="8dp" app:contentInsetStart="8dp"
app:contentInsetEnd="8dp"
tools:visibility="visible"> tools:visibility="visible">
<FrameLayout <FrameLayout
@ -76,10 +77,40 @@
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:padding="4dp" android:padding="4dp"
android:layout_gravity="end"
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/ic_add" android:src="@drawable/ic_add"
android:tint="@color/green" /> android:tint="@color/green" />
<com.google.android.material.chip.ChipGroup
android:id="@+id/sortChoices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:chipSpacing="8dp"
android:layout_gravity="center"
app:singleSelection="true">
<com.google.android.material.chip.Chip
android:id="@+id/sortDefault"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text=" - " />
<com.google.android.material.chip.Chip
android:id="@+id/sortAscending"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A..Z" />
<com.google.android.material.chip.Chip
android:id="@+id/sortDescending"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Z..A" />
</com.google.android.material.chip.ChipGroup>
</FrameLayout> </FrameLayout>
</com.google.android.material.bottomappbar.BottomAppBar> </com.google.android.material.bottomappbar.BottomAppBar>

Loading…
Cancel
Save