この機能を実現するための最良の戦略は何ですか?
カードが付いた横向きのRecyclerViewがあります。各カードは画面全体に表示されますが、アイテムが複数ある場合は、次のカードと前のカードの一部を表示したいと思います。
アダプタでカードAndroid:layout_width
をmatch_parent
ではなく250dpのような特定のDPに設定することで、これを実現できることはわかっています。しかし、それは適切な解決策のようには見えません。
これは私のコードです:
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)
}
アクティビティのレイアウト:
<?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>
これは私の結果です:
この状況で次のカードの一部を紹介したいと思います。これどうやってするの?
ありがとう。
あなたがする必要があるのは、RecyclerView
にパディングを設定し、clipToPadding
をfalse
に設定し、SnapHelper
を使用して、そしてカードのマージンがRecylerView
のパディング以下です。
したがって、カードから画面の端までの距離を16 dpにして、カード間の距離を8 dpにしたいとします。各カードのマージンを4 dpに設定する必要があるため、合計マージンは8 dpになります。また、カードの両側にすでに4 dpのマージンがあるため、パディングを12 dpに設定する必要があります。
次のようになります。
あなたのリスト:
<?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"/>
最後のアイテムに強制的にパディングを付けるため、パディングソリューションはすべてのケースに適しているわけではないと思います。
個人的には、各項目のランタイム幅の計算を使用しており、これに非常に満足しています。したがって、次のことができます。
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()
}
}
その結果、すべての中央のアイテムは次のページの一部を表示してレンダリングされますが、最後のアイテムは全幅でレンダリングされます。
CardView
の幅を"match_parent"
から"0dp"
に変更します。そして、layout_weight
を"80"
(または類似)として追加します。親ビュー(RecyclerView
)layout_weightSum
を"100"
として作成します。
Android:layout_width="0dp"
Android:layout_weight="80"