Why are all the images not coming to first column and the textviews two second column in android?

39 Views Asked by At

So, i have a list of images and another list of names of those images. I want to display all the images one below other in cardviews of first column and all the names one below other on cardviews in second column. But I am getting the like this Output

So, I want all the images strictly in first column and the names on second column.Below is my xml layout files 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"
    xmlns:tools="http://schemas.android.com/tools">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/flash_tablebar"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        android:layout_alignParentTop="true">

        <ImageView
            android:id="@+id/back_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:src="@drawable/ic_arrow_back" />
    </androidx.appcompat.widget.Toolbar>


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

</RelativeLayout>

item_practise_cards.xml

<GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:columnCount="2"
    android:orientation="horizontal"
    android:padding="8dp">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardImagePractise"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="4dp"
        android:onClick="onCardClick"
        android:clickable="true"
        android:foreground="?android:attr/selectableItemBackground">

        <ImageView
            android:id="@+id/imageViewPractise"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:scaleType="centerCrop" />
    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
        android:id="@+id/cardTextPractise"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="4dp"
        android:onClick="onCardClick"
        android:clickable="true"
        android:foreground="?android:attr/selectableItemBackground">

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

Following the Fragment class PractiseFragment.kt

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

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.visuallithuanian.R
import com.example.visuallithuanian.adapter.PractiseAdapter
import com.example.visuallithuanian.databinding.FragmentPractiseBinding
import dagger.hilt.android.AndroidEntryPoint
class PractiseFragment : Fragment() {
     lateinit var binding: FragmentPractiseBinding
    lateinit var recyclerView: RecyclerView
    private val imageNamesMap= HashMap<Int,String>()

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

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

        (requireActivity() as AppCompatActivity).setSupportActionBar(binding.toolbar)
        (requireActivity() as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true)

        populateImages()

        binding.recyclerViewPractise.layoutManager = GridLayoutManager(requireContext(),2)
       binding.recyclerViewPractise.adapter = PractiseAdapter(imageNamesMap)


        return binding.root

    }

    private fun populateImages() {
        // Add image resources to a list
        val imageResources = listOf(
            R.drawable.africa,
            R.drawable.asia,
            R.drawable.europe,
            R.drawable.antartica,
            R.drawable.australia
            // Add more image resources as needed
        )

        // Add image names to a list in random order
        val imageNames = listOf(
            "Africa",
            "Asia",
            "Europe",
            "Antarctica",
            "Australia"
            // Add more image names corresponding to the resources
        ).shuffled()

        // Use the shuffled names to assign each image resource ID a corresponding name in the imageNamesMap
        for (i in imageResources.indices) {
            imageNamesMap[imageResources[i]] = imageNames[i]
        }
    }


    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId){

            android.R.id.home->{
                requireActivity().onBackPressed()
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }

    // Handle card clicks for both card views
    fun onCardClick(view: View,position: Int) {
        // Check the clicked view's ID to identify which cardView was clicked
        when (view.id) {
            R.id.cardImagePractise -> {
                Toast.makeText(requireContext(),"Hello Card Image",Toast.LENGTH_SHORT).show()
            }
            R.id.cardTextPractise -> {
                Toast.makeText(requireContext(),"Hello Card Text",Toast.LENGTH_SHORT).show()
            }
        }
    }


}

Below is the adapter class PractiseAdapter.kt

package com.example.visuallithuanian.adapter

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

class PractiseAdapter(private val imageNamesMap: HashMap<Int, String>) :
    RecyclerView.Adapter<PractiseAdapter.PractiseViewHolder>() {

    private val imagesList: MutableList<Int> = imageNamesMap.keys.toMutableList()

    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 = imagesList.size

    override fun onBindViewHolder(holder: PractiseViewHolder, position: Int) {
        val imageResource = imagesList[position]
        val imageName = imageNamesMap[imageResource]

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

        holder.cardImagePractise.setOnClickListener {
            onCardClick(it, position)
        }

        holder.cardTextPractise.setOnClickListener {
            onCardClick(it, position)
        }
    }

    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)
    }

    private fun onCardClick(view: View, position: Int) {
        // Check the clicked view's ID to identify which cardView was clicked
        when (view.id) {
            R.id.cardImagePractise -> {
                // Handle image card click
                Toast.makeText(view.context, "Image clicked at position $position", Toast.LENGTH_SHORT).show()
            }
            R.id.cardTextPractise -> {
                // Handle text card click
                Toast.makeText(view.context, "Text clicked at position $position", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

I believe there is some issues in xml layout file

2

There are 2 best solutions below

3
Ahmad Bilal Khan On

In your case, you are setting GridLayoutManager with span count 2. Which is way its showing image items in two columns per row.

simplest solution is, set LinearLayoutManager in recyclerview with orientation vertical.

You can set LayoutManager in xml as

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerViewPractise"
    android:layout_below="@id/toolbar"
    android:layout_width="match_parent"
    tools:listitem="@layout/item_practise_cards"
    **app:layoutManager="android.support.v7.widget.LinearLayoutManager"
    android:orientation="vertical"**
    android:layout_marginTop="10dp"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp" />

Or programmatically as

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

Hope this helps

0
Goutham On

I would suggest you to use constraint layout instead of GridLayout to have to CardViews side by side.

So your item_practise_cards.xml will be something like this:

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="8dp">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardImagePractise"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        
        app:layout_constraintEnd_toStartOf="@id/cardTextPractise"
        app:layout_constraintStart_toStartOf="parent"

        android:layout_margin="4dp"
        android:onClick="onCardClick"
        android:clickable="true"
        android:foreground="?android:attr/selectableItemBackground">

        <ImageView
            android:id="@+id/imageViewPractise"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:scaleType="centerCrop" />
    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
        android:id="@+id/cardTextPractise"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        app:layout_constraintStart_toEndOf="@id/cardImagePractise"
        app:layout_constraintEnd_toEndOf="parent"

        android:layout_margin="4dp"
        android:onClick="onCardClick"
        android:clickable="true"
        android:foreground="?android:attr/selectableItemBackground">

        <TextView
            android:id="@+id/textViewPractise"
            android:layout_width="wrap_content"
            android:gravity="center"
            android:layout_height="wrap_content"
            android:text="Random Name"
            android:textSize="18sp" />
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>