0

I have recycleview in fragment. When i click one of the items in recyclerview,ı want to open new fragment. I have to column in my adapter as you see picture:enter image description here I have created two fragment also.(fragment_opel and fragment chevrolet.)when user click chevrolet row, fragment_chevrolet have to open.I am new about android studio.I create onclick method in my adapter. But i cannot fill that function. :) Can you help me about it please?

My adapter:

package com.example.parcaburada



class AracMarkaAdapter(tumKategori: ArrayList<AracMarka>) :
    RecyclerView.Adapter<AracMarkaAdapter.AracMarkaViewHolder>() {


    var araclar = tumKategori

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AracMarkaViewHolder {

        var inflater = LayoutInflater.from(parent.context)
        var arackategori = inflater.inflate(R.layout.arac_kategori, parent, false)

        return AracMarkaViewHolder(arackategori)

    }

    override fun getItemCount(): Int {
        return araclar.size
    }

    override fun onBindViewHolder(holder: AracMarkaViewHolder, position: Int) {


        holder.aracismi.text = araclar.get(position).aracAdi
        holder.aracLogo.setImageResource(araclar.get(position).aracLogo)


    }


    class AracMarkaViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
        View.OnClickListener {
        override fun onClick(v: View?) {


        }


        var teksatirKategori = itemView
        var aracismi = teksatirKategori.tvaracAdi
        var aracLogo = teksatirKategori.img_arac_sembol
    }


}

My fragment:

package com.example.parcaburada.ui.kategori



class KategoriFragment : Fragment() {
    var araclarKategori = ArrayList<AracMarka>()


    private lateinit var galleryViewModel: GalleryViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        veriKaynaginiDoldur()
        galleryViewModel =
            ViewModelProviders.of(this).get(GalleryViewModel::class.java)
        var root = inflater.inflate(R.layout.fragment_category, container, false)

        var rvarackategori = root.findViewById(R.id.rvarackategori) as RecyclerView
        var MyAdapter = AracMarkaAdapter(araclarKategori)
        rvarackategori.adapter = MyAdapter

        var linearLayoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
        rvarackategori.layoutManager = linearLayoutManager

        return root
    }

    fun veriKaynaginiDoldur(): ArrayList<AracMarka> {

        var aracLogo = arrayOf(R.drawable.opellogo, R.drawable.chevroletlogo)
        var aracismi = resources.getStringArray(R.array.arabaisim)

        for (i in 0 until min(aracismi.size, aracLogo.size)) {

            var eklenecekaracKategori = AracMarka(aracismi[i], aracLogo[i])
            araclarKategori.add(eklenecekaracKategori)
        }
        return araclarKategori

    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

    }


}
akiilhan
  • 131
  • 2
  • 12
  • I don't see a click listener anywhere in your code. [Have you gone through this post?](https://stackoverflow.com/questions/24471109/recyclerview-onclick). It's all about setting a listener, then you can do whatever you want. – Taseer Sep 26 '19 at 14:45
  • you wants to do it in adpter or in activity ? – Danial clarc Sep 26 '19 at 14:47
  • @Danialclarc recyclerview is defined my fragment. So i have to define on adapter. – akiilhan Sep 26 '19 at 15:41
  • @TaseerAhmad i defined click listener on my adapter. You can see that. But it is empty. Because i dont now how to do that.Maybe i could be totaly wrong. – akiilhan Sep 26 '19 at 15:43

4 Answers4

1

First setup a click listener:

Set a click listener on the ViewHolder object.

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AracMarkaViewHolder {

    var inflater = LayoutInflater.from(parent.context)
    var arackategori = inflater.inflate(R.layout.arac_kategori, parent, false)

    return AracMarkaViewHolder(arackategori).also {
       arackategori.setOnClickListener { clickHandler.forwardClick(it) }
    }
}

We setup a listener, where we invoke the function forwardClick(holder: AracMarkaViewHolder). We pass the current inflated view holder reference to it so that we can do any future operations on it.

Now setup an interface:

We create an interface because we want any click event to be handeled by the activity. Those events, in your case include, launching a new fragment.

interface ClickEventHandler {
    fun forwardClick(holder: AracMarkaViewHolder)
}

Now in your adapter, setup the interface like this:

private val clickHandler: ClickEventHandler = context as ClickEventHandler 

Modify adapter class signature:

Now, we need to slightly modify adapter's constructor.

var MyAdapter = AracMarkaAdapter(araclarKategori, requireContext()) //We pass the activity's context. 

And your adapter class signature should look something like this:

 class AracMarkaAdapter(tumKategori: ArrayList<AracMarka>, context: Context) :
   RecyclerView.Adapter<AracMarkaAdapter.AracMarkaViewHolder>() {
        private val clickHandler: ClickEventHandler = context as ClickEventHandler 
  }   

Implement the interface:

Now we implement the interface in the activity.

class MainActivity : AppCompatActivity(), ClickEventHandler  {
  override fun forwardClick(holder: AracMarkaViewHolder) {
     //Launch a new fragment here.
  }
}
Taseer
  • 3,143
  • 3
  • 13
  • 31
  • Hello Taseer. THank you so much. I arrange my code accordind to your advise.But, for this code: val clickHandler: ClickEventHandler = context as ClickEventHandler, context cannot resolve. – akiilhan Sep 26 '19 at 16:22
  • You need to pass `context` to the adapter class. For example `class Adapter(context: Context)`. Then, `Adapter(this)`. – Taseer Sep 26 '19 at 16:29
  • Sorry for my questions, but ı cannot get it. – akiilhan Sep 26 '19 at 16:36
  • Check the edit, you just need to pass `context` as a parameter to the adapter class exactly the way you are passing a list to it. – Taseer Sep 26 '19 at 16:41
  • Hello Taseer, actually thank you so much for your helping. The problem is in class AracMarkaAdapter ,AracMarkaViewHolder is uresolve. – akiilhan Sep 27 '19 at 08:56
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/200056/discussion-between-taseer-ahmad-and-akiilhan). – Taseer Sep 27 '19 at 08:58
1

Just implement the "go to fragment" in your onBindViewHolder method like this-

override fun onBindViewHolder(holder: AracMarkaViewHolder, position: Int) {
    holder.aracismi.text = araclar.get(position).aracAdi
    holder.aracLogo.setImageResource(araclar.get(position).aracLogo)
    holder.setOnClickListener {
        if (position == 0) {
            TODO("Go to first fragment")
        } else {
            TODO("Go to second fragment")
        }
    }
}
Gulshan
  • 2,973
  • 5
  • 31
  • 44
  • Hello, thank you so much. now i can get positions. But now, to go to first fragment, i cannot call "supportFragmentManager". Do you now howw to do that? – akiilhan Sep 27 '19 at 18:55
  • 2
    Setting a listener in `onBindVIewHolder` is a bad practice as on scrolling, it keeps on setting click listeners on each view holder. Also, it's not a job of an adapter class to handle that logic. It should be propagated to the activity level and handled there. – Taseer Sep 27 '19 at 19:06
1

Just in case this helps anyone who's using Kotlin and Android Studio 4.

I'm using adapters on a RecycleView in a fragment. You can only do the override in the mainactivity.kt class not the adapter class as it's not on the main thread if you're going to show a new fragment view.

So my constructor in my adapter for my recyclerview is changed to:

class MyFollowRecyclerViewAdapter(
    private val values: List<FollowItem>,
    private val context: Context
)

Then I have a variable in my adapter class:

 private val clickHandler: ClickEventHandler = context as ClickEventHandler

Then I added the setOnClickListener in my adapter class to the onCreateViewHolder method:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(layout.fragment_item_follow, parent, false)
        view.setOnClickListener {
            clickHandler.viewFollow(it)
        }
        return ViewHolder(view)
    }

ClickEventHandler is defined in my adapter class as:

  interface ClickEventHandler {
        fun viewFollow(holder: View)
    }

Now for the ovverride of the function in mainactivity. I add ClickEventListener to my MainActivity class:

class MainActivity : AppCompatActivity(), ClickEventHandler {

Then I create my override function of the function defined in my adapter class in my mainactivity class:

 override fun viewFollow(holder: View) {
}
scarer
  • 91
  • 7
0

you need to implement an onClickListener interface for your adapter. after that you can set your recyclerview visibility gone and frameLayout Visible. now send which fragment that you want into frameLayout.

OR

implement adapter onClickListener in your main activity and show which fragment you want by selected recyclerview item index

Hosein Haqiqian
  • 218
  • 3
  • 11
  • Thank you for your helping. for second advise, my recyclerview is in my fragment. So my main activity is empty. Should i implement adapter onClickListener on my mainactiviy even so? or use in fragment? – akiilhan Sep 26 '19 at 16:02
  • Including some code will help the reader understand the solution properly. – Taseer Sep 26 '19 at 16:10
  • @akiilhan you want to change fragment that is already passed into frameLayout and that is already defined in mainActivity , right? in this case , you should implement adapter onClickListener into your mainActivity and replace second fragment with FragmentTransaction. – Hosein Haqiqian Sep 26 '19 at 16:42
  • @TaseerAhmad sorry. that's how i can help now. your answer did the most. – Hosein Haqiqian Sep 26 '19 at 16:43
  • @HoseinHaqiqian I created two row using recyclerview. But i created recyclerview in my fragment not in my mainactivity. my purpose is when i click row, different fragment should open. Actually ı now how to pass data fragment to fragment using button. But now there is no button and i am using recyclerview. I am so confused. – akiilhan Sep 26 '19 at 18:36
  • dear @akiilhan , interfaces can be passed through the fragment and then to the activity to manage different situation like this. – Hosein Haqiqian Sep 26 '19 at 20:10