title: How to have a collapsing of top view into a smaller sized view?
body: <p>This question was asked before in a too broad and unclear way <a href="https://stackoverflow.com/q/47053822/878126"><strong>here</strong></a>, so I've made it much more specific, with full explanation and code of what I've tried. </p>
  
  <h2>Background</h2>
  
  <p>I'm required to mimic the way the Google Calendar has a view at the top, that can animate and push down the view at the bottom, yet it has extra, different behavior. I've summarized what I'm trying to do on 3 characteristics:</p>
  
  <ol>
  <li>Pressing on the toolbar will always work, to toggle expanding/collapsing of the top view, while having an arrow icon that changes its rotation. This is like on Google Calendar app.</li>
  <li>The top view will always snap, just like on Google Calendar app.</li>
  <li>When the top view is collapsed, only pressing on the toolbar will allow to expand it. This is like on Google Calendar app</li>
  <li>When the top view is expanded, scrolling at the bottom view will only allow to collapse. If you try to scroll the other direction, nothing occurs, not even to the bottom view. This is like on Google Calendar app</li>
  <li>Once collapsed, the top view will be replaced with a smaller view. This means it will always take some space, above the bottom view. This is not like on Google Calendar app, because on the Calendar app, the top view completely disappears once you collapse it.</li>
  </ol>
  
  <p>Here's how Google Calendar app look like:</p>
  
  <p><a href="https://i.stack.imgur.com/BY3U0.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/BY3U0.gif" alt="enter image description here"></a></p>
  
  <p>Scrolling on the bottom view also slowly hides the view at the top:</p>
  
  <p><a href="https://i.stack.imgur.com/M2eHG.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/M2eHG.gif" alt="enter image description here"></a></p>
  
  <h2>The problem</h2>
  
  <p>Using various solutions I've found in the past, I've succeeded to implement only a part of the needed behavior:</p>
  
  <ol>
  <li><p>Having some UI in the toolbar is done by having some views in it, including the arrow view. For manual expanding/collapsing I use <code>setExpanded</code> on the <code>AppBarLayout</code> view. For the rotation of the arrow, I use a listener of how much the <code>AppBarLayout</code> has resized, using <code>addOnOffsetChangedListener</code> on it.</p></li>
  <li><p>Snapping is easily done by adding <code>snap</code> value into <code>layout_scrollFlags</code> attribute of the <code>CollapsingToolbarLayout</code>. However, to make it really work well, without weird issues (reported <a href="https://issuetracker.google.com/issues/63745189" rel="noreferrer"><strong>here</strong></a>), I used <a href="https://stackoverflow.com/a/45338791/878126"><strong>this solution</strong></a>.</p></li>
  <li><p>Blocking of affecting the top view when scrolling can be done by using the same code I've used on #2 (<a href="https://stackoverflow.com/a/45338791/878126"><strong>here</strong></a>), by calling <code>setExpandEnabled</code> there. 
  This works fine for when the top view is collapsed.</p></li>
  <li><p>Similar to #3, but sadly, since it uses <code>setNestedScrollingEnabled</code>, which is in both directions, this works well only when the top view is collapsed. When it's expanded, it still allows the bottom view to scroll up, as opposed to Calendar app. When expanded, I need it to only allow to collapse, without allowing to really scroll.</p></li>
  </ol>
  
  <p>Here's a demonstration of the good, and the bad:</p>
  
  <p><a href="https://i.stack.imgur.com/HhHB9.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/HhHB9.gif" alt="enter image description here"></a></p>
  
  <ol start="5">
  <li>This I've failed completely to do. I've tried a lot of solutions I've thought about, putting views in various places with various flags. </li>
  </ol>
  
  <p>In short, I've succeeded doing 1-3, but not 4-5.</p>
  
  <h2>The code</h2>
  
  <p>Here's the current code (also available as whole project <a href="https://ufile.io/obvnu" rel="noreferrer"><strong>here</strong></a>) : </p>
  
  <p><strong>ScrollingActivity.kt</strong></p>
  
  <pre><code>class ScrollingActivity : AppCompatActivity(), AppBarTracking {
  
      private var mNestedView: MyRecyclerView? = null
      private var mAppBarOffset: Int = 0
      private var mAppBarIdle = false
      private var mAppBarMaxOffset: Int = 0
  
      private var isExpanded: Boolean = false
  
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_scrolling)
          val toolbar = findViewById&lt;Toolbar&gt;(R.id.toolbar)
          setSupportActionBar(toolbar)
          mNestedView = findViewById(R.id.nestedView)
          app_bar.addOnOffsetChangedListener({ appBarLayout, verticalOffset -&gt;
              mAppBarOffset = verticalOffset
              val totalScrollRange = appBarLayout.totalScrollRange
              val progress = (-verticalOffset).toFloat() / totalScrollRange
              arrowImageView.rotation = 180 + progress * 180
              isExpanded = verticalOffset == 0;
              mAppBarIdle = mAppBarOffset &gt;= 0 || mAppBarOffset &lt;= mAppBarMaxOffset
              if (mAppBarIdle)
                  setExpandAndCollapseEnabled(isExpanded)
          })
  
          app_bar.post(Runnable { mAppBarMaxOffset = -app_bar.totalScrollRange })
  
          mNestedView!!.setAppBarTracking(this)
          mNestedView!!.layoutManager = LinearLayoutManager(this)
          mNestedView!!.adapter = object : RecyclerView.Adapter&lt;RecyclerView.ViewHolder&gt;() {
              override fun getItemCount(): Int = 100
  
              override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
                  return object : ViewHolder(LayoutInflater.from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false)) {}
              }
  
              override fun onBindViewHolder(holder: ViewHolder, position: Int) {
                  (holder.itemView.findViewById&lt;View&gt;(android.R.id.text1) as TextView).text = "item $position"
              }
          }
  
          expandCollapseButton.setOnClickListener({ v -&gt;
              isExpanded = !isExpanded
              app_bar.setExpanded(isExpanded, true)
          })
      }
  
      private fun setExpandAndCollapseEnabled(enabled: Boolean) {
          mNestedView!!.isNestedScrollingEnabled = enabled
      }
  
      override fun isAppBarExpanded(): Boolean = mAppBarOffset == 0
      override fun isAppBarIdle(): Boolean = mAppBarIdle
  }
  </code></pre>
  
  <p><strong>MyRecyclerView.kt</strong></p>
  
  <pre><code>/**A RecyclerView that allows temporary pausing of casuing its scroll to affect appBarLayout, based on https://stackoverflow.com/a/45338791/878126 */
  class MyRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : RecyclerView(context, attrs, defStyle) {
      private var mAppBarTracking: AppBarTracking? = null
      private var mView: View? = null
      private var mTopPos: Int = 0
      private var mLayoutManager: LinearLayoutManager? = null
  
      interface AppBarTracking {
          fun isAppBarIdle(): Boolean
          fun isAppBarExpanded(): Boolean
      }
  
      override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?,
                                           type: Int): Boolean {
          if (type == ViewCompat.TYPE_NON_TOUCH &amp;&amp; mAppBarTracking!!.isAppBarIdle()
                  &amp;&amp; isNestedScrollingEnabled) {
              if (dy &gt; 0) {
                  if (mAppBarTracking!!.isAppBarExpanded()) {
                      consumed!![1] = dy
                      return true
                  }
              } else {
                  mTopPos = mLayoutManager!!.findFirstVisibleItemPosition()
                  if (mTopPos == 0) {
                      mView = mLayoutManager!!.findViewByPosition(mTopPos)
                      if (-mView!!.top + dy &lt;= 0) {
                          consumed!![1] = dy - mView!!.top
                          return true
                      }
                  }
              }
          }
  
          val returnValue = super.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type)
          if (offsetInWindow != null &amp;&amp; !isNestedScrollingEnabled &amp;&amp; offsetInWindow[1] != 0)
              offsetInWindow[1] = 0
          return returnValue
      }
  
      override fun setLayoutManager(layout: RecyclerView.LayoutManager) {
          super.setLayoutManager(layout)
          mLayoutManager = layoutManager as LinearLayoutManager
      }
  
      fun setAppBarTracking(appBarTracking: AppBarTracking) {
          mAppBarTracking = appBarTracking
      }
  
  }
  </code></pre>
  
  <p><strong>ScrollingCalendarBehavior.kt</strong></p>
  
  <pre><code>class ScrollingCalendarBehavior(context: Context, attrs: AttributeSet) : AppBarLayout.Behavior(context, attrs) {
      override fun onInterceptTouchEvent(parent: CoordinatorLayout?, child: AppBarLayout?, ev: MotionEvent): Boolean = false
  }
  </code></pre>
  
  <p><strong>activity_scrolling.xml</strong></p>
  
  <pre><code>&lt;android.support.design.widget.CoordinatorLayout
      android:id="@+id/coordinatorLayout" 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=".ScrollingActivity"&gt;
  
      &lt;android.support.design.widget.AppBarLayout
          android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="wrap_content"
          android:fitsSystemWindows="true" android:stateListAnimator="@null" android:theme="@style/AppTheme.AppBarOverlay"
          app:expanded="false" app:layout_behavior="com.example.user.expandingtopviewtest.ScrollingCalendarBehavior"
          tools:targetApi="lollipop"&gt;
  
          &lt;android.support.design.widget.CollapsingToolbarLayout
              android:id="@+id/collapsingToolbarLayout" android:layout_width="match_parent"
              android:layout_height="match_parent" android:fitsSystemWindows="true"
              android:minHeight="?attr/actionBarSize" app:contentScrim="?attr/colorPrimary"
              app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" app:statusBarScrim="?attr/colorPrimaryDark"&gt;
  
              &lt;LinearLayout
                  android:layout_width="match_parent" android:layout_height="250dp"
                  android:layout_marginTop="?attr/actionBarSize" app:layout_collapseMode="parallax"
                  app:layout_collapseParallaxMultiplier="1.0"&gt;
  
                  &lt;TextView
                      android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="10dp"
                      android:paddingRight="10dp" android:text="some large, expanded view"/&gt;
              &lt;/LinearLayout&gt;
  
              &lt;android.support.v7.widget.Toolbar
                  android:id="@+id/toolbar" android:layout_width="match_parent"
                  android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin"
                  app:popupTheme="@style/AppTheme.PopupOverlay"&gt;
  
                  &lt;android.support.constraint.ConstraintLayout
                      android:id="@+id/expandCollapseButton" android:layout_width="match_parent"
                      android:layout_height="?attr/actionBarSize" android:background="?android:selectableItemBackground"
                      android:clickable="true" android:focusable="true" android:orientation="vertical"&gt;
  
                      &lt;TextView
                          android:id="@+id/titleTextView" android:layout_width="wrap_content"
                          android:layout_height="wrap_content" android:layout_marginBottom="8dp"
                          android:layout_marginLeft="8dp" android:layout_marginStart="8dp" android:ellipsize="end"
                          android:gravity="center" android:maxLines="1" android:text="title"
                          android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
                          android:textColor="@android:color/white" app:layout_constraintBottom_toBottomOf="parent"
                          app:layout_constraintStart_toStartOf="parent"/&gt;
  
                      &lt;ImageView
                          android:id="@+id/arrowImageView" android:layout_width="wrap_content" android:layout_height="0dp"
                          android:layout_marginLeft="8dp" android:layout_marginStart="8dp"
                          app:layout_constraintBottom_toBottomOf="@+id/titleTextView"
                          app:layout_constraintStart_toEndOf="@+id/titleTextView"
                          app:layout_constraintTop_toTopOf="@+id/titleTextView"
                          app:srcCompat="@android:drawable/arrow_down_float"
                          tools:ignore="ContentDescription,RtlHardcoded"/&gt;
  
                  &lt;/android.support.constraint.ConstraintLayout&gt;
              &lt;/android.support.v7.widget.Toolbar&gt;
  
          &lt;/android.support.design.widget.CollapsingToolbarLayout&gt;
  
      &lt;/android.support.design.widget.AppBarLayout&gt;
  
      &lt;com.example.user.expandingtopviewtest.MyRecyclerView
          android:id="@+id/nestedView" android:layout_width="match_parent" android:layout_height="match_parent"
          app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".ScrollingActivity"/&gt;
  
  &lt;/android.support.design.widget.CoordinatorLayout&gt;
  </code></pre>
  
  <h2>The questions</h2>
  
  <ol>
  <li><p>How can I make the scrolling being blocked when the top view is expanded, yet allow to collapse while scrolling ?</p></li>
  <li><p>How can I make the top view be replaced with a smaller one when collapsed (and back to large one when expanded), instead of completely disappear ? </p></li>
  </ol>
  
  <hr>
  
  <h2>Update</h2>
  
  <p>Even though I've got the basic of what I asked about, there are still 2 issues with the current code (available on Github, <a href="https://github.com/Cheticamp/ExpandedTopViewTestUpdate" rel="noreferrer"><strong>here</strong></a>) :</p>
  
  <ol>
  <li>The small view (the one you see on collapsed state) has inner views that need to have a clicking effect on them. When using the <code>android:background="?attr/selectableItemBackgroundBorderless"</code> on them, and clicking on this area while being expanded, the clicking is done on the small view. I've handled it by putting the small view on a different toolbar, but then the clicking effect doesn't get shown at all. I've written about this <a href="https://github.com/Cheticamp/ExpandedTopViewTestUpdate/issues/1" rel="noreferrer"><strong>here</strong></a>, including sample project.</li>
  </ol>
  
  <p>Here's the fix:</p>
  
  <pre><code>&lt;android.support.design.widget.CoordinatorLayout
      android:id="@+id/coordinatorLayout" 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"&gt;
  
      &lt;android.support.design.widget.AppBarLayout
          android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="wrap_content"
          android:fitsSystemWindows="true" android:stateListAnimator="@null" android:theme="@style/AppTheme.AppBarOverlay"
          app:expanded="false" app:layout_behavior="com.example.expandedtopviewtestupdate.ScrollingCalendarBehavior"
          tools:targetApi="lollipop"&gt;
  
          &lt;android.support.design.widget.CollapsingToolbarLayout
              android:id="@+id/collapsingToolbarLayout" android:layout_width="match_parent"
              android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"
              android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary"
              app:layout_scrollFlags="scroll|exitUntilCollapsed|snap|enterAlways"
              app:statusBarScrim="?attr/colorPrimaryDark"&gt;
  
              &lt;!--large view --&gt;
              &lt;LinearLayout
                  android:id="@+id/largeView" android:layout_width="match_parent" android:layout_height="280dp"
                  android:layout_marginTop="?attr/actionBarSize" android:orientation="vertical"
                  app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="1.0"&gt;
  
                  &lt;TextView
                      android:id="@+id/largeTextView" android:layout_width="match_parent"
                      android:layout_height="match_parent" android:layout_gravity="center"
                      android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true"
                      android:focusable="true" android:focusableInTouchMode="false" android:gravity="center"
                      android:text="largeView" android:textSize="14dp" tools:background="?attr/colorPrimary"
                      tools:layout_gravity="top|center_horizontal" tools:layout_height="40dp" tools:layout_width="40dp"
                      tools:text="1"/&gt;
  
              &lt;/LinearLayout&gt;
  
              &lt;!--top toolbar--&gt;
              &lt;android.support.v7.widget.Toolbar
                  android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content"
                  android:layout_marginBottom="@dimen/small_view_height" app:contentInsetStart="0dp"
                  app:layout_collapseMode="pin" app:popupTheme="@style/AppTheme.PopupOverlay"&gt;
  
                  &lt;android.support.constraint.ConstraintLayout
                      android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true"
                      android:focusable="true"&gt;
  
                      &lt;LinearLayout
                          android:id="@+id/expandCollapseButton" android:layout_width="match_parent"
                          android:layout_height="?attr/actionBarSize"
                          android:background="?android:selectableItemBackground" android:gravity="center_vertical"
                          android:orientation="horizontal" app:layout_constraintStart_toStartOf="parent"
                          app:layout_constraintTop_toTopOf="parent"&gt;
  
                          &lt;TextView
                              android:id="@+id/titleTextView" android:layout_width="wrap_content"
                              android:layout_height="wrap_content" android:ellipsize="end" android:gravity="center"
                              android:maxLines="1" android:text="title"
                              android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
                              android:textColor="@android:color/white"/&gt;
  
                          &lt;ImageView
                              android:id="@+id/arrowImageView" android:layout_width="wrap_content"
                              android:layout_height="wrap_content" android:layout_marginLeft="8dp"
                              android:layout_marginStart="8dp" app:srcCompat="@android:drawable/arrow_up_float"
                              tools:ignore="ContentDescription,RtlHardcoded"/&gt;
                      &lt;/LinearLayout&gt;
  
                  &lt;/android.support.constraint.ConstraintLayout&gt;
  
              &lt;/android.support.v7.widget.Toolbar&gt;
  
              &lt;android.support.v7.widget.Toolbar
                  android:id="@+id/smallLayoutContainer" android:layout_width="match_parent"
                  android:layout_height="wrap_content" android:layout_marginTop="?attr/actionBarSize"
                  android:clipChildren="false" android:clipToPadding="false" app:contentInsetStart="0dp"
                  app:layout_collapseMode="pin"&gt;
                  &lt;!--small view--&gt;
                  &lt;LinearLayout
                      android:id="@+id/smallLayout" android:layout_width="match_parent"
                      android:layout_height="@dimen/small_view_height" android:clipChildren="false"
                      android:clipToPadding="false" android:orientation="horizontal" tools:background="#ff330000"
                      tools:layout_height="@dimen/small_view_height"&gt;
  
                      &lt;TextView
                          android:id="@+id/smallTextView" android:layout_width="match_parent"
                          android:layout_height="match_parent" android:layout_gravity="center"
                          android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true"
                          android:focusable="true" android:focusableInTouchMode="false" android:gravity="center"
                          android:text="smallView" android:textSize="14dp" tools:background="?attr/colorPrimary"
                          tools:layout_gravity="top|center_horizontal" tools:layout_height="40dp"
                          tools:layout_width="40dp" tools:text="1"/&gt;
  
                  &lt;/LinearLayout&gt;
              &lt;/android.support.v7.widget.Toolbar&gt;
          &lt;/android.support.design.widget.CollapsingToolbarLayout&gt;
  
      &lt;/android.support.design.widget.AppBarLayout&gt;
  
      &lt;com.example.expandedtopviewtestupdate.MyRecyclerView
          android:id="@+id/nestedView" android:layout_width="match_parent" android:layout_height="match_parent"
          app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".ScrollingActivity"/&gt;
  
  &lt;/android.support.design.widget.CoordinatorLayout&gt;
  </code></pre>
  
  <ol start="2">
  <li>The Google Calendar allows to perform a scroll-down gesture on the toolbar itself, to trigger showing the month view. I've succeeded only adding a clicking event there, but not scrolling. Here's how it looks like:</li>
  </ol>
  
  <p><a href="https://i.stack.imgur.com/S28X5.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/S28X5.gif" alt="enter image description here"></a></p>