Quelle est la meilleure stratégie pour réaliser cette fonctionnalité:
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:
Je voudrais montrer une partie de la prochaine carte à cette situation. Comment puis-je faire ceci?
Merci.
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"/>
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.
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"