Improve custom field, add move, work in progress

dev
Aurelien Hubert 7 years ago
parent d3178e656b
commit d0128700d6
  1. 37
      app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt
  2. 32
      app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt
  3. 103
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt
  4. 1
      app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt

@ -11,12 +11,14 @@ import net.pokeranalytics.android.model.interfaces.NameManageable
import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.model.interfaces.SaveValidityStatus
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import timber.log.Timber import timber.log.Timber
import java.util.* import java.util.*
import kotlin.collections.ArrayList
open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDataSource, RowRepresentable { open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDataSource, RowRepresentable {
@ -57,7 +59,6 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa
private var rowRepresentation: List<RowRepresentable> = mutableListOf() private var rowRepresentation: List<RowRepresentable> = mutableListOf()
override fun adapterRows(): List<RowRepresentable>? { override fun adapterRows(): List<RowRepresentable>? {
Timber.d("adapterRows: ${rowRepresentation.size}")
return rowRepresentation return rowRepresentation
} }
@ -93,6 +94,16 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa
return R.string.relationship_error return R.string.relationship_error
} }
override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? {
return when (row) {
is CustomFieldEntry -> row.editingDescriptors(
mapOf(
"defaultValue" to row.value
)
)
else -> null
}
}
private fun updatedRowRepresentationForCurrentState(): List<RowRepresentable> { private fun updatedRowRepresentationForCurrentState(): List<RowRepresentable> {
val rows = ArrayList<RowRepresentable>() val rows = ArrayList<RowRepresentable>()
@ -101,11 +112,14 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa
if (type == Type.LIST.ordinal && entries.size >= 0) { if (type == Type.LIST.ordinal && entries.size >= 0) {
rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, R.string.items_list)) rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, R.string.items_list))
entries.forEach {entry -> if (entries.isNotEmpty()) {
rows.add(CustomizableRowRepresentable(RowViewType.TITLE, title = entry.value)) Timber.d("entries: ${entries.size}")
entries.sortBy { it.order }
rows.addAll(entries)
} }
} }
Timber.d("rows: ${rows.size}")
return rows return rows
} }
@ -113,4 +127,21 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa
this.rowRepresentation = this.updatedRowRepresentationForCurrentState() this.rowRepresentation = this.updatedRowRepresentationForCurrentState()
} }
/**
* Add entry
*/
fun addEntry() {
val entry = CustomFieldEntry()
entry.order = (entries.lastOrNull()?.order ?: 0) + 1
entries.add(entry)
updateRowRepresentation()
}
/**
*
*/
fun deleteEntry() {
}
} }

@ -1,15 +1,45 @@
package net.pokeranalytics.android.model.realm package net.pokeranalytics.android.model.realm
import android.content.Context
import android.text.InputType
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.R
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.NULL_TEXT
import java.util.* import java.util.*
open class CustomFieldEntry : RealmObject() { open class CustomFieldEntry : RealmObject(), RowRepresentable {
@PrimaryKey @PrimaryKey
var id = UUID.randomUUID().toString() var id = UUID.randomUUID().toString()
var value: String = "" var value: String = ""
var order: Int = 0 var order: Int = 0
@Ignore
override val viewType: Int = RowViewType.TITLE.ordinal
@Ignore
override val bottomSheetType: BottomSheetType = BottomSheetType.EDIT_TEXT
override fun localizedTitle(context: Context): String {
return context.getString(R.string.value)
}
override fun getDisplayName(): String {
return if (value.isNotEmpty()) value else NULL_TEXT
}
override fun editingDescriptors(map: Map<String, Any?>): ArrayList<RowRepresentableEditDescriptor>? {
val defaultValue: Any? by map
return arrayListOf(
RowRepresentableEditDescriptor(defaultValue, R.string.value, InputType.TYPE_CLASS_TEXT)
)
}
} }

@ -5,15 +5,17 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
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.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.px import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment
import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableDiffCallback
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
@ -34,6 +36,71 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
private val oldRows: ArrayList<RowRepresentable> = ArrayList() private val oldRows: ArrayList<RowRepresentable> = ArrayList()
private val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
var dragFrom = -1
var dragTo = -1
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
return if (viewHolder.adapterPosition <= 2) {
return 0
} else {
makeFlag(
ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.DOWN
or ItemTouchHelper.UP or ItemTouchHelper.START or ItemTouchHelper.END
)
}
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
if (target.adapterPosition <= 2) {
return false
}
val fromPosition = viewHolder.adapterPosition
val toPosition = target.adapterPosition
if (dragFrom == -1) {
dragFrom = viewHolder.adapterPosition - 1 // Header
}
dragTo = target.adapterPosition - 1 // Header
rowRepresentableAdapter.notifyItemMoved(fromPosition, toPosition)
/*
adapterRows()?.filter { it is CustomFieldEntry }?.forEachIndexed { index, rowRepresentable ->
val entry = rowRepresentable as CustomFieldEntry
Timber.d("$index ${entry.value} ${entry.order}")
}
*/
return true
}
override fun onMoved(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, fromPos: Int, target: RecyclerView.ViewHolder, toPos: Int, x: Int, y: Int) {
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
Collections.swap(customField.entries, fromPos - (CustomFieldRow.values().size + 1), toPos - (CustomFieldRow.values().size + 1))
customField.entries.forEachIndexed { index, rowRepresentable ->
val entry = rowRepresentable as CustomFieldEntry
entry.order = index
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
dragFrom = -1
dragTo = -1
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
}
})
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState) super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_custom_view, container, false) return inflater.inflate(R.layout.fragment_custom_view, container, false)
@ -78,23 +145,37 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? { override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? {
return when (row) { return when (row) {
SimpleRow.NAME -> row.editingDescriptors(mapOf("defaultValue" to this.customField.name)) SimpleRow.NAME -> row.editingDescriptors(mapOf("defaultValue" to this.customField.name))
is CustomFieldEntry -> row.editingDescriptors(mapOf("defaultValue" to row.value))
else -> null else -> null
} }
} }
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
when (row) { when (row) {
is CustomFieldEntry -> {
val data = customField.editDescriptors(row)
Timber.d("data: $data")
BottomSheetFragment.create(fragmentManager, row, this, data, false)
}
else -> super.onRowSelected(position, row, fromAction) else -> super.onRowSelected(position, row, fromAction)
} }
} }
override fun onRowValueChanged(value: Any?, row: RowRepresentable) { override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
//super.onRowValueChanged(value, row)
Timber.d("onRowValueChanged: $row => $value") Timber.d("onRowValueChanged: $row => $value")
when (row) {
is CustomFieldEntry -> {
row.value = value as String? ?: ""
rowRepresentableAdapter.refreshRow(row)
}
CustomFieldRow.TYPE -> {
customField.updateValue(value, row) customField.updateValue(value, row)
updateUI() updateUI()
updateAdapterUI() updateAdapterUI()
} }
}
}
/** /**
* Init UI * Init UI
@ -104,8 +185,11 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
bottomBar.translationY = 72f.px bottomBar.translationY = 72f.px
bottomBar.visibility = View.VISIBLE bottomBar.visibility = View.VISIBLE
itemTouchHelper.attachToRecyclerView(recyclerView)
addItem.setOnClickListener { addItem.setOnClickListener {
Timber.d("Click on add item") customField.addEntry()
updateAdapterUI()
} }
updateUI() updateUI()
@ -123,7 +207,6 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
} else { } else {
bottomBar.animate().translationY(72f.px) bottomBar.animate().translationY(72f.px)
.setInterpolator(FastOutSlowInInterpolator()) .setInterpolator(FastOutSlowInInterpolator())
.withEndAction { }
.start() .start()
} }
} }
@ -132,6 +215,15 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
* Update adapter UI * Update adapter UI
*/ */
private fun updateAdapterUI() { 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 { customField.adapterRows()?.let {
val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(it, oldRows)) val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(it, oldRows))
rowRepresentableAdapter.updateRows(diffResult) rowRepresentableAdapter.updateRows(diffResult)
@ -139,6 +231,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa
oldRows.clear() oldRows.clear()
oldRows.addAll(it) oldRows.addAll(it)
} }
*/
} }
} }

@ -70,6 +70,7 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate {
} }
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
BottomSheetFragment.create(fragmentManager, row, this, getDataSource().editDescriptors(row)) BottomSheetFragment.create(fragmentManager, row, this, getDataSource().editDescriptors(row))
} }

Loading…
Cancel
Save