parent
e80ef58493
commit
d77317cdde
@ -0,0 +1,167 @@ |
||||
package net.pokeranalytics.android.ui.adapter |
||||
|
||||
import android.content.Context |
||||
import android.view.LayoutInflater |
||||
import android.view.View |
||||
import android.view.ViewGroup |
||||
import androidx.appcompat.widget.AppCompatTextView |
||||
import androidx.recyclerview.widget.RecyclerView |
||||
import io.realm.RealmResults |
||||
import kotlinx.android.synthetic.main.row_transaction.view.* |
||||
import net.pokeranalytics.android.R |
||||
import net.pokeranalytics.android.model.realm.Transaction |
||||
import net.pokeranalytics.android.ui.view.BindableHolder |
||||
import net.pokeranalytics.android.ui.view.RowViewType |
||||
import net.pokeranalytics.android.util.NULL_TEXT |
||||
import net.pokeranalytics.android.util.extensions.getMonthAndYear |
||||
import timber.log.Timber |
||||
import java.util.* |
||||
import kotlin.collections.HashMap |
||||
|
||||
|
||||
/** |
||||
* An adapter capable of displaying a list of RowRepresentables |
||||
* @param dataSource the datasource providing rows |
||||
* @param delegate the delegate, notified of UI actions |
||||
*/ |
||||
class FeedTransactionRowRepresentableAdapter( |
||||
var delegate: RowRepresentableDelegate? = null, |
||||
var realmTransactions: RealmResults<Transaction>, |
||||
var distinctTransactionsHeaders: RealmResults<Transaction> |
||||
) : |
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
||||
|
||||
private var headersPositions = HashMap<Int, Date?>() |
||||
private lateinit var sortedHeaders: SortedMap<Int, Date?> |
||||
|
||||
init { |
||||
refreshData() |
||||
} |
||||
|
||||
/** |
||||
* Display a transaction view |
||||
*/ |
||||
inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { |
||||
fun bind(position: Int, row: Transaction?, adapter: FeedTransactionRowRepresentableAdapter) { |
||||
|
||||
itemView.transactionRow.setData(row as Transaction) |
||||
val listener = View.OnClickListener { |
||||
adapter.delegate?.onRowSelected(position, row) |
||||
} |
||||
itemView.transactionRow.setOnClickListener(listener) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Display a header |
||||
*/ |
||||
inner class HeaderTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { |
||||
fun bind(position: Int, title: String, adapter: FeedTransactionRowRepresentableAdapter) { |
||||
// Title |
||||
itemView.findViewById<AppCompatTextView>(R.id.title)?.let { |
||||
it.text = title |
||||
} |
||||
} |
||||
} |
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { |
||||
if (viewType == RowViewType.ROW_TRANSACTION.ordinal) { |
||||
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_transaction, parent, false) |
||||
return RowTransactionViewHolder(layout) |
||||
} else { |
||||
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_header_title, parent, false) |
||||
return HeaderTitleViewHolder(layout) |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
override fun getItemViewType(position: Int): Int { |
||||
if (sortedHeaders.containsKey(position)) { |
||||
return RowViewType.HEADER_TITLE.ordinal |
||||
} else { |
||||
return RowViewType.ROW_TRANSACTION.ordinal |
||||
} |
||||
} |
||||
|
||||
override fun getItemCount(): Int { |
||||
return realmTransactions.size + distinctTransactionsHeaders.size |
||||
} |
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { |
||||
if (holder is RowTransactionViewHolder) { |
||||
holder.bind(position, getTransactionForPosition(position), this) |
||||
} else if (holder is HeaderTitleViewHolder) { |
||||
holder.bind(position, getHeaderForPosition(holder.itemView.context, position), this) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return the header |
||||
*/ |
||||
private fun getHeaderForPosition(context: Context, position: Int): String { |
||||
if (sortedHeaders.containsKey(position)) { |
||||
val realmHeaderPosition = sortedHeaders.keys.indexOf(position) |
||||
return distinctTransactionsHeaders[realmHeaderPosition]?.date?.getMonthAndYear() ?: "" |
||||
} |
||||
return NULL_TEXT |
||||
} |
||||
|
||||
/** |
||||
* Get real index |
||||
*/ |
||||
private fun getTransactionForPosition(position: Int): Transaction? { |
||||
|
||||
// Row position |
||||
var headersBefore = 0 |
||||
for (key in sortedHeaders.keys) { |
||||
if (position > key) { |
||||
headersBefore++ |
||||
} else { |
||||
break |
||||
} |
||||
} |
||||
|
||||
return realmTransactions[position - headersBefore] |
||||
} |
||||
|
||||
/** |
||||
* Refresh headers positions |
||||
*/ |
||||
fun refreshData() { |
||||
|
||||
headersPositions.clear() |
||||
|
||||
val start = System.currentTimeMillis() |
||||
|
||||
var previousYear = Int.MAX_VALUE |
||||
var previousMonth = Int.MAX_VALUE |
||||
|
||||
val calendar = Calendar.getInstance() |
||||
|
||||
// Add headers if the date doesn't exist yet |
||||
for ((index, transaction) in realmTransactions.withIndex()) { |
||||
calendar.time = transaction.date |
||||
if (checkHeaderCondition(calendar, previousYear, previousMonth)) { |
||||
headersPositions[index + headersPositions.size] = transaction.date |
||||
previousYear = calendar.get(Calendar.YEAR) |
||||
previousMonth = calendar.get(Calendar.MONTH) |
||||
} |
||||
} |
||||
|
||||
sortedHeaders = headersPositions.toSortedMap() |
||||
|
||||
Timber.d("Create viewTypesPositions in: ${System.currentTimeMillis() - start}ms") |
||||
} |
||||
|
||||
/** |
||||
* Check if we need to add a header |
||||
* Can be change to manage different condition |
||||
*/ |
||||
private fun checkHeaderCondition(currentCalendar: Calendar, previousYear: Int, previousMonth: Int): Boolean { |
||||
return currentCalendar.get(Calendar.YEAR) == previousYear && currentCalendar.get(Calendar.MONTH) < previousMonth || (currentCalendar.get(Calendar.YEAR) < previousYear) |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
Loading…
Reference in new issue