Background
I'm try to achieve something similar to what the Camera app has for its modes:
I might probably not need to have a ViewPager, as seems that it uses above the horizontal list, but could be nice to have it as an option.
The problem
While technically I succeeded to have the RecyclerView center its items, it doesn't let you actually have the all items to be able to be on the center (example is the first/last one). When you try to scroll to the first or last items, it doesn't let you , because you've reached the edge of the RecyclerView :
Not only that, but in the beginning it doesn't really center, and if I have the RecyclerView have few items, it becomes a problem because I want them to be centered, but having android:layout_width="match_parent" (because all of it should be touch-able) produces this:
while having android:layout_width="wrap_content" get me this:
On both cases, I can't scroll at all. When it's "wrap_content", it's a problem because I won't be able to scroll on the sides.
What I've tried
It's possible to snap the items so that there will always be an item in the center of RecyclerView as such :
val snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(categoriesRecyclerView)
We can also get which is the item in the center (as shown here), by having a scroll listener and using snapHelper.findSnapView(layoutManagaer)
.
But as I wrote, I can't really have the first/last item being selected this way, because I can't scroll to it so that it will be at the middle.
I tried to look at the docs of the related classes, but I can't find such a thing.
Here's the current code (sample available here) :
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.adapter = object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val holder = object : RecyclerView.ViewHolder(
LayoutInflater.from(this@MainActivity).inflate(
R.layout.list_item,
parent,
false
)
) {}
holder.itemView.setOnClickListener {
}
return holder
}
override fun getItemCount(): Int = 20
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder.itemView.textView.text = "pos:$position"
}
}
val snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(recyclerView)
}
}
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView android:background="#66000000"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_size"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/list_item"/>
</androidx.constraintlayout.widget.ConstraintLayout>
list_item.xml
<TextView
android:id="@+id/textView" 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="wrap_content" android:layout_height="@dimen/list_item_size"
android:background="?attr/selectableItemBackground" android:breakStrategy="balanced" android:clickable="true"
android:focusable="true" android:gravity="center" android:maxLines="1" android:padding="8dp"
android:shadowColor="#222" android:shadowDx="1" android:shadowDy="1" android:textColor="#fff"
app:autoSizeTextType="uniform" tools:targetApi="m" tools:text="@tools:sample/lorem"/>
The question
How can I let the user freely scroll inside, so that the edge will be determined by whether the first/last item is in the middle? How can I always have the items centered, including when I just started seeing the RecyclerView), and including when there are few of them?