rubensousa / DpadRecyclerView

A RecyclerView built for Android TV with Compose in mind and as a replacement for Leanback's BaseGridView.
https://rubensousa.github.io/DpadRecyclerView/
Apache License 2.0
136 stars 17 forks source link

First item of first row is smaller then all the others #205

Closed fankloano closed 8 months ago

fankloano commented 8 months ago

As discussed, the issue where the first item is smaller then the rest (see the red line on top of the following picture): firstitem_grid

Using the following d-pad-recyclerview-code in the layout:

<com.rubensousa.dpadrecyclerview.DpadRecyclerView
        android:id="@+id/rv_layout_Movies"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        app:spanCount="7"
        app:layout_constraintStart_toEndOf="@id/linLayout_movie_categories"
        app:layout_constraintHeight_percent="0.40"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintWidth_percent="1.0"
        tools:listitem="@layout/rv_item_movies"/>

Fragment code to prepare the recyclerview:

private fun prepareMoviesRecyclerView() {
        moviesAdapter = MoviesAdapter(onMovieClickListener, onMovieLongClickListener,this, helpViewModel)
        binding.rvLayoutMovies.apply {
            adapter = moviesAdapter
            addItemDecoration(
                DpadLinearSpacingDecoration.create(
                    itemSpacing = 12,
                    edgeSpacing = 6,
                    perpendicularEdgeSpacing = 12
                )
            )
            setSmoothFocusChangesEnabled(false)
        }
    }

And in the adapter I am simple using Glide to load the images from url to the imageview. If you need additional code please let me know which one, so that I can post it.

ps: I had a similar problem on a simple vertical dpad-recyclerview when there was some problem with the sizes of the focused columns (I was able to solve it with changing the margins I had).

rubensousa commented 8 months ago

Hi @fankloano. Can you please post the XML and kotlin code for your ViewHolders?

fankloano commented 8 months ago

Following the xml-code of rv_item_movies:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="160dp"
    android:id="@+id/cardview_movie"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardCornerRadius="5dp"
    app:cardElevation="2dp"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:foreground="@drawable/selector_vod_card_background">

    <FrameLayout
        android:background="@color/colorBG"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="1dp">

        <ImageView
            android:id="@+id/ivMovies"
            android:layout_width="match_parent"
            android:layout_height="180dp"
            android:scaleType="fitXY"
            tools:src="@drawable/testposter"/>

        <ImageView
            android:id="@+id/tv_isFullyWatched"
            android:layout_width="35dp"
            android:layout_height="20dp"
            android:background="#D02E3035"
            android:src="@drawable/ic_checked"
            android:layout_gravity="end"
            app:tint="@color/light_blue"
            android:visibility="invisible"/>

        <TextView
            android:id="@+id/tvMovies"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/ivMovies"
            android:layout_gravity="bottom"
            android:fontFamily="sans-serif-smallcaps"
            android:gravity="center"
            android:padding="5dp"
            android:background="#C12E3035"
            android:textColor="@color/white"
            android:textSize="10dp"
            android:typeface="monospace" />

        <ImageView
            android:id="@+id/tv_isFavorite"
            android:layout_width="35dp"
            android:layout_height="20dp"
            android:background="#D02E3035"
            android:src="@drawable/ic_favorite_vod"
            android:layout_gravity="start"
            android:visibility="invisible"/>

    </FrameLayout>

</androidx.cardview.widget.CardView>

With kotlin code you mean the adapter code?

  inner class ViewHolder(val binding: RvItemMoviesBinding) : RecyclerView.ViewHolder(binding.root) {

        fun bind(movie: Movie) {
            binding.apply {
                tvMovies.text = movie.movieName

                val image = movie.poster_url
                if (!image.isNullOrEmpty()) {
                    Glide.with(itemView.context).load(image)
                        .into(ivMovies)
                }

                binding.tvIsFavorite.visibility = if (movie.isFavorite) View.VISIBLE else View.INVISIBLE

                binding.cardviewMovie.setOnKeyListener { _, keyCode, event ->
                        if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && event.action == KeyEvent.ACTION_DOWN) {

                            if (bindingAdapterPosition % 7 == 0) {
                                fragment.setMovieCategoriesVisibilityAnimated(true)
                                return@setOnKeyListener true
                            }
                        }
                        if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_DOWN) {
                            fragment.setMovieCategoriesVisibilityAnimated(true)
                            return@setOnKeyListener true
                        }
                        if (keyCode == KeyEvent.KEYCODE_DPAD_UP && event.action == KeyEvent.ACTION_DOWN) {
                            if (bindingAdapterPosition == 0) {
                                binding.cardviewMovie.requestFocus()
                                return@setOnKeyListener true
                            }
                        }
                        if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN && event.action == KeyEvent.ACTION_DOWN) {
                            if (bindingAdapterPosition == itemCount - 1) {
                                binding.cardviewMovie.requestFocus()
                                return@setOnKeyListener true
                            }
                        }
                        return@setOnKeyListener false
                    }
                }
            }
        }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = RvItemMoviesBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        val viewHolder = ViewHolder(binding)
        return viewHolder
    }

    @UnstableApi
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val movie = getItem(position)!!
        holder.bind(movie)
        holder.binding.cardviewMovie.setOnFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                fragment.setDetailsUi(movie)
            } else {
            }
        }
    }
rubensousa commented 8 months ago

So your problem seems to be the usage of DpadLinearSpacingDecoration. Please use this instead: https://rubensousa.github.io/DpadRecyclerView/recipes/spacing/#grid-spacings

fankloano commented 8 months ago

@rubensousa sorry I overlooked the spacing recipes for grid.. using DpadGridSpacingDecoration solved the problem, thanks