web-dev-qa-db-fra.com

Comment montrer une partie de la carte suivante / précédente RecyclerView

Quelle est la meilleure stratégie pour réaliser cette fonctionnalité:

enter image description here

J'ai un RecyclerView horizontal avec des cartes. Chaque carte remplira tout l'écran, mais je veux qu'elle montre une partie de la carte suivante et précédente si elle a plus d'un élément.

Je sais que je peux y parvenir en définissant ma carte Android:layout_width sur l'adaptateur pour avoir un DP spécifique comme 250dp au lieu de match_parent. Mais cela ne ressemble pas à une bonne solution.

Voici mon code:

Activité avec RecyclerView:

    class ListPokemon : AppCompatActivity() {

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

        val items = createListPokemons()
        recyclerView.adapter = PokemonAdapter(items)
        recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
        recyclerView.setHasFixedSize(true)
        val pagerSnapHelper = PagerSnapHelper()
        pagerSnapHelper.attachToRecyclerView(recyclerView)
    }

    private fun createListPokemons(): List<Pokemon> {
        val pokemons = ArrayList<Pokemon>()
        pokemons += createPokemon("Pikachu")
        pokemons += createPokemon("Bulbasaur")
        pokemons += createPokemon("Charmander")
        pokemons += createPokemon("Squirtle")

        return pokemons
    }

    private fun createPokemon(name: String) = Pokemon(name = name, height = 1, weight = 69, id = 1)
}

Disposition de l'activité:

<?xml version="1.0" encoding="utf-8"?>
<Android.support.constraint.ConstraintLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/recyclerView"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:layoutManager="Android.support.v7.widget.LinearLayoutManager"/>

</Android.support.constraint.ConstraintLayout>

Adaptateur:

class PokemonAdapter(val list: List<Pokemon>) : RecyclerView.Adapter<PokemonAdapter.PokemonVH>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PokemonAdapter.PokemonVH {
        return PokemonVH(LayoutInflater.from(parent.context)
            .inflate(R.layout.pokemon_item, parent, false))
    }

    override fun onBindViewHolder(holder: PokemonAdapter.PokemonVH, position: Int) {
        holder.textViewName.text = list[position].name
    }

    override fun getItemCount(): Int {
        return list.size
    }

    class PokemonVH(itemView: View) : RecyclerView.ViewHolder(itemView) {

        var textViewName: TextView = itemView.findViewById(R.id.textViewName)
    }
}

Disposition de l'adaptateur:

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.CardView
    Android:layout_gravity="center_horizontal"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_marginStart="16dp"
    Android:layout_marginEnd="16dp"
    app:cardCornerRadius="8dp"
    app:cardElevation="4dp">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical">

        <TextView
            Android:padding="36dp"
            Android:id="@+id/textViewName"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:gravity="center"
            Android:textSize="22sp"
            tools:text="Teste String"/>

    </LinearLayout>

</Android.support.v7.widget.CardView>

Voici mon résultat:

enter image description here

Je voudrais montrer une partie de la prochaine carte à cette situation. Comment puis-je faire ceci?

Merci.

14
leonvian

Ce que vous devez faire est de définir le remplissage de votre RecyclerView, définir clipToPadding sur false, utiliser un SnapHelper avec, et vous devez vous assurer que le les marges sur vos cartes sont inférieures ou égales au remplissage dans le RecylerView.

Supposons donc que vous souhaitiez que la distance entre les cartes et les côtés de l'écran soit de 16dp et que la distance entre les cartes soit de 8dp. Vous devrez définir les marges sur chaque carte à 4dp, donc la marge totale est de 8dp. Et vous devez définir le remplissage à 12dp, étant donné qu'il y a déjà une marge de 4dp de chaque côté de la carte.

Cela ressemblera un peu à ceci:

Votre liste:

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.RecyclerView
    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="wrap_content"
    app:layoutManager="Android.support.v7.widget.LinearLayoutManager"
    Android:clipToPadding="false"
    Android:orientation="horizontal"
    Android:paddingStart="12dp"
    Android:paddingEnd="12dp"/>

Vos cartes:

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.CardView
    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="wrap_content"
    Android:layout_marginEnd="4dp"
    Android:layout_marginStart="4dp"
    app:cardElevation="2dp"/>
34

Je pense que la solution de rembourrage n'est pas bonne dans tous les cas, car force le dernier élément à avoir un rembourrage vers la droite.

Personnellement, j'utilise le calcul de la largeur d'exécution de chaque élément et j'en suis très satisfait. Vous pouvez donc effectuer les opérations suivantes:

onBindViewHolder

if (position == data.size - 1) {
    holder.itemView.layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)
} else {
    if (width == null) {
        holder.itemView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
              override fun onGlobalLayout() {
                   holder.itemView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                   width = holder.itemView.width
                   params.width = width!! - partOfPage
                   holder.itemView.requestLayout()
              }
         })
     } else {
         params.width = width!! - partOfPage
         holder.itemView.requestLayout()
     }
 }

Le résultat est que tous les éléments du milieu sont rendus montrant une partie de la page suivante, mais le dernier est rendu pleine largeur.

1
mspapant

Modifiez la largeur de votre CardView de "match_parent" à "0dp". Et ajouter, layout_weight comme "80" (ou similaire). Faites votre vue parent (RecyclerView) layout_weightSum comme "100".

Android:layout_width="0dp"
Android:layout_weight="80"
0
Gokul Nath KP