【问题标题】:How to show part of next/previous card RecyclerView如何显示下一张/上一张卡片 RecyclerView 的一部分
【发布时间】:2020-01-17 19:03:56
【问题描述】:

实现此功能的最佳策略是什么:

我有一个带有卡片的水平 RecyclerView。 每张卡片都会填满整个屏幕,但如果它有多个项目,我希望它显示下一张卡片和上一张卡片的一部分。

我知道我可以通过在适配器上将我的卡 android:layout_width 设置为具有特定的 DP,例如 250dp 而不是 match_parent。 但这看起来不是一个合适的解决方案。

这是我的代码:

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

Activity的布局:

<?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>

适配器:

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

适配器布局:

<?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>

这是我的结果:

我想在这种情况下展示下一张卡片的一部分。我该怎么做?

谢谢。

【问题讨论】:

  • 使用浏览器

标签: android android-recyclerview


【解决方案1】:

您需要做的是将填充设置为RecyclerView,将clipToPadding 设置为false,并使用SnapHelper,并且您需要确保卡片上的边距小于或等于到RecylerView 中的填充。

因此,假设您希望卡片到屏幕两侧的距离为 16dp,并且您希望卡片之间的距离为 8dp。您必须将每张卡片的边距设置为 4dp,因此总边距为 8dp。并且您必须将内边距设置为 12dp,因为卡片的每一侧已经有 4dp 的边距。

看起来有点像这样:

您的清单:

<?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"/>

你的卡片:

<?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"/>

【讨论】:

  • 看起来很棒!谢谢。
  • 如果我们需要根据卡片位置的不同边距怎么办,所以假设我们可以在第一张卡片旁边看到更多卡片(因此它不会居中),其余中间卡片是居中,即在它们之前和之后看到相同数量的卡片,最后一张卡片似乎更多的是倒数第二张卡片?
  • @RamPrasadBismil 您必须根据位置动态设置 onBindViewHolder 中的边距
  • 多么聪明的把戏!虽然我不明白为什么提到了SnapHelper,但它并没有在这个解决方案中使用。
【解决方案2】:

我认为填充解决方案并不适用于所有情况,因为会强制最后一项向右填充。

我个人使用每个项目的运行时宽度计算,对此我非常满意。因此,您可以执行以下操作:

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

结果是所有中间项都呈现为显示下一页的一部分,但最后一项呈现全宽。

【讨论】:

    【解决方案3】:

    将您的 CardView 宽度从 "match_parent" 更改为 "0dp"。并将layout_weight 添加为"80"(或类似名称)。将您的父视图 (RecyclerView) layout_weightSum 设为 "100"

    android:layout_width="0dp"
    android:layout_weight="80"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 1970-01-01
      • 1970-01-01
      • 2020-12-08
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多