I have recyclerView and after click of card I would like to replace fragments in activity. The problem is I have no access to activity. Here is my code in adapter:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val itemsViewModel = mList[position]
holder.tagImage.setImageResource(itemsViewModel.tagImage)
holder.tagName.text = itemsViewModel.tagName
holder.tagDescription.text = itemsViewModel.tagDescription
holder.itemView.setOnClickListener {
Log.d(InTorry.TAG, itemsViewModel.tagName)
val fragment = ProductsFragment()
val transaction = activity?.supportFragmentManager?.beginTransaction()
transaction?.replace(R.id.homeFragmentsContainer, fragment)
//transaction?.disallowAddToBackStack()
transaction?.commit()
}
}
The above replace code works in fragment but in adapter there is "activity?" error.
Kind Regards
Jack
There are multiple ways to solve this problem.
Using Context
You can use the context from holder.itemView and cast it into an Activity.
This is probably the simplest way, however this can be problematic since a Context may represent an Activity, a Service, an Application, etc. in which case it may lead to a ClassCastException when used simply.
Using Callback
You can set up a callback from your Adapter to your Activity or Fragment and then replace your Fragment.
Use JetPack Navigation
This is my personal favorite as the latest versions allow you to access NavController from Activity, Fragment or any View in the hierarchy to navigate. This is just one of many benefits of using this library.
Here is a link to Jetpack Navigation.
The Simplest and Safer way to solve this is my using Callback from your holder to activity. Below is the step by step process :
Decalare an Interface
interface OnItemClick {
fun onClick()
}
Implement that interface in you Activity and put the desired code
class MainActivity : OnItemClick {
...
override onClick() {
// Do whatever you want
val fragment = ProductsFragment()
val transaction = fragmentManager.beginTransaction()
transaction.replace(R.id.homeFragmentsContainer, fragment)
transaction.commit()
}
}
Create a variable of that Interface type in you Adapter and in your onBindViewHolder method invoke that interface
class MyAdapter(val listener : OnItemClick) {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
...
listener.onClick()
}
Finally pass that interface to your Adapter from you Activity
class MainActivity : OnItemClick {
val adapter = MyAdapter(this)
...
}
NOTE : Please don't pass activity to context here and there you will get unexpected result and most probably a crash.
After watching this video https://www.youtube.com/watch?v=WqrpcWXBz14
I managed to do it this way
In Adapter
class TagsAdapter(var mList: List<TagsViewModel>) :
RecyclerView.Adapter<TagsAdapter.ViewHolder>() {
var onItemClick: ((TagsViewModel) -> Unit)? = null//click listener STEP 1!!!
override fun onBindViewHolder(holder: TagsAdapter.ViewHolder, position: Int) {
holder.itemView.setOnClickListener {
onItemClick?.invoke(itemsViewModel)//click listener STEP 2!!!
}
}
}
And in Fragment
class TagsFragment : Fragment() {
private lateinit var tagsRecyclerView: RecyclerView
private var tagsArray = ArrayList<TagsViewModel>()
private lateinit var adapter: TagsAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = TagsAdapter(tagsArray)
tagsRecyclerView.adapter = adapter
adapter.onItemClick = {//click listener STEP 3!!!
val fragment = ProductsFragment()
val transaction = activity?.supportFragmentManager?.beginTransaction()
transaction?.replace(R.id.homeFragmentsContainer, fragment)
//transaction?.disallowAddToBackStack()
transaction?.commit()
}
}
}
It looks very clean and easy. I don't know is a correct way but it works
Related
Hello i have a recyclerview that is filled with some data coming from a Webservice, using Retrofit.
Now I want to implement a onClickListener, so when i click each row of the Recycler View, i can see more data from that object, and tried to work with some examples, but i got stucked
Here is my adapter. I know that in the onCreateViewHolder, i should put in the Return AnunciosViewHolder a second parameter, of the type cellClickListener, but i have no idea what i have to put. I tried this#CellCLickListener and this#cellCLickListener and it gave me error that is is unresolved
class AnuncioAdapter(val anuncios: List<Anuncio>): RecyclerView.Adapter<AnunciosViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AnunciosViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recyclerline, parent, false)
return AnunciosViewHolder(view)
}
override fun getItemCount(): Int {
return anuncios.size
}
override fun onBindViewHolder(holder: AnunciosViewHolder, position: Int) {
return holder.bind(anuncios[position])
}
}
class AnunciosViewHolder(itemView : View, private val cellClickListener: CellClickListener): RecyclerView.ViewHolder(itemView){
private val morada: TextView = itemView.findViewById(R.id.morada)
private val telemovel: TextView = itemView.findViewById(R.id.number)
private val fotografia: ImageView = itemView.findViewById(R.id.image)
fun bind(anuncio: Anuncio) {
morada.text = anuncio.morada
telemovel.text = anuncio.telemovel
itemView.setOnClickListener {
cellClickListener.onCellClickListener(anuncio)
}
I also tried creating an interface
interface CellClickListener {
fun onCellClickListener (data: Anuncio)
}
and in my Activity i put this method and it gives me an error that «overrides nothing»
override fun onCellClickListener(data: Anuncio) {
val intent = Intent(this#ListaAnuncios, DetalhesActivity::class.java)
intent.putExtra(PARAM_ID, data.id.toString())
intent.putExtra(PARAM_MORADA, data.morada)
intent.putExtra(PARAM_TELEMOVEL, data.telemovel)
startActivityForResult(intent, newAnuncioActivityRequestCode1)
Log.e("***ID", data.id.toString())
}
UPDATE
After using the suggestions made by Praveen i was able to clean my Adapter from errors, however i am struggling in the activity part
if it put
val anuncioAdapter = AnuncioAdapter(anuncios, this)
on the beggining of my On Create, it doesn't recognize «anuncios»
However i am declaring my adapter inside the call.enqueue
recyclerView.apply {
setHasFixedSize(true)
layoutManager =
LinearLayoutManager(this#ListaAnuncios)
adapter = AnuncioAdapter(response.body()!!)
}
And it is asking to pass an instance of cellClickListener here, but if i use «this» in here, it is stated that i am trying to pass an instance of the recycler view instead of the CellClickListener
NEW UPDATE
Forgot to put all the call.enqueue method
call.enqueue(object : Callback<List<Anuncio>> {
override fun onResponse(call: Call<List<Anuncio>>, response: Response<List<Anuncio>>) {
if (response.isSuccessful){
recyclerView.apply {
setHasFixedSize(true)
layoutManager =
LinearLayoutManager(this#ListaAnuncios)
adapter = AnuncioAdapter(response.body()!!)
}
}
}
override fun onFailure(call: Call<List<Anuncio>>, t: Throwable) {
Toast.makeText(this#ListaAnuncios, "${t.message}", Toast.LENGTH_LONG).show()
}
}) }
i tried both approaches of #Praveen and #aligur, but still struggling with asking me to put the instance of Clicklistener as the 2nd parameter, but using «this» is putting the instance of the Recycler View and not of the ClickListener
Thank You in advance
and in my Activity i put this method and it gives me an error that
«overrides nothing»
You are not implementing CellClickListener in your activity. Add CellClickListener after your activity's class name declaration
class MainActivity : AppCompatActivity(), CellClickListener {
}
I know that in the onCreateViewHolder, i should put in the Return
AnunciosViewHolder a second parameter, of the type cellClickListener,
but i have no idea what i have to put. I tried this#CellCLickListener
and this#cellCLickListener and it gave me error that is is unresolved
You've to add the private val cellClickListener: CellClickListener parameter to the constructor of AnuncioAdapter, not the ViewHolder. Only then you will be able to pass it from your activity.
Change constructor of AnuncioAdapter to accept a CellClickListener and remove the same from the constructor of AnunciosViewHolder
class AnuncioAdapter(
private val anuncios: List<Anuncio>,
private val cellClickListener: CellClickListener
): RecyclerView.Adapter<AnunciosViewHolder>() {
}
To access this cellClickListener inside AnunciosViewHolder you've to make it an inner class of AnuncioAdapter, which you can make, as it's already tightly coupled with the adapter.
inner class AnunciosViewHolder(itemView : View): RecyclerView.ViewHolder(itemView){
}
Now, on creating an object of AnuncioAdapter inside activity, just pass an instance of cellClickListener using this, as it's already implementing it.
val anuncioAdapter = AnuncioAdapter(anuncios, this)
I think the easiest way is passing function as parameter to RecyclerViewAdapter.
for instance:
RecyclerViewAdapter(val clickListener : () -> Unit)
onCreateViewHolder(){
clickListener.invoke()
}
in your view
adapter = ReceylerViewAdapter({
//do your stuff here
})
Was finally able to find a solution. By Using #Praveen suggestion, and by finding this example https://github.com/velmurugan-murugesan/Android-Example/tree/master/RetrofitWithRecyclerviewKotlin/app/src/main/java/app/com/retrofitwithrecyclerviewkotlin
On the activity i added a new val, before the OnCreate method
lateinit var anuncioAdapter: AnuncioAdapter
Added this on the onCreate (so i could use the first sugestion)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
anuncioAdapter = AnuncioAdapter(this,this)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = anuncioAdapter
And changed the recyclerview.apply {} on the call.enqeue just to
anuncioAdapter.Anuncios(response.body()!!);
And finally created the Anuncios Method on the Adapter
fun Anuncios(anuncio: List<Anuncio>){
this.anuncios = anuncio;
notifyDataSetChanged()
}
With this it works like how i wanted id. Thanks for the help
i need to create a fragment from activty-adapter on imagebutton click and to pass 3 data along
having trouble with fragment or it says
android.app.Application cannot be cast to android.app.Activity
please help someone
code is in the image
code i tried
Simple way to do it (although you should probably communicate through a viewModel, that is beyond scope of this question):
First take in a listener into the adapter
class FakeAdapter(private val items: List<String>, private val startFragmentCallback: () -> Unit) :
RecyclerView.Adapter<FakeViewHolder>() {
Then, in the onBindViewHolder:
override fun onBindViewHolder(holder: FakeViewHolder, position: Int) {
holder.itemView.setOnClickListener { // in your case this might be holder.commenting - but i don't know what 'commenting' is
startFragmentCallback.invoke()
}
}
Then in the Activity have a private function to create the fragment:
private fun startFragmentCallback() {
// code to start fragment goes here
}
And then use that function when creating your adapter in the activity:
val listOfStrings = listOf("1", "2", "3")
val adapter = FakeAdapter(listOfStrings, this::startFragmentCallback)
I have a RecyclerView which was build using an Arraylist. That Arraylist consists of User defined objects named ListItem.
Each recyclerview has a card view. Each CardView holds each ListItem.
I have removed one CardView from that RecyclerView.
When I rotate the screen , A new Activity is created which results in showing the old data. But I want the recyclerview to hold only updated list and should retain the scrolled position.
ListItem class :
class ListItem(var title: String, var info: String, val imageResource: Int) {
}
MainActivity class :
class MainActivity : AppCompatActivity() {
private lateinit var mSportsData: ArrayList<ListItem>
private lateinit var mAdapter: MyAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val gridColumnCount = resources.getInteger(R.integer.grid_column_count)
recycler_view.layoutManager = GridLayoutManager(this,gridColumnCount)
mSportsData = ArrayList()
recycler_view.setHasFixedSize(true)
initializeData()
recycler_view.adapter = mAdapter
var swipeDirs = 0
if (gridColumnCount <= 1) {
swipeDirs = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
}
val helper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN,swipeDirs) {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
val from = viewHolder.adapterPosition
val to = target.adapterPosition
Collections.swap(mSportsData,from,to)
mAdapter.notifyItemMoved(from,to)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
mSportsData.removeAt(viewHolder.adapterPosition)
mAdapter.notifyItemRemoved(viewHolder.adapterPosition)
}
})
helper.attachToRecyclerView(recycler_view)
}
private fun initializeData() {
val sportsList : Array<String> = resources.getStringArray(R.array.sports_titles)
Log.d("Printing","$sportsList")
val sportsInfo : Array<String> = resources.getStringArray(R.array.sports_info)
val sportsImageResources : TypedArray = resources.obtainTypedArray(R.array.sports_images)
mSportsData.clear()
for (i in sportsList.indices-1) {
Log.d("Printing","${sportsList[i]},${sportsInfo[i]},${sportsImageResources.getResourceId(i,0)}")
mSportsData.add(ListItem(sportsList[i], sportsInfo[i], sportsImageResources.getResourceId(i, 0)))
}
sportsImageResources.recycle()
mAdapter = MyAdapter(mSportsData,this)
mAdapter.notifyDataSetChanged()
}
fun resetSports(view: View) {
initializeData()
}
}
MyAdapter class :
class MyAdapter(var mSportsData: ArrayList<ListItem>, var context: Context) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.wordlist_item,parent,false))
}
override fun getItemCount() = mSportsData.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val listItem = mSportsData.get(position)
holder.bindTo(listItem)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
itemView.setOnClickListener(this)
}
override fun onClick(view: View) {
val currentSport = mSportsData.get(adapterPosition)
val detailIntent = Intent(context, DetailActivity::class.java)
detailIntent.putExtra("title", currentSport.title)
detailIntent.putExtra("image_resource", currentSport.imageResource)
context.startActivity(detailIntent)
}
fun bindTo(currentSport : ListItem){
itemView.heading_textview.setText(currentSport.title)
itemView.description_textview.setText(currentSport.info)
Glide.with(context).load(currentSport.imageResource).into(itemView.image_view)
}
}
}
You can restrict activity restarting in your Manifest if you have same layout for Portrait and Landscape mode.
Add this to your activity in the manifest.
<activity android:name=".activity.YourActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize"/>
If you don't want to restrict screen orientation changes, then you can use OnSaveInstanceState method to save your older data when orientation changed. Whatever data you save via this method you will receive it in your OnCreate Method in bundle. Here is the helping link. So here as you have ArrayList of your own class type you also need to use Serializable or Parcelable to put your ArrayList in your Bundle.
Except these making ArrayList as public static is always a solution, But its not a good solution in Object Oriented paratime. It can also give you NullPointerException or loss of data, in case of low memory conditions.
It looks like initializeData is called twice since onCreate is called again on orientation change, you could use some boolean to check if data has been already initialized then skip initializing
What you are doing is you are deleting the values that are passed down to the recyclerview but when the orientation changes the recyclerview reloads from activity and the original data from activity is passed down again and nothing changes, so if you want to save the changes in recyclerview you have to change the original data in the activity so that if the view reloads the data is the same.
I think u initialize adapter in oncreate method in which the whole adapter will be recreated and all datas is also newly created when configuration changes. Because u init data in oncreate method. Try something globally maintain the list and also delete the item in the list in activity when u delete in adapter also. Or try something like view model architecture
Use MVVM pattern in the project. It will manage the orientation state.
MVVM RecyclerView example:
https://medium.com/#Varnit/android-data-binding-with-recycler-views-and-mvvm-a-clean-coding-approach-c5eaf3cf3d72
I was told that it is better to start another activity from the main activity instead of starting it from the adapter and that I should use an InteractionListener to communicate with the adapter and call the intent from the main activity.
Problem is I didn't understand how to implement an InteractionListener.
I tried this https://developer.android.com/training/basics/fragments/communicating but I don't know how to initialize the callback.
I tried to do this as I was told but I'm beginner and didnt understand this tutorial, got some errors I couldnt solve.
interface OnAdapterInteractionListener {
fun itemSelected(/Some Parameters Maybe/)
}
class ItemRecyclerViewAdapter(
private val mListener: OnFragmentInteractionListener?
) : {
// set on click listener from item to OnAdapterInteractionListener.itemSelected(/* Maybe Item Argument/)
class MainActivity: Activity(), OnFragmentInteractionListener {
override fun itemSelected(/ Some Parameters*/ ) {
startAct....
}
}
I just want to call an activity by clicking on some items of my recycler view.
I really appreciate any help or suggestions you can provide.
Assume that you have a list of names(Strings) and you want to show them as a list. When one of these names is clicked you should show show clicked item(name) within another activity. You can implement it as following.
Your activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerView"
tools:context=".MainActivity">
</androidx.recyclerview.widget.RecyclerView>
Adapter ItemRecyclerViewAdapter, subclass of RecyclerView.Adpater, which requires list of Strings as a constructor argument and which is able to accept OnAdapterInteractionListener(Edit: Placed inside the adpater) to interact with activity or fragment:
class ItemRecyclerViewAdapter(private val names: List<String>)
: RecyclerView.Adapter<ItemRecyclerViewAdapter.MyViewHolder>() {
private var nameClickListener: OnAdapterInteractionListener? = null
fun setOnAdapterInteractionListener(listener: OnAdapterInteractionListener) {
nameClickListener = listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_name, parent, false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return names.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.tvName.text = names[position]
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvName: TextView = itemView.findViewById(R.id.tvName)
init {
itemView.setOnClickListener {
nameClickListener?.itemSelected(names[adapterPosition], adapterPosition)
}
}
}
interface OnAdapterInteractionListener {
fun itemSelected(name: String, position: Int)
}
}
And MainActivity class:
class MainActivity : AppCompatActivity() {
private lateinit var mAdapter: ItemRecyclerViewAdapter
private val names: ArrayList<String> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.layoutManager = LinearLayoutManager(this)
initNames()
mAdapter = ItemRecyclerViewAdapter(names)
mAdapter.setOnAdapterInteractionListener(object : ItemRecyclerViewAdapter.OnAdapterInteractionListener {
override fun itemSelected(name: String, position: Int) {
Intent(this#MainActivity, DetailActivity::class.java).also {
it.putExtra("name", name)
startActivity(it)
}
}
})
recyclerView.adapter = mAdapter
}
private fun initNames() {
names.add("Name1")
names.add("Name2")
names.add("Name3")
}
}
Next you should implement DetailActivity which handles StringExtra as shown bellow and sets it to TextView:
intent?.getStringExtra("name").also {
detailText.text = it
}
Here detailText is a TextView.
You need to handle item click of an adapter. Refer to detailed answer here Passing data from one activity to interactor of another activity
Especially TaskItemListener usage in the sample.
It is pretty simple and straight forward. You have to create an interface to act as the listener and have to implement it in your activity. Then you should pass that implementation / reference to the adapter for accessing the interface method from adapter.
Sorry that it is in java. But you can follow the same method
Create and interface. You can create it inside the adapter / as a separate class (I am creating it inside my adapter)
public interface AdapterCallback{
void onAdapterSelected(int pos);
}
And inside the activity.
MyAdapter.AdapterCallback callback = new MyAdapter.AdapterCallback() {
#Override
public void onAdapterSelected(int pos) {
Intent intent = new Intent(getApplicationContext(),
SecondActivity.class);
startActivityForResult(intent, 100);
}
};
Then pass this implementation to the adapter while creating it.
MyAdapter adapter = new MyAdapter(dataList, callback); //dataList is list variable name
You have to make changes in adapter constructor as well.
public MyAdapter(ArrayList<Student> data, AdapterCallback callback) {
this.callback = callback;
this.myList = data;
}
Then inside onBindViewHolder, replace the start activity code with callback.onAdapterSelected
viewHolder.mBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callback.onAdapterSelected(i);
}
});
None of the answers helped. I think they all have some java so that they dont work.
That said i solved the problem by :
in the adapter declaration
var ctx: Context? = null
```kotlin
in the listener inside adapter
```kotlin
(ctx as MainActivity).openProject()
```kotlin
in the listener inside adapter
```kotlin
fun openProject() {
val intent = Intent(this, ProjectActivity::class.java)
this.startActivity(intent)
}
```kotlin
Well that solved my problem for now. If you know if doing an InterationListener insted is optimal or something please coment, thx.
I would like to call the Support Fragment Manager in my RecyclerView.Adapter after the click event in order to move to a different fragment. My approach:
(context as MainActivity).supportFragmentManager
.beginTransaction()
.replace(MainActivity.FRAGMENT_CONTAINER, TextScreen())
.commit()
But I get the following error:
kotlin.TypeCastException: null cannot be cast to non-null type
Can you help me?
Updated for 2021 - Kotlin Answer
If you want to call "supportFragmentManager" in Fragment
activity.supportFragmentManager
This is because your Context instance in the adapter is not guaranteed to be an Activity. It could potentially be a ContextWrapper holding the Activity as a base Context. Attempting to unwrap this would be fragile.
Instead, I would recommend that you define an interface in your adapter. From your Activity, provide an implementation of this interface to your adapter that will perform the FragmentTransaction. For example:
class MyAdapter : RecyclerView.Adapter<MyType> {
private var listener: (() -> Unit)? = null
fun setListener(listener: (() -> Unit)?) {
this.listener = listener
}
// wherever your onClick is handled:
listener?.invoke()
}
Then, in the Activity that's initializing MyAdapter:
myAdapter.setListener {
supportFragmentManager
.beginTransaction()
.replace(MainActivity.FRAGMENT_CONTAINER, TextScreen())
.commit()
}
I suggest you handle your fragment transaction in your fragment/activity. This would help you to have cleaner code and using context in fragment/activity is much easier. Try to define the interface between your adapter and fragment and call your interface method in the adapter and implement the interface in activity/fragment. There you can access context easily.
get the activity or fragment as argument in your adapter.
class ArticleAdapter(private val articleActivity: ArticleActivity, private val docs: List<ArticleResult.ArticleDoc>) : RecyclerView.Adapter<ArticleAdapter.Holder>() {
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): Holder = Holder(LayoutInflater.from(p0.context).inflate(R.layout.row_general2, p0, false))
override fun getItemCount(): Int = docs.size
override fun onBindViewHolder(holder: Holder, position: Int) {
articleActivity.supportFragmentManager
}
class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textViewTitleRow = itemView.findViewById<TextView>(R.id.textViewTitleRow)!!
val textView1Row = itemView.findViewById<TextView>(R.id.textView1Row)!!
val textView2Row = itemView.findViewById<TextView>(R.id.textView2Row)!!
val imageViewDownloadRow = itemView.findViewById<ImageView>(R.id.imageViewDownloadRow)!!
val textViewMoreRow = itemView.findViewById<TextView>(R.id.textViewMoreRow)!!
val imageViewBookRow = itemView.findViewById<ImageView>(R.id.imageViewBookRow)!!
}
}