Open WaheedAbbas opened 2 years ago
Hi @WaheedAbbas, that looks weird, could you send a minimal project showing that issue?
I created a separate project to explain the issue. The view basically has a question title, and Yes/No radio buttons, hitting yes would show an input field.
MainActivity:
class MainActivity : FormActivity() {
private val TAG = "MainActivity"
override fun initForm() {
adapter?.registerViewHolder(
FormItemClosedQuestion::class.java,
R.layout.availablity_and_price_layout,
FormClosedQuestionViewHolder::class.java
)
adapter?.apply {
+questionsSection
}
}
private val questionsSection: FormItemSection = FormItemSection().apply {
title = "Questions Section"
enableCollapse = true
add(FormItemClosedQuestion().question("Question Price 1").onValueChanged {
Log.d(TAG, "Price: ${it.price}")
})
add(FormItemClosedQuestion().question("Question Price 2").onValueChanged {
Log.d(TAG, "Price: ${it.price}")
})
add(FormItemClosedQuestion().question("Question Price 3").onValueChanged {
Log.d(TAG, "Price: ${it.price}")
})
add(FormItemClosedQuestion().question("Question Price 4").onValueChanged {
Log.d(TAG, "Price: ${it.price}")
})
add(FormItemClosedQuestion().question("Question Price 5").onValueChanged {
Log.d(TAG, "Price: ${it.price}")
})
}
}
FormClosedQuestionViewHolder:
class FormClosedQuestionViewHolder(inflater: LayoutInflater, resource: Int, parent: ViewGroup) :
FormViewHolder(inflater, resource, parent) {
private var questionTextView : TextView? = null
private var priceIEdt : EditText? = null
private var actionYesRadioBtn : RadioButton? = null
init {
questionTextView = itemView.findViewById(R.id.question_text)
priceIEdt = itemView.findViewById(R.id.price_edt)
actionYesRadioBtn = itemView.findViewById(R.id.action_yes_radio_btn)
}
override fun bind(s: FormItem, listener: FormItemCallback?) {
super.bind(s, listener)
if (s is FormItemClosedQuestion) {
questionTextView?.text = s.question
priceIEdt?.setText(s.price)
Log.d("FormClosedQuestionViewHolder", "bind(): ${s.question} has ${s.price}")
actionYesRadioBtn?.setOnCheckedChangeListener { compoundButton, isChecked ->
if(isChecked) {
priceIEdt?.visibility = View.VISIBLE
} else {
priceIEdt?.visibility = View.GONE
}
}
priceIEdt?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
s.price = p0.toString()
listener?.onValueChanged(s)
}
override fun afterTextChanged(p0: Editable?) {
}
})
}
}
}
open class FormItemClosedQuestion : FormItem() {
var question: String = ""
var price : String = ""
}
fun <T : FormItemClosedQuestion> T.question(question: String) = apply {
this.question = question
}
fun <T : FormItemClosedQuestion> T.price(price: String) = apply {
this.price = price
}
availablity_and_price_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="10dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/question_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Toblerone Stick Chocolate Honey and Almond 100 ML"
/>
<RadioGroup
android:id="@+id/actions_toggle_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="5dp"
android:elevation="5dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/action_yes_radio_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Yes" />
<RadioButton
android:id="@+id/action_no_radio_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:buttonTint="@color/teal_200"
android:checked="true"
android:text="No" />
</RadioGroup>
<EditText
android:id="@+id/price_edt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:padding="10dp"
android:imeOptions="actionDone"
android:visibility="gone"
android:hint="Price" />
</LinearLayout>
While creating the example project I found out that the issue only happens when you increase the number of elements. When you test the app with 5 FormItems in the section, it would work fine but it would break when you increase them to 15.
Thanks @WaheedAbbas, could you email me the minimal project( ben.qiao@gmail.com)?
I have shared the project with you using OneDrive Link since Gmail was blocking it for security reasons. Let me know if you get it. Thanks. :) @tianzhuqiao
@WaheedAbbas , the issue is in the way to call addTextChangedListener
; it shall be called in init
(as it only needs to be set once), not in bind
. bind
will be called many times, e.g., if in bind
, when re-use the cell, priceIEdt?.setText(s.price)
may trigger the onTextChanged
(set by previous item, so s
is also from the previous item).
init {
questionTextView = itemView.findViewById(R.id.question_text)
priceIEdt = itemView.findViewById(R.id.price_edt)
actionYesRadioBtn = itemView.findViewById(R.id.action_yes_radio_btn)
actionYesRadioBtn?.setOnCheckedChangeListener { compoundButton, isChecked ->
if(isChecked) {
priceIEdt?.visibility = View.VISIBLE
} else {
priceIEdt?.visibility = View.GONE
}
}
priceIEdt?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
(item as? FormItemClosedQuestion)?.let {
it.price = p0.toString()
listener?.onValueChanged(it)
}
}
override fun afterTextChanged(p0: Editable?) {
}
})
}
Thank you so much. @tianzhuqiao That solved the issue for me. I also had to add a property in FormItem class to set and get value for the radio buttons. FormItemClosedQuestion:
open class FormItemClosedQuestion : FormItem() {
var question: String = ""
var price : String = ""
var isYes = false
}
Then get in bind
method.
override fun bind(s: FormItem, listener: FormItemCallback?) {
super.bind(s, listener)
if (s is FormItemClosedQuestion) {
questionTextView?.text = s.question
priceIEdt?.setText(s.price)
actionYesRadioBtn?.isChecked = s.isYes
actionNoRadioBtn?.isChecked = !s.isYes
Log.d("FormClosedQuestionViewHolder", "bind(): ${s.question} has ${s.price}")
}
}
Now it works perfectly fine. Thanks again for such an awesome library.
I created a custom view that has a custom input field. When I scroll, the value of one input field ends up filling some other random input field. The values keep switching to a different input field filling other boxes as well with the same value every time I scroll up and down. This does not seem to be the case with FormItemText() or other existing input form items. Can you please have a look into this?
MainActivity: