输入超过 6 行时 RecyclerView 出现问题 [已关闭]

问题描述 投票:0回答:1

我正在用 Kotlin + XML 制作一个应用程序,但 RecyclerView 有问题:

我有两个字段 etPerson 和 etContribution,还有一个 btnAdd 按钮将该人添加到参与者列表中,并更新 rvParticipants 视图以显示更新后的列表。当第 7 个参与者进入时,问题就出现了; rvParticipants 列表通过重复第一行被覆盖。

MainActivity.kt

MainActivity 类:AppCompatActivity() {

// Variables for payment calculation
private var totalPayment = 0.0
private var paymentPerPerson = 0.0

// List of participants
private val participantList = mutableListOf<Participant>()

// Views
private lateinit var etExpenditure: EditText
private lateinit var etNPersons: EditText
private lateinit var tvPayment: TextView
private lateinit var etPersonName: EditText
private lateinit var etContribution: EditText
private lateinit var tvOwe: TextView
private lateinit var rvParticipants: RecyclerView

// Adapter for the participant list
private lateinit var participantAdapter: ParticipantAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Initialize views
    initializeViews()

    // Setup RecyclerView and adapter
    setupRecyclerView()

    // Configure "Add" button
    findViewById<Button>(R.id.btnAdd).setOnClickListener {
        addParticipant()
    }

    // Configure "Calculate" button
    findViewById<Button>(R.id.btnCalculate).setOnClickListener {
        calculatePayment()
    }

    // Configure TextWatcher for etExpenditure
    etExpenditure.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            // No implementation required
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            // No implementation required
        }

        override fun afterTextChanged(s: Editable?) {
            calculatePayment()
        }
    })

    // Configure TextWatcher for etNPersons
    etNPersons.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            // No implementation required
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            // No implementation required
        }

        override fun afterTextChanged(s: Editable?) {
            calculatePayment()
        }
    })
}

// Method to initialize views
private fun initializeViews() {
    etExpenditure = findViewById(R.id.etExpenditure)
    etNPersons = findViewById(R.id.etNPersons)
    tvPayment = findViewById(R.id.tvPayment)
    etPersonName = findViewById(R.id.etPersonName)
    etContribution = findViewById(R.id.etContribution)
    tvOwe = findViewById(R.id.tvOwe)
    rvParticipants = findViewById(R.id.rvParticipants)
}

// Method to setup RecyclerView and adapter
private fun setupRecyclerView() {
    participantAdapter = ParticipantAdapter(participantList, paymentPerPerson)
    rvParticipants.adapter = participantAdapter
    rvParticipants.layoutManager = LinearLayoutManager(this)
}

// Method to add a participant
private fun addParticipant() {
    val name = etPersonName.text.toString()
    val contribution = etContribution.text.toString().toDoubleOrNull()

    if (name.isNotEmpty() && contribution != null) {
        val participant = Participant(name, contribution)
        participantList.add(participant)

        participantAdapter.notifyItemInserted(participantList.size - 1)

        etPersonName.text.clear()
        etContribution.text.clear()

        calculateDebts()
    } else {
        // Show error if the name is empty or the contribution is not valid
    }
}

// Method to calculate payments and debts
private fun calculatePayment() {
    val expenditure = etExpenditure.text.toString().toDoubleOrNull()
    val persons = etNPersons.text.toString().toIntOrNull()

    if (expenditure != null && persons != null) {
        totalPayment = expenditure

        paymentPerPerson = totalPayment / persons

        tvPayment.text = "$" + String.format("%.2f", paymentPerPerson)

        calculateDebts()
    } else {
        // Show error if the expenditure or the number of persons is not valid
        tvPayment.text = ""
        participantList.forEach { participant ->
            participant.totalContribution = 0.0
        }
        participantAdapter.updatePaymentPerPerson(0.0)
        participantAdapter.notifyDataSetChanged()
    }
}

// Method to calculate debts for each participant
private fun calculateDebts() {
    val nPersons = etNPersons.text.toString().toInt()

    participantList.forEach { participant ->
        participant.totalContribution = paymentPerPerson - participant.contribution
    }

    participantAdapter.updatePaymentPerPerson(paymentPerPerson)
    participantAdapter.notifyDataSetChanged()
}

}

**ParticipantAdapter.kt**

类 ParticipantAdapter( 私人 val 参与者:MutableList, private var paymentPerPerson:双倍 ) : RecyclerView.Adapter() {

// ViewHolder class to hold references to the views of each list item
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val tvName: TextInputEditText = itemView.findViewById(R.id.tvName)
    val tvContribution: TextInputEditText = itemView.findViewById(R.id.tvContribution)
    val tvOwe: TextInputEditText = itemView.findViewById(R.id.tvOwe)
    val btnDelete: Button = itemView.findViewById(R.id.btnDelete)
    val tvOweLayout: TextInputLayout = itemView.findViewById(R.id.tvOweLayout)
    val tvNameLayout: TextInputLayout = itemView.findViewById(R.id.tvNameLayout)
}

// Method called when a new ViewHolder is created
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    // Inflate the layout of the list item
    val view = LayoutInflater.from(parent.context)
        .inflate(R.layout.item_participant, parent, false)
    return ViewHolder(view)
}

// Method called when a ViewHolder is bound to the data at a specific position
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val participant = participants[position]

    // Set the values of the TextViews
    holder.tvName.setText(participant.name)
    holder.tvContribution.setText(participant.contribution.toString())
    holder.tvOwe.setText(participant.totalContribution.toString())

    // Set the font type to bold
    holder.tvName.setTypeface(null, Typeface.BOLD)
    holder.tvContribution.setTypeface(null, Typeface.BOLD)
    holder.tvOwe.setTypeface(null, Typeface.BOLD)

    // Get the text color and background color of tvOwe
    val textColor = getOweTextColor(participant.totalContribution)
    val backgroundColor = getOweBackgroundColor(participant.totalContribution)

    // Set the text color and background color of tvOwe
    holder.tvOwe.setTextColor(textColor)
    holder.tvOweLayout.boxBackgroundColor = backgroundColor

    // Set the background color of tvName
    updateNameBackgroundColor(holder, backgroundColor)

    // Configure the delete button
    holder.btnDelete.setOnClickListener {
        participants.removeAt(position)
        notifyItemRemoved(position)
    }

    // Configure the TextWatcher for tvContribution
    holder.tvContribution.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            // No implementation required
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            // No implementation required
        }

        override fun afterTextChanged(s: Editable?) {
            val contribution = s.toString().toDoubleOrNull() ?: 0.0
            participant.contribution = contribution
            participant.totalContribution = calculateTotalContribution(participant)
            holder.tvOwe.setText(participant.totalContribution.toString())
            val textColor = getOweTextColor(participant.totalContribution)
            val backgroundColor = getOweBackgroundColor(participant.totalContribution)
            holder.tvOwe.setTextColor(textColor)
            holder.tvOweLayout.boxBackgroundColor = backgroundColor
            updateNameBackgroundColor(holder, backgroundColor)
        }
    })

    // Configure the TextWatcher for tvName
    holder.tvName.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            // No implementation required
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            // No implementation required
        }

        override fun afterTextChanged(s: Editable?) {
            val name = s.toString()
            participant.name = name
        }
    })
}

// Method that returns the number of items in the list
override fun getItemCount(): Int {
    return participants.size
}

// Method to get the text color of tvOwe based on the total contribution
private fun getOweTextColor(totalContribution: Double): Int {
    return when {
        totalContribution == 0.0 -> Color.BLUE
        totalContribution > 0.0 -> Color.RED
        totalContribution < 0.0 -> Color.parseColor("#004D00") // Change the green color value here
        else -> Color.TRANSPARENT
    }
}

// Method to get the background color of tvOwe based on the total contribution
private fun getOweBackgroundColor(totalContribution: Double): Int {
    return when {
        totalContribution == 0.0 -> Color.parseColor("#CCCCCC")
        totalContribution > 0.0 -> Color.parseColor("#FFD4D4")
        totalContribution < 0.0 -> Color.parseColor("#E2FFD7")
        else -> Color.TRANSPARENT
    }
}

// Method to update the background color of tvName based on the background color of tvOwe
private fun updateNameBackgroundColor(holder: ViewHolder, backgroundColor: Int) {
    holder.tvNameLayout.boxBackgroundColor = backgroundColor
}

// Method to add a participant to the list
fun addParticipant(participant: Participant) {
    participants.add(participant)
    notifyDataSetChanged()
}

// Method to update the value of paymentPerPerson
fun updatePaymentPerPerson(payment: Double) {
    paymentPerPerson = payment
    notifyDataSetChanged()
}

// Method to calculate the total contribution of a participant
private fun calculateTotalContribution(participant: Participant): Double {
    return paymentPerPerson - participant.contribution
}

}

android kotlin android-recyclerview
1个回答
0
投票

addParticipant 方法中,您可以替换

participantAdapter.notifyItemInserted(participantList.size - 1)

participantAdapter.notifyDataSetChanged()

这只是使其工作的简单方法,使用带有大列表的notifyDataSetChanged将使您的代码变慢。要使用notifyItemInserted(),您需要更多地控制索引位置

© www.soinside.com 2019 - 2024. All rights reserved.