I've got a CoordinatorLayout
which contains a CollapsingToolbarLayout
and a RecyclerView
. Everything looks the way it's supposed to, except that when I try to scroll to the last item programmatically, it doesn't go all the way to the bottom. Instead, it does this:
I don't think this is a clipping problem, since the bottom item is fully there if I scroll down:
Here's the main layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="150dp"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="16dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="@+id/toolbar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:contentInsetStart="72dp"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/recyclerview_bottom_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
And here's the code that goes with the screencaps above:
class TestActivity : AppCompatActivity() {
private val itemNames = listOf("top item", "next item", "yada", "yada yada", "yada yada yada", "second last item", "last item")
private val selectedPosition = itemNames.size - 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.recyclerview_with_collapsing_toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setTitle(R.string.some_title)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.setHasFixedSize(true)
val layoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = MyAdapter()
// try to scroll to the initial selected position
recyclerView.scrollToPosition(selectedPosition)
// layoutManager.scrollToPosition(selectedPosition)
// layoutManager.scrollToPositionWithOffset(selectedPosition, resources.getDimensionPixelOffset(R.dimen.item_height))
// recyclerView.post {
// recyclerView.smoothScrollToPosition(selectedPosition)
// }
}
inner class MyAdapter: RecyclerView.Adapter<MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, itemType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return itemNames.size
}
override fun onBindViewHolder(vh: MyViewHolder, position: Int) {
vh.words.text = itemNames[position]
if (selectedPosition == position) {
vh.parent.setBackgroundColor(Color.MAGENTA)
} else {
vh.parent.setBackgroundColor(Color.BLACK)
}
}
}
inner class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val parent = itemView
val words: TextView = itemView.findViewById(R.id.some_text)
}
}
Additional notes:
If I get rid of the CollapsingToolbarLayout
then it does show the entire last item.
I've left some of my other attempts in the code above (commented out). None of them worked.
This example just involves a short static list and always scrolls to the same item, but the code I'm actually working on is a bit more complicated.
The designer really wants everything to look exactly as designed, and I'm not free to change the visual design.
How can I scroll to the last item in a RecyclerView
that's inside a layout with a collapsing toolbar?
The problem is that getNestedScrollingParentForType(type) in NestedScrollingChildHelper#dispatchNestedScroll returns null for the non-touch scroll, so scrolling is not dispatched when it is done programmatically.
So we need to enable that before scrolling programmatically:
if (!recyclerView.hasNestedScrollingParent(ViewCompat.TYPE_NON_TOUCH)) {
recyclerView.startNestedScroll(View.SCROLL_AXIS_VERTICAL,ViewCompat.TYPE_NON_TOUCH);
}
// now smooth scroll your recycler view programmatically here.
A fix for this problem would be to collapse the toolbar before scrolling to the given position. This can be done by adding app_bar_layout.setExpanded(false)
before scrollToPosition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With