Why my cardview shows wrong colour even if correct name is choosen in android?

53 Views Asked by At

I have two columns with all the images in first column and second column with names. The image and names are stored in HashMap in the form of key-value pair. Where keys are images and value as their correct names. But, there is a catch , the names are shuffled so user can click on correct name. So, what I am trying to achieve is , when I click on image cardview, it's background colour should turn to green [it does change] and then when i click correct name for that image that correct name should turn into Green too and if wrong name card is clicked than that name card background should turn into Red. Currently , I am getting Red colour even correct name is choosen like this it looks like this

Below is the code of my Fragment PractiseFragment.kt

package com.example.visuallithuanian.ui.activities.fragments


import com.example.visuallithuanian.adapter.PractiseAdapter
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.visuallithuanian.Utils.shuffleList
import com.example.visuallithuanian.constants.ImageStore
import com.example.visuallithuanian.databinding.FragmentPractiseBinding

class PractiseFragment : Fragment() {
    lateinit var binding: FragmentPractiseBinding

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // Inflate the layout for this fragment

        binding = FragmentPractiseBinding.inflate(layoutInflater,container,false)


        val layoutManager = LinearLayoutManager(requireContext(),LinearLayoutManager.VERTICAL,false)
        binding.recyclerViewPractise.layoutManager = layoutManager

        // Shuffle the list of image names
        val shuffledImageNames = ImageStore.imagesNamesMap.values.toList().shuffleList()
        val shuffledImageResources = ImageStore.imagesNamesMap.keys.toList().shuffleList()


        val adapter = PractiseAdapter(shuffledImageResources,shuffledImageNames)
        binding.recyclerViewPractise.adapter = adapter


        return binding.root

    }

}

Following is the xml file for this fragment named fragment_practise.xml

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/nana"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- RecyclerView to display the image cards -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewPractise"
        android:layout_width="match_parent"
        tools:listitem="@layout/item_practise_cards"
        android:layout_marginTop="100dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="20dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp" />

</RelativeLayout>

Below is the code the video of adapter class , PractiseAdapter.kt

  package com.example.visuallithuanian.adapter

import android.annotation.SuppressLint
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import com.example.visuallithuanian.R
import com.example.visuallithuanian.Utils.shuffleList


class PractiseAdapter(
    private val imageResources: List<Int>,
    private val imageNames: List<String>
) : RecyclerView.Adapter<PractiseAdapter.PractiseViewHolder>() {

    private val shuffledIndexes: List<Int> = imageResources.indices.shuffled()
    private var selectedImagePosition = -1
    private var selectedNamePosition = -1
    private var correctNameIndex = -1

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PractiseViewHolder {
        val view =
            LayoutInflater.from(parent.context).inflate(R.layout.item_practise_cards, parent, false)
        return PractiseViewHolder(view)
    }

    override fun getItemCount(): Int = imageResources.size

    override fun onBindViewHolder(holder: PractiseViewHolder, @SuppressLint("RecyclerView") position: Int) {
        val shuffledIndex = shuffledIndexes[position]
        val imageResource = imageResources[shuffledIndex]
        val imageName = imageNames[shuffledIndex]

        holder.imageViewPractise.setImageResource(imageResource)
        holder.textViewPractise.text = imageName

        // Set the background color of the image card based on selection
        holder.cardImagePractise.setCardBackgroundColor(
            if (selectedImagePosition == position) Color.GREEN else Color.WHITE
        )

        // Set the background color of the name card based on selection and correctness
        holder.cardTextPractise.setCardBackgroundColor(
            when {
                selectedNamePosition == position -> {
                    if (imageName == imageNames[correctNameIndex] && correctNameIndex == shuffledIndex) {
                        Color.GREEN // Correct name selected
                    } else {
                        Color.RED // Wrong name selected
                    }
                }
                else -> Color.WHITE // Default color
            }
        )

        holder.cardImagePractise.setOnClickListener {
            // Set the selected image position and reset the selected name position
            selectedImagePosition = position
            selectedNamePosition = -1
            correctNameIndex = imageNames.indexOf(imageName)
            notifyDataSetChanged()
        }

        holder.cardTextPractise.setOnClickListener {
            if (selectedImagePosition != -1) {
                // Check if the correct name is selected
                val correctImageName = imageNames[selectedImagePosition]
                if (imageName == correctImageName) {
                    Toast.makeText(
                        it.context,
                        "Correct name selected!",
                        Toast.LENGTH_SHORT
                    ).show()
                } else {
                    Toast.makeText(
                        it.context,
                        "Wrong name selected!",
                        Toast.LENGTH_SHORT
                    ).show()
                }
                selectedNamePosition = position
                notifyDataSetChanged()
            } else {
                Toast.makeText(
                    it.context,
                    "Please select an image card first.",
                    Toast.LENGTH_SHORT
                ).show()
            }
        }
    }

    class PractiseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val cardImagePractise: CardView = itemView.findViewById(R.id.cardImagePractise)
        val cardTextPractise: CardView = itemView.findViewById(R.id.cardTextPractise)
        val imageViewPractise: ImageView = itemView.findViewById(R.id.imageViewPractise)
        val textViewPractise: TextView = itemView.findViewById(R.id.textViewPractise)
    }
}

Below is the xml layout file for Adapter class, item_practise_cards.xml

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:columnCount="2"
    android:rowCount="4"
    android:layout_marginTop="10dp"
    android:orientation="horizontal"
    android:padding="8dp">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardImagePractise"
        android:layout_width="150dp"
        android:layout_height="120dp"
        android:layout_gravity="center"
        android:layout_margin="4dp"
        app:cardCornerRadius="10dp"
        android:foreground="?android:attr/selectableItemBackground">

        <ImageView
            android:id="@+id/imageViewPractise"
            android:layout_width="100dp"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_height="100dp"
            android:scaleType="centerCrop" />
    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
        android:id="@+id/cardTextPractise"
        android:layout_width="150dp"
        android:layout_height="120dp"
        android:layout_gravity="center"
        android:layout_margin="4dp"
        app:cardCornerRadius="10dp"
        android:foreground="?android:attr/selectableItemBackground"
        android:focusable="true"
        tools:ignore="UsingOnClickInXml">

        <TextView
            android:id="@+id/textViewPractise"
            android:layout_width="150dp"
            android:gravity="center"
            android:layout_height="150dp"
            android:textStyle="bold"
            android:text="Random Name"
            android:textSize="18sp" />
    </androidx.cardview.widget.CardView>
</GridLayout>

below is the singleton where i have declared all the image-name key-value pairs in Hahmap. It's name is ImageStore.kt

package com.example.visuallithuanian.constants

import com.example.visuallithuanian.R

object ImageStore {

    val imagesNamesMap= hashMapOf(
        R.drawable.africa to "Africa",
        R.drawable.asia to "Asia",
        R.drawable.europe to "Europe",
        R.drawable.antartica to "Antarctica"
    )

}

I want background colour of name card Africa to be Green and not Red.

1

There are 1 best solutions below

2
Dat Pham Tat On

I think you have it overcomplicated, which gave room for errors. Try to simplify PractiseAdpter as follow:

class PractiseAdapter(
    private val imageResources: List<Int>,
    private val imageNames: List<String>
) : RecyclerView.Adapter<PractiseAdapter.PractiseViewHolder>() {

    private var selectedImageResource = -1
    private var selectedImageName = ""

    ...

    override fun onBindViewHolder(
        holder: PractiseViewHolder,
        @SuppressLint("RecyclerView") position: Int
    ) {
        val imageResource = imageResources[position]
        val imageName = imageNames[position]

        holder.imageViewPractise.setImageResource(imageResource)
        holder.textViewPractise.text = imageName

        holder.cardImagePractise.setOnClickListener {
            // Set the selected image position and reset the selected name position
            selectedImageResource = imageResources[position]
            selectedImageName = ""
            notifyDataSetChanged()
        }

        // Set the background color of the image card based on selection
        holder.cardImagePractise.setCardBackgroundColor(
            if (selectedImageResource == imageResources[position]) Color.GREEN else Color.WHITE
        )

        holder.cardTextPractise.setOnClickListener {
            if (selectedImageResource == -1) {
                Toast.makeText(
                    it.context,
                    "Please select an image card first.",
                    Toast.LENGTH_SHORT
                ).show()
            } else {
                selectedImageName = imageNames[position]
            }
            notifyDataSetChanged()
        }

        val nameColor = if (imageNames[position] == selectedImageName) {
            if (ImageStore.imagesNamesMap[selectedImageResource] == selectedImageName) {
                Toast.makeText(
                    holder.itemView.context,
                    "Correct name selected!",
                    Toast.LENGTH_SHORT
                ).show()
                Color.GREEN
            } else {
                Toast.makeText(
                    holder.itemView.context,
                    "Wrong name selected!",
                    Toast.LENGTH_SHORT
                ).show()
                Color.RED
            }
        } else {
            Color.WHITE
        }

        holder.textViewPractise.setBackgroundColor(nameColor)
    }

    ...
}

In short, just remember the selected image resource and the selected name directly, instead of their indexes. Then, use ImageStore.imagesNamesMap to match the selected image and the selected name.