I have been trying to call a function from fragment to adapter, but I can't approach it right. I want to invisible the button present in the fragment from adapter.
**My Adapter Code:**
package com.littleboo.brandlogo.Adapters
import android.R
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat.getSystemService
import androidx.recyclerview.widget.RecyclerView
import com.littleboo.brandlogo.Fragments.QuizFragment
import com.littleboo.brandlogo.MainActivity
import com.littleboo.brandlogo.Models.Question
import com.littleboo.brandlogo.databinding.ActivityMainBinding.inflate
import com.littleboo.brandlogo.databinding.FragmentQuizBinding
import kotlinx.coroutines.NonDisposableHandle.parent
class QuestionAdap(val context: Context, val question: Question) :
RecyclerView.Adapter<QuestionAdap.OptionViewHolder>() {
var index = 1
var score = 0
val animShake: Animation = AnimationUtils.loadAnimation(context, com.littleboo.brandlogo.R.anim.shake)
private var options: List<String> = listOf(question.option1, question.option2, question.option3, question.option4)
inner class OptionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
var optionView = itemView.findViewById<TextView>(com.littleboo.brandlogo.R.id.quiz_option)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder {
val view = LayoutInflater.from(context).inflate(com.littleboo.brandlogo.R.layout.quizoptions, parent, false)
return OptionViewHolder(view)
}
override fun onBindViewHolder(holder: OptionViewHolder, position: Int) {
holder.optionView.text = options[position]
holder.itemView.setOnClickListener {
question.userAnswer = options[position]
notifyDataSetChanged()
}
if(question.userAnswer == options[position] && question.userAnswer == question.answer){
holder.itemView.setBackgroundResource(com.littleboo.brandlogo.R.drawable.option_item_selected_bg)
score = 10
Toast.makeText(context,"Score is $score", Toast.LENGTH_SHORT).show()
}
else if(question.userAnswer == options[position] && question.userAnswer != question.answer){
holder.itemView.setBackgroundResource(com.littleboo.brandlogo.R.drawable.wrong_option_item_selected_bg)
holder.itemView.startAnimation(animShake)
}
else{
holder.itemView.setBackgroundResource(com.littleboo.brandlogo.R.drawable.non_option_item_selected_bg)
}
}
override fun getItemCount(): Int {
return options.size
}
}
My Quiz Fragment Code:
package com.littleboo.brandlogo.Fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import com.bumptech.glide.Glide
import com.google.firebase.firestore.FirebaseFirestore
import com.littleboo.brandlogo.Adapters.QuestionAdap
import com.littleboo.brandlogo.Models.Question
import com.littleboo.brandlogo.Models.quizmodel
import com.littleboo.brandlogo.R
import com.littleboo.brandlogo.databinding.FragmentQuizBinding
class QuizFragment : Fragment(){
lateinit var binding: FragmentQuizBinding
var quizzes: MutableList<quizmodel>? = null
private var questions = mutableMapOf<String, Question>()
private lateinit var mArraylist: ArrayList<Question>
var index = 1
private lateinit var mfirestore: FirebaseFirestore
private lateinit var mrecycler: RecyclerView
lateinit var myadapter: QuestionAdap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentQuizBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mrecycler = binding.optionList
mrecycler.layoutManager
myadapter = QuestionAdap(requireContext(),Question())
mArraylist = arrayListOf()
questions.map { it.key to it.value }.shuffled().toMap()
setUpFirestore()
setUpEventListener()
}
override fun onDestroy() {
super.onDestroy()
mfirestore.terminate()
// finish()
}
private fun setUpEventListener() {
binding.nextbtn.setOnClickListener {
index
bindViews()
}
// binding.btnSubmit.setOnClickListener {
// Log.d("FINALQUIZ", questions.toString())
// val intent = Intent(this, ResultActivity::class.java)
// val json = Gson().toJson(quizzes!![0])
// intent.putExtra("QUIZ", json)
// startActivity(intent)
// finish()
// }
}
private fun setUpFirestore() {
mfirestore = FirebaseFirestore.getInstance()
val quizTitle = activity?.intent?.getStringExtra("title")
if (quizTitle != null) {
mfirestore.collection("Quizes").whereEqualTo("title", quizTitle)
.get()
.addOnSuccessListener {
if (it != null && !it.isEmpty) {
quizzes = it.toObjects(quizmodel::class.java)
questions = quizzes!![0].questions
shuffle()
bindViews()
}
}
}
}
private fun bindViews() {
// btnPrevious.visibility = View.GONE
// binding.btnSubmit.visibility = View.GONE
// binding.btnNext.visibility = View.GONE
// if (index == 1) { //first question
// binding.btnNext.visibility = View.VISIBLE
// } else if (index == questions!!.size) { // last question
// binding.btnSubmit.visibility = View.VISIBLE
//// btnPrevious.visibility = View.VISIBLE
// } else { // Middle
//// btnPrevious.visibility = View.VISIBLE
// binding.btnNext.visibility = View.VISIBLE
// }
val circularProgressDrawable = CircularProgressDrawable(requireContext())
circularProgressDrawable.strokeWidth = 8f
// circularProgressDrawable.colorFilter = ("#ac5fe1")
circularProgressDrawable.centerRadius = 30f
circularProgressDrawable.start()
val question = questions!!["question$index"]
question?.let {
Glide.with(this).load(it.imagequiz).placeholder(circularProgressDrawable).into(binding.imagequiz)
val optionAdapter = QuestionAdap(requireContext(), it)
mrecycler.layoutManager = LinearLayoutManager(requireContext())
mrecycler.adapter = optionAdapter
mrecycler.setHasFixedSize(true)
}
}
private fun shuffle() {
val keys = questions.keys.toMutableList().shuffled()
val values = questions.values.toMutableList().shuffled()
keys.forEachIndexed { index, key ->
questions[key] = values[index]
}
}
}
I tried calling fragment in adapter like: QuizFragment().binding.btnxt.visibility = View.Visible
in BindViewHolder function.
Thank You
CodePudding user response:
You can use kotlin lambda function to achieve it. Like this
class QuestionAdap(val context: Context, val question: Question, var onItemClicked: ((boolean) -> Unit))
call onItemClicked in your adapter where you want it and in fragment
myadapter = QuestionAdap(requireContext(),Question()) { boolean ->
if (boolean) {
// hide/show
} else {
//hide/show
}
}
CodePudding user response:
You can use the Callback functions of kotlin in your fragment, which will be passed into your adapter. So whenever you invoke that callback from your adapter, it will be triggered in your fragment.
Step 1: Create a method like the one below in your fragment.
private fun showHideButtonFromAdapter (
isButtonVisible: Boolean
) {
// set your button visibility according to isButtonVisible value.
}
Step 2: pass a method from your fragment to adapter as argument
val adapter = YourAdapter(::showHideButtonFromAdapter)
// set above adapter in your recycler view.
Step 3: In your adapter invoke that callback function like the one below.
class ColorPickerAdapter constructor(
private val onItemClicked: (Boolean) -> Unit
) : RecyclerView.Adapter<YourAdapter.ViewHolder>() {
// your other adapter methods here
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
onItemClicked.invoke(pass true or false as per your requirement)
// above invocation will trigger an event in the fragment.
}
}
CodePudding user response:
In your adapter there need to be instance of your fragment, so change it like:
class QuestionAdap(val context: Context, val question: Question, fragment: Fragment) :
RecyclerView.Adapter<QuestionAdap.OptionViewHolder>() {
Then you can call your fragment by simply writing fragment
in your adapter like:
override fun onBindViewHolder(holder: OptionViewHolder, position: Int) {
holder.optionView.text = options[position]
holder.itemView.setOnClickListener {
question.userAnswer = options[position]
notifyDataSetChanged()
}
//Example
fragment.shuffle()
And you need to send this fragment instance when you create it's adapter, so in your fragment use this:
myadapter = QuestionAdap(requireContext(),Question(), this)