Below is my recyclerview adapter, whenever my recyclerview is populated I iterate through all views and calculate total incomes and expenses and get the balance in a variable called MainAccountBalance. how to pass this variable value to my Mainfragment so I can show it on a textview on top of the recyclerview? any time the recyclerview items changes, or the recyclerview populated/repopulated the variable should automatically passed and updated on the textview.
Am new to this, a Kotlin detailed code would really be appreciated. Thanks.
class RecyclerViewAdapter(options: FirestoreRecyclerOptions<DataModel>) : FirestoreRecyclerAdapter<DataModel, RecyclerViewAdapter.MyViewHolder>(options) {
private var listener: OnItemClickListener? = null
private var MainAccountBalance: Double = 0.00
override fun onBindViewHolder(holder: MyViewHolder, position: Int, model: DataModel) {
holder.noteTextView.setText(model.transaction_note)
holder.transactionDateTextView.setText(model.transaction_timestamp?.let { convertLongToDateString(it) }).toString()
var totalIncome: Double = 0.0
var totalexpense: Double = 0.0
// change the money to red or blue based on the transaction type
val transaction_type = model.transaction_type
if (transaction_type=="expense") {
holder.amountTextView.setTextColor(Color.parseColor("#D12E9A"));
holder.amountTextView.text = model.transaction_amount?.let { replaceArabicNumbers(convertIntToCurrencyString(it)) }
totalexpense =model.transaction_amount!! totalexpense
}
else {
holder.amountTextView.setTextColor(Color.parseColor("#3A86FF"))
holder.amountTextView.text = model.transaction_amount?.let { replaceArabicNumbers(convertIntToCurrencyString(it)) }
totalIncome = model.transaction_amount!! totalIncome
}
MainAccountBalance = totalIncome - totalexpense
}
public fun replaceArabicNumbers(original: kotlin.String): kotlin.String {
return original
.replace("٠","0")
.replace("١","1")
.replace("٢","2")
.replace("٣","3")
.replace("٤","4")
.replace("٥","5")
.replace("٦","6")
.replace("٧","7")
.replace("٨","8")
.replace("٩","9")
// arabic decimal point = U 066B
.replace("٫",".")
// thousands grouping seperator = U 066C
.replace("٬",",")
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val v: View = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_main_account_item,
parent, false)
return MyViewHolder(v)
}
fun deleteItem(position: Int) {
snapshots.getSnapshot(position).reference.delete()
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var transactionDateTextView: TextView
var noteTextView: TextView
var amountTextView: TextView
init {
transactionDateTextView = itemView.findViewById(R.id.transactionDateTextView)
noteTextView = itemView.findViewById(R.id.noteTextView)
amountTextView = itemView.findViewById(R.id.amountTextView)//
itemView.setOnClickListener {
val position = adapterPosition
if (position != RecyclerView.NO_POSITION && listener != null) {
listener!!.onItemClick(snapshots.getSnapshot(position), position)
}
}
}
}
interface OnItemClickListener {
fun onItemClick(documentSnapshot: DocumentSnapshot?, position: Int)
}
fun setOnItemClickListener(listener: OnItemClickListener?) {
this.listener = listener
}
fun convertLongToDateString(systemTime: Long): kotlin.String {
//return SimpleDateFormat("dd-MM-yyyy' Time: 'HH:mm")
return SimpleDateFormat("dd-MM-yyyy")
.format(systemTime).toString()
}
fun convertIntToCurrencyString(money :Double): kotlin.String {
//currency formatter
val formatter: NumberFormat = DecimalFormat("#,###.##")
val myNumber = money
val formattedNumber: kotlin.String = formatter.format(myNumber)
return formattedNumber
//currency formatter
}
}
CodePudding user response:
because you are using FirestoreRecyclerAdapter
data is updated automatically and you have no control on it, there are some options I explain one of them that can help you :
in your adapter class add a method like this :
fun getAcountBalance():String{
// iterate and update value of MainAccountBalance
// add a log to check if your calculated value is correct
return MainAccountBalance.toString()
}
in your activity or fragment where you are using this adapter do this (if you are using fragment do onCreate part in onViewCreated) :
override fun onCreate(savedInstanceState: Bundle?) {
.....
// difine yourTopTextView before this part
// initialize your adapter
val yourAdapter = RecyclerViewAdapter(...)
//add observer to adapter changes
yourAdapter.registerAdapterDataObserver(object :
RecyclerView.AdapterDataObserver() {
// setText the view after any change
override fun onChanged() {
super.onChanged()
setTextOfYourView(yourAdapter.getAcountBalance())
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
super.onItemRangeChanged(positionStart, itemCount)
setTextOfYourView(yourAdapter.getAcountBalance())
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
super.onItemRangeChanged(positionStart, itemCount, payload)
setTextOfYourView(yourAdapter.getAcountBalance())
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
super.onItemRangeInserted(positionStart, itemCount)
setTextOfYourView(yourAdapter.getAcountBalance())
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
super.onItemRangeRemoved(positionStart, itemCount)
setTextOfYourView(yourAdapter.getAcountBalance())
}
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
super.onItemRangeMoved(fromPosition, toPosition, itemCount)
setTextOfYourView(yourAdapter.getAcountBalance())
}
})
// set adapter to recycler view
youRecyclerView.adapter= yourAdapter
}
fun setTextOfYourView(balnce :String){
yourTopTextView.setText(balnce)
}