I define mSelectedItem as a public var in the class CustomAdapter, I think mSelectedItem=getAdapterPosition() will be Ok when I use mSelectedItem in inner class ViewHolder.
But it failed, and display "Unresolved reference: mSelectedItem" error, why?
And more, what is good way for getAdapterPosition() in Kotlin, there is hint which display "This inspection reports calls to java get and set methods that can be replaced with use of Kotlin synthetic properties", but it will cause errro when I use mSelectedItem=getAdapterPosition .
class CustomAdapter (val backupItemList: List<MSetting>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
public var mSelectedItem = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.item_recyclerview, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(backupItemList[position])
holder.itemView.radioButton.setChecked(position == mSelectedItem);
}
override fun getItemCount(): Int {
return backupItemList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(aMSetting: MSetting) {
itemView.radioButton.tag=aMSetting._id
itemView.textViewUsername.text=aMSetting.createdDate.toString()
itemView.textViewAddress.text=aMSetting.description
mSelectedItem=getAdapterPosition() //It will cause error
}
}
}
If you don't want to make the ViewHolder an inner class (which you should not), you could create a class like AdapterSelection that has a field var selectedItem:Int inside it and replace your public var mSelectedItem = -1 with private var mSelectedItem = AdapterSelection(-1). Then pass the mSelectedItem to the bind method (bindItems(aMSetting: MSetting, adapterSelection:AdapterSelection) and inside the bind, set the position adapterSelection.selectedItem = getAdapterPosition().
You could have passed the adapter itself, but it is messy, that's why I suggest making another class.
ViewHolder is the Recycler rather than the operator.if you want to get the position,you put this mSelectedItem = position in onBindViewHolder.And this method named getAdapterPosition() always works on with notifyItemsetChanged().hope this will help you.
Related
I'm looking for a way to find the context of a RecyclerView Adapter outside of the viewholder methods. I have two different arrays that I would like to be able to display based on the activity/fragment that is being shown(the final app would have 4 arrays which is why I don't just want to make another adapter for each array). I can get it to work in the onbindviewholder using holder.itemview.context but since the arrays aren't the same size I need a way to use context for an if statement in getitemcount() as well. Passing context in the constructor results in "no value passed for parameter". Was wondering if anyone has found a solution to this problem using either fragments or activities. Worst case scenario I just make a different adapter for every array
class ItemAdapter(var context: Context) : RecyclerView.Adapter<ItemAdapter.ViewHolder>() {
private var weeklyTasks = arrayOf(R.string.app_name, R.string.daily_hint_1, R.string.daily_hint_2, R.string.daily_hint_3)
private var dailyTasks = arrayOf(R.string.daily_hint_1, R.string.daily_hint_2, R.string.daily_hint_3)
private var xp = intArrayOf(R.mipmap.tenxp_round, R.mipmap.fiftyxp_round, R.mipmap.hundredxp_round)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.task_layout, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
//cant use context here because no value is passed for parameter
return dailyTasks.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//var context = holder.itemView.context -> this works here but not as a constructor
if(context is ToDoList) {
holder.itemImage.setImageResource(xp[0])
holder.itemDetail.text = dailyTasks[position].toString()
}
else{
holder.itemImage.setImageResource(xp[1])
holder.itemDetail.text = weeklyTasks[position].toString()
}
}
inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
var itemImage: ImageView
var itemDetail: TextView
init {
itemImage = itemView.findViewById(R.id.item_image)
itemDetail = itemView.findViewById(R.id.item_detail)
}
}
}
I'm new in Android dev.
In my code i don't using onClick method, but i using setOnClickListener and Callback. The main problem that is in this way i don't know how to get the position of the item in RecyclerView.
Here is my Adapter:
class TestAdapter(val test : ArrayList<Test>, private val testAdapterCallback: (Test, Int)->Unit) : RecyclerView.Adapter<TestAdapter.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.test_view_item, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return test.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val num : Test = test[position]
holder.textView.text = num.id.toString()
holder.cardView.setTag(position)
holder.cardView.setOnClickListener(){
testAdapterCallback(num)
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val cardView = itemView.findViewById<CardView>(R.id.testCardView)
val textView = itemView.findViewById<TextView>(R.id.testTextView)
}
}
I have added second parametr into callback but i don't know how i must change my adapter's inicializations in this peace of code:
val adapter = TestAdapter(list) { item ->
testAdapterItemClick(item)
}
In activity i'm using this method :
private fun testAdapterItemClick(item: Test) {}
Please, help me to check the position of the choosen element. I need it later.
Thanks in advance)
P.S. Sorry for my English
Add the position as parameter in the callback.
So, instead of: private val testAdapterCallback: (Test)->Unit
Use: private val testAdapterCallback: (Test, Int)->Unit.
This way you can pass the position in the callback.
holder.cardView.setOnClickListener(){
testAdapterCallback(num, position)
}
In your activity:
val adapter = TestAdapter(list) { item, position ->
testAdapterItemClick(item)
}
Create interface for your OnClickListener
interface OnClickListener{
fun clickItem(test: Test, index: Int)
}
Pass listener to your adapter like below.
class TestAdapter(
var test : ArrayList<Test>?,
val clickListener: OnClickListener,
var mActivity: Activity
) :
RecyclerView.Adapter<TestAdapter.MyViewHolder>() {
}
Now in your onBindViewHolder add click listener.
var mtest= test !!.get(i)
holder.cardView.setOnClickListener {
clickListener.clickItem(mtest, i)
}
Implement Listener to your activity and initialize it.
this.mOnClickListener = this
Pass listener to your adapter where you passing the arraylist.
mTestAdapter = TestAdapter(arrayList, mOnClickListener ,mActivity)
You'll get the position in your activity override method.
override fun editItem(mTest: Test, index: Int) {
if (mTest!= null) {
}
}
I am trying to pass an array from my Recyclerview Activity to its Adapter as such:
//Setting NavBar Title
val navBarTitle = intent.getStringExtra(FirstCustomViewHolder.LESSON_TITLE_KEY)
supportActionBar?.title = navBarTitle
var content : Array<String>
if (navBarTitle == "Introduction"){
content = arrayOf("Intro1", "Intro2")
}
else{
content = arrayOf(":esson1-1", "Lesson 1-2")
}
I am passing the array as such:
recyclerView_main.adapter = SecondAdapter(content)
And I am getting an angry red underline as shown below.
On mouse-over the pop-up error reads:
Too many arguments for public constructor......
Is there a proper way to pass an array or variable to my adapter? I am fairly new to Kotlin and appreciate and pointers.
Thank you.
Edit:
As requested, this is my adapter class:
class SecondAdapter : RecyclerView.Adapter<SecondCustomViewGolder>(){
//Variable below to be replaced by array from Activity
var lessons = arrayOf("Satu", "Dua", "Tiga", "Empat", "Lima", "Enam", "Tujuh",
"Lapan", "Sembilan")
override fun getItemCount(): Int {
return lessons.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SecondCustomViewGolder {
var layoutInflater = LayoutInflater.from(parent.context)
var cellForRow = layoutInflater.inflate(R.layout.lesson_row, parent, false)
return SecondCustomViewGolder(cellForRow)
}
override fun onBindViewHolder(holder: SecondCustomViewGolder, position: Int) {
}
}
class SecondCustomViewGolder(var viewTwo : View) : RecyclerView.ViewHolder(viewTwo){
}
Does your SecondAdapter class constructor accept an Array as an argument? If not, you must add it there. The error is because you're trying to pass an argument to a constructor that accepts no arguments.
EDIT
Do it like so:
class SecondAdapter(val lessonArray: Array<String>) : RecyclerView.Adapter<SecondCustomViewGolder>(){
override fun getItemCount(): Int {
return lessons.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SecondCustomViewGolder {
var layoutInflater = LayoutInflater.from(parent.context)
var cellForRow = layoutInflater.inflate(R.layout.lesson_row, parent, false)
return SecondCustomViewGolder(cellForRow)
}
override fun onBindViewHolder(holder: SecondCustomViewGolder, position: Int) {
}
}
class SecondCustomViewGolder(var viewTwo : View) : RecyclerView.ViewHolder(viewTwo){
}
I made it a val since it's my preference. If you intend to modify the variable, than you just declare it as a var in the constructor. There's no need to assign it inside the class. Just declaring it in the constructor makes it accessible throughout the class.
You can use the ListAdapter
and use submitList()
I'm trying to set some values to some dialog properties based on list item position and have just converted some code from Java to Kotlin, but for some reason, all the myList[position] instances within the click listener return this error:
'getter for position: Int' is deprecated. Deprecated in Java.
However for onBindViewHolder What alternative can be used to resolve this error?
class MyRVAdapter(private val myList: ArrayList<Item>) : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {
override fun getItemCount(): Int {
return myList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.myBtn.text = (myList[position].textBtnTitle)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.my_cv, parent, false)
return ViewHolder(v)
}
class ViewHolder (itemView : View):RecyclerView.ViewHolder(itemView) {
val myBtn = itemView.findViewById<Button>(R.id.btn_a)!!
init {
myBtn.setOnClickListener {
val builder = AlertDialog.Builder(myBtn.context)
builder.setTitle(myList[position].txtDialogTitle)
builder.setMessage(myList[position].txtDialogMessage)
builder.setPositiveButton(android.R.string.ok){ dialog, _ -> dialog.dismiss() }
val dialog: AlertDialog = builder.create()
dialog.show()
}
}
}
}
This method is deprecated. This method is confusing when adapters nest other adapters. If you are calling this in the context of an Adapter, you probably want to call getBindingAdapterPosition() or if you want the position as RecyclerView sees it, you should call getAbsoluteAdapterPosition().
[Source:https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.ViewHolder#getAdapterPosition()]
I'm assuming you're talking about the references to position inside your ViewHolder class.
Use adapterPosition there instead. The Java equivalent is getAdapterPosition(). If you were using getPosition() in Java, you may have had the deprecation warning suppressed.
itemSelectedForPreview(layoutPosition)
OR
itemSelectedForPreview(bindingAdapterPosition)
I'm trying to create an android wear app with a list of items. To enable circular scrolling, I'm using WearableRecyclerView by coding in kotlin. But facing this error Unresolved reference: Adapter The same code in java doesn't throw this error! I've also referred the inner and outer classes concepts in kotlin. Adapter class is an abstract class of RecyclerView which in turn is extended by WearableRecyclerView. Any guidance will be of much use, Thankyou!!
Here is my code
class CustomRecyclerAdapter(context: Context,dataSet: Array<String>): WearableRecyclerView.Adapter<CustomRecyclerAdapter.viewHolder>() {
var mDataSet: Array<String>
var mcontext: Context
init {
mDataSet = dataSet
mcontext=context
}
inner class viewHolder(view: View) : WearableRecyclerView(mcontext) {
val mTextView: TextView
init {
mTextView = view.findViewById(R.id.textView)
}
override fun toString(): String {
return mTextView.text as String
}
}
fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): viewHolder {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.recycler_row_item, viewGroup, false)
return viewHolder(view)
}
fun onBindViewHolder(viewHolder: viewHolder, position: Int) {
// Replaces content of view with correct element from data set
viewHolder.mTextView.text = mDataSet[position]
}
// Return the size of your dataset (invoked by the layout manager)
fun getItemCount(): Int {
return mDataSet.size
}
}
Rather than using a (apparently non existent) WearableRecyclerView.Adapter consider using the non-wearable adapter: RecyclerView.Adapter
Your class inner class viewHolder(view: View) : WearableRecyclerView(mcontext) must extends WearableRecyclerView.ViewHolder instead of WearableRecyclerView like :
inner class viewHolder(view: View) : WearableRecyclerView.ViewHolder(view)