Search code examples
androidgrid-layout

Making an Intent on a selected GridLayout position


I am trying to create a method that will listen to the item that is clicked and if the category is clicked, it should open the activity selected. I have a Grid Layout setup, but I am not really sure how I would set an onClickListener or an onRecyclerViewItemClick for this purpose. I do have a pseudocode that I believe could be implemented, but would need guidance for this.

Here is my MainActivity.kt:

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
    private lateinit var appBarConfiguration: AppBarConfiguration
    private var mAuthListener : FirebaseAuth.AuthStateListener? = null

    lateinit var myApi: IMyAPI
    lateinit var txt_user_name:TextView
    lateinit var txt_email_address:TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()

        myApi = RetrofitClient.getInstance().create(IMyAPI::class.java)

        Log.d("__MAIN__", "OnCreate")
    }

    private fun initView() {
        recycler_view.layoutManager = GridLayoutManager(this, 2)
        recycler_view.addItemDecoration(GridItemDecoration(10, 2))

        val categoryListAdapter = CategoryListGridRecyclerAdapter()
        recycler_view.adapter = categoryListAdapter
        categoryListAdapter.setProductList(generateDummyData())

        val navView: NavigationView = findViewById(R.id.nav_view)
        navView.setNavigationItemSelectedListener(this)
        navView.bringToFront()
    }

    private fun generateDummyData(): List<Category> {
        val listOfCategory = mutableListOf<Category>()

        var categoryModel = Category(1, "Products", R.drawable.kumo_logo, 1.90)
        listOfCategory.add(categoryModel)

        categoryModel = Category(2, "Food", R.drawable.kumo_logo, 1.90)
        listOfCategory.add(categoryModel)

        categoryModel = Category(3, "Technology", R.drawable.kumo_logo, 1.90)
        listOfCategory.add(categoryModel)

        categoryModel = Category(4, "News", R.drawable.kumo_logo, 1.90)
        listOfCategory.add(categoryModel)

        categoryModel = Category(5, "Economy", R.drawable.kumo_logo, 1.90)
        listOfCategory.add(categoryModel)

        categoryModel = Category(6, "Sports", R.drawable.kumo_logo, 1.90)
        listOfCategory.add(categoryModel)

        return listOfCategory
    }

    //Pseudocode:
    /*override fun onRecyclerViewItemClick(category: Category, position: Int)
    {
        lateinit var catClick: Intent
        if(category.id == 1)
        {
            catClick = Intent(this, ShowProducts::class.java)
        }

        startActivity(catClick) //start activity selected
    }*/

    override fun onNavigationItemSelected(item: MenuItem):Boolean {
        when (item.itemId) {
            R.id.nav_sign_out -> {
                Log.d("Testing logout ", "user")
                FirebaseAuth.getInstance().signOut()
                startActivity(Intent(this@MainActivity, LoginActivity::class.java))
                finish()
            }
        }

        return true
    }

}

GridItemDecoration.kt:

class GridItemDecoration(gridSpacingPx: Int, gridSize: Int) : RecyclerView.ItemDecoration() {
    private var mSizeGridSpacingPx: Int = gridSpacingPx
    private var mGridSize: Int = gridSize

    private var mNeedLeftSpacing = false

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        val frameWidth = ((parent.width - mSizeGridSpacingPx.toFloat() * (mGridSize - 1)) / mGridSize).toInt()
        val padding = parent.width / mGridSize - frameWidth
        val itemPosition = (view.getLayoutParams() as RecyclerView.LayoutParams).viewAdapterPosition

        if (itemPosition < mGridSize) {
            outRect.top = 0
        } else {
            outRect.top = mSizeGridSpacingPx
        }
        if (itemPosition % mGridSize == 0) {
            outRect.left = 0
            outRect.right = padding
            mNeedLeftSpacing = true
        } else if ((itemPosition + 1) % mGridSize == 0) {
            mNeedLeftSpacing = false
            outRect.right = 0
            outRect.left = padding
        } else if (mNeedLeftSpacing) {
            mNeedLeftSpacing = false
            outRect.left = mSizeGridSpacingPx - padding
            if ((itemPosition + 2) % mGridSize == 0) {
                outRect.right = mSizeGridSpacingPx - padding
            } else {
                outRect.right = mSizeGridSpacingPx / 2
            }
        } else if ((itemPosition + 2) % mGridSize == 0) {
            mNeedLeftSpacing = false
            outRect.left = mSizeGridSpacingPx / 2
            outRect.right = mSizeGridSpacingPx - padding
        } else {
            mNeedLeftSpacing = false
            outRect.left = mSizeGridSpacingPx / 2
            outRect.right = mSizeGridSpacingPx / 2
        }
        outRect.bottom = 0
    }
}

CategoryListGridRecyclerAdapter.kt

class CategoryListGridRecyclerAdapter:RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private var listOfCategory = listOf<Category>()
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return CategoryListViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.product_row, parent, false))

    }

    override fun getItemCount(): Int = listOfCategory.size

    override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
        val productViewHolder = viewHolder as CategoryListViewHolder
        productViewHolder.bindView(listOfCategory[position])
    }

    fun setProductList(listOfCategory: List<Category>) {
        this.listOfCategory = listOfCategory
        notifyDataSetChanged()
    }
}

Solution

  • You can do something like this:

      lateinit var mOnItemClickListener: (category: Category,pos: Int)-> Unit
    
      fun setOnItemClickListener(callback: (category: Category,pos: Int)-> Unit){
        mOnItemClickListener = callback
      }
    
      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return CategoryListViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.product_row, parent, false))
                .listen {pos,_ ->      
                     if(::mOnItemClickListener.isInitialized){
                           mOnItemClickListener(listOfCategory[pos],pos)
                     }
                 }
      }
     //I took this code from a post a while back, don't know the author
     fun <T : RecyclerView.ViewHolder> T.listen(event: (position: Int, type: Int) -> Unit): T {
         itemView.setOnClickListener {
            event.invoke(adapterPosition, itemViewType)
         }
         return this
     }
    

    On MainActivity

    categoryListAdapter.setOnItemClickListener { category, pos ->
     ...
    }