Reputation: 138
i have dynamic list question from API with recyclerview but every question have different type (Input Text,Radio Button,etc) so i need make list with diferent type in my recyclerview. i seacrh on internet also in this site i need to check list type in onCreateViewHolder and return view with different layout source but i still cant solve my problem,my result not return any error but my list is always return just first type view (input_field layout) but canot return second type view (input_selection layout)
this my adapter
class QuestionViewAdapter(private val listQuestion: ArrayList<Question>) : RecyclerView.Adapter<QuestionViewAdapter.InputField>() {
private var context: Context? = null
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): InputField {
context = viewGroup.context
if(listQuestion[i].prodeskel_type_id == 1){
var view = LayoutInflater.from(viewGroup.context).inflate(R.layout.input_field, viewGroup, false)
return InputField(view)
} else {
var view = LayoutInflater.from(viewGroup.context).inflate(R.layout.input_selection, viewGroup, false)
return InputField(view)
}
}
override fun onBindViewHolder(InputFieldHolder: InputField, i: Int) {
val question = listQuestion.get(i)
if(question.prodeskel_type_id == 2){
InputFieldHolder.questionText?.text = question.isi
var rprms = InputFieldHolder.radiogroup?.layoutParams
for (i in question.pilihan_jawabans) {
val rdbtn = RadioButton(context)
rdbtn.id = View.generateViewId()
rdbtn.text = i.isi.toString()
rprms = RadioGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
InputFieldHolder.radiogroup?.addView(rdbtn, rprms)
}
} else {
InputFieldHolder.txtInput?.hint = question.isi
if(question.getEditTextValue().toString() != "null"){
InputFieldHolder.txtInput?.editText?.setText(question.getEditTextValue().toString())
}
InputFieldHolder.txtInput?.editText?.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {
InputFieldHolder.txtInput?.editText?.text?.length?.let {
InputFieldHolder.txtInput?.editText?.setSelection(
it
)
}
}
override fun beforeTextChanged(s: CharSequence, start: Int,
count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int,
before: Int, count: Int) {
Log.i("Edit", InputFieldHolder.txtInput?.editText?.text.toString())
question.setEditTextValue(InputFieldHolder.txtInput?.editText?.text.toString())
}
})
}
InputFieldHolder.setIsRecyclable(false);
}
override fun getItemCount(): Int {
return listQuestion.size
}
public fun getItem(): ArrayList<Question> {
return listQuestion
}
inner class InputField internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
internal var txtInput: TextInputLayout? = null
internal var radiogroup: RadioGroup? = null
internal var questionText: TextView? = null
init {
txtInput = itemView.findViewById(R.id.txtInputField)
radiogroup = itemView.findViewById(R.id.radiogroup)
questionText = itemView.findViewById(R.id.questionText)
}
}
}
UPDATE (SOLVED)
i solved by add this function
override fun getItemViewType(position: Int) = listQuestion[position].prodeskel_type_id
and add selection condition on onCreateViewHolder
and onBindViewHolder
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): InputField {
if(viewType == 1){
//view type layout1
} else {
//view type layout2
}
}
override fun onBindViewHolder(InputFieldHolder: InputField, i: Int) {
if(getItemViewType(i) == 1){
//add text to layout1
} else {
//add text to layout2
}
}
Upvotes: 0
Views: 172
Reputation: 7380
As you have written in the code onCreateViewHolder receives an Int
and which is the type of view. based on that it creates viewholders
.
But in your case the view type will be always 0. onCreateViewHolder
receives viewType and which is returned by getItemViewType
which you need to override.
for example
@Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
return viewType;
}
also your onCreateViewHolder
and onBindViewHolder
should be depending on the viewType received as argument.
example
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): InputField {
if(viewType == 1){
...
}
}
override fun onBindViewHolder(InputFieldHolder: InputField, position: Int) {
if(getViewType(position) == 1){
...
}
}
In your scenario getViewType
will be something like this
override fun getItemViewType(position: Int) = listQuestion[position].prodeskel_type_id
Hope that helps. also I would ask you to understand how RecyclerView and its adapter works
Upvotes: 1
Reputation: 2446
To use multiple item types in RecyclerView
you need to override method getItemViewType
. The value it returns will be placed as 2-nd parameter in onCreateViewHolder
method (BTW, better to rename it from i
to viewType
). Default implementation of getItemViewType
always returns same value, so you would never get what you want with it.
Upvotes: 1