2016年2月28日 星期日

scroll actionbar(use the design library,a more easy way to make the app bar can scroll than before)

http://saulmm.github.io/mastering-coordinator

scroll actionbar(use the design library,a more easy way to make the app bar can scroll than before)

Coordinator Layout

simliar to frame layout,overlap by default,can use layout gravity,
這個強大的Layout擁有"依據Layout底下一個View的位置變化,
進而讓其它子View也跟著位移"的能力。


now,we start to program it:
1.
compile 'com.android.support:design:23.1.0'


2.
the orginal code is
<RelativeLayout
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.support.v7.widget.RecyclerView
       android:id="@+id/recyclerview_forecast"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       />
   <!-- empty list -->
   <TextView
       android:id="@+id/recyclerview_forecast_empty"
       android:text="@string/empty_forecast_list"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:gravity="center_horizontal"
       android:paddingRight="@dimen/activity_horizontal_margin"
       android:paddingEnd="@dimen/activity_horizontal_margin"
       android:paddingLeft="@dimen/activity_horizontal_margin"
       android:paddingStart="@dimen/activity_horizontal_margin"
       android:paddingTop="@dimen/activity_vertical_margin"
       android:paddingBottom="@dimen/activity_vertical_margin"
       />
   <LinearLayout
       android:id="@+id/appbar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentTop="true"
       android:background="?attr/colorPrimary"
       android:orientation="vertical">
       <android.support.v7.widget.Toolbar
           android:id="@+id/toolbar"
           android:layout_height="?attr/actionBarSize"
           android:layout_width="match_parent"
           android:elevation="0dp"
           app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
           app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
       <ImageView
           android:layout_width="match_parent"
           android:layout_height="?attr/listPreferredItemHeight"
           android:layout_gravity="center"
           android:scaleType="center"
           android:src="@drawable/ic_logo"
           android:contentDescription="@string/app_name"/>
   </LinearLayout>
</RelativeLayout>

if we want to make the app bar scrolling acrodaing to the Recycle view, we must use CoordinatorLayout ,and AppBarLayout


3.
first we use a FrameLayout or LinearLayout


than put all the view inside,


like this
<!--
    Copyright (C) 2015 The Android Open Source Project


    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at


         http://www.apache.org/licenses/LICENSE-2.0


    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:orientation="vertical"
   android:layout_height="match_parent">


   

          


    


           <android.support.v7.widget.Toolbar
               android:id="@+id/toolbar"
               android:layout_width="match_parent"
               android:layout_height="?attr/actionBarSize"
               android:elevation="0dp"
               app:layout_scrollFlags="scroll|enterAlways"
               app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
               app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />


           <ImageView
               android:layout_width="match_parent"
               android:layout_height="?attr/listPreferredItemHeight"
               android:layout_gravity="center"
               android:contentDescription="@string/app_name"
               android:scaleType="center"
               android:src="@drawable/ic_logo"
               app:layout_scrollFlags="scroll|enterAlways" />
     


<android.support.v7.widget.RecyclerView
               android:id="@+id/recyclerview_forecast"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               app:layout_behavior="@string/appbar_scrolling_view_behavior" />
       <!-- empty list -->
       <TextView
           android:id="@+id/recyclerview_forecast_empty"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:gravity="center_horizontal"
           android:paddingBottom="@dimen/activity_vertical_margin"
           android:paddingEnd="@dimen/activity_horizontal_margin"
           android:paddingLeft="@dimen/activity_horizontal_margin"
           android:paddingRight="@dimen/activity_horizontal_margin"
           android:paddingStart="@dimen/activity_horizontal_margin"
           android:paddingTop="@dimen/activity_vertical_margin"
           android:text="@string/empty_forecast_list" />


  


</FrameLayout>




4.than we create a CoordinatorLayout,and put the view that can scroll and  the view that can follow scroll into it


<!--
    Copyright (C) 2015 The Android Open Source Project


    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at


         http://www.apache.org/licenses/LICENSE-2.0


    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:orientation="vertical"
   android:layout_height="match_parent">


   <android.support.design.widget.CoordinatorLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent">

           <android.support.v7.widget.RecyclerView
               android:id="@+id/recyclerview_forecast"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
                />


       


           <android.support.v7.widget.Toolbar
               android:id="@+id/toolbar"
               android:layout_width="match_parent"
               android:layout_height="?attr/actionBarSize"
               android:elevation="0dp"
               
               app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
               app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />


           <ImageView
               android:layout_width="match_parent"
               android:layout_height="?attr/listPreferredItemHeight"
               android:layout_gravity="center"
               android:contentDescription="@string/app_name"
               android:scaleType="center"
               android:src="@drawable/ic_logo"
                />
      


       <!-- empty list -->
       <TextView
           android:id="@+id/recyclerview_forecast_empty"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:gravity="center_horizontal"
           android:paddingBottom="@dimen/activity_vertical_margin"
           android:paddingEnd="@dimen/activity_horizontal_margin"
           android:paddingLeft="@dimen/activity_horizontal_margin"
           android:paddingRight="@dimen/activity_horizontal_margin"
           android:paddingStart="@dimen/activity_horizontal_margin"
           android:paddingTop="@dimen/activity_vertical_margin"
           android:text="@string/empty_forecast_list" />


   </android.support.design.widget.CoordinatorLayout>


</FrameLayout>

5.
put all the view that want ot follow the scroll in to a Appbar layout


<!--
    Copyright (C) 2015 The Android Open Source Project


    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at


         http://www.apache.org/licenses/LICENSE-2.0


    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:orientation="vertical"
   android:layout_height="match_parent">


   <android.support.design.widget.CoordinatorLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent">

           <android.support.v7.widget.RecyclerView
               android:id="@+id/recyclerview_forecast"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
                />


       


           <android.support.design.widget.AppBarLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content">


           <android.support.v7.widget.Toolbar
               android:id="@+id/toolbar"
               android:layout_width="match_parent"
               android:layout_height="?attr/actionBarSize"
               android:elevation="0dp"
               app:layout_scrollFlags="scroll|enterAlways"
               app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
               app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />


           <ImageView
               android:layout_width="match_parent"
               android:layout_height="?attr/listPreferredItemHeight"
               android:layout_gravity="center"
               android:contentDescription="@string/app_name"
               android:scaleType="center"
               android:src="@drawable/ic_logo"
               app:layout_scrollFlags="scroll|enterAlways" />
       </android.support.design.widget.AppBarLayout>
      


       <!-- empty list -->
       <TextView
           android:id="@+id/recyclerview_forecast_empty"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:gravity="center_horizontal"
           android:paddingBottom="@dimen/activity_vertical_margin"
           android:paddingEnd="@dimen/activity_horizontal_margin"
           android:paddingLeft="@dimen/activity_horizontal_margin"
           android:paddingRight="@dimen/activity_horizontal_margin"
           android:paddingStart="@dimen/activity_horizontal_margin"
           android:paddingTop="@dimen/activity_vertical_margin"
           android:text="@string/empty_forecast_list" />


   </android.support.design.widget.CoordinatorLayout>


</FrameLayout>


6
put  app:layout_behavior="@string/appbar_scrolling_view_behavior" to the scrollable view


7.define the scroll flagto the view that inside the appbar layout
app:layout_scrollFlags="scroll|enterAlways"
mean :


  • scroll: this flag should be set for all views that want to scroll off the screen - for views that do not use this flag, they’ll remain pinned to the top of the screen
  • enterAlways: this flag ensures that any downward scroll will cause this view to become visible, enabling the ‘quick return’ pattern
  • enterAlwaysCollapsed: When your view has declared a minHeight and you use this flag, your View will only enter at its minimum height (i.e., ‘collapsed’), only re-expanding to its full height when the scrolling view has reached it’s top.
  • exitUntilCollapsed: this flag causes the view to scroll off until it is ‘collapsed’ (its minHeight) before exiting
One note: all views using the scroll flag must be declared before views that do not use the flag. This ensures that all views exit from the top, leaving the fixed elements behind.


here is the final cdeo:
<!--
    Copyright (C) 2015 The Android Open Source Project


    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at


         http://www.apache.org/licenses/LICENSE-2.0


    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:orientation="vertical"
   android:layout_height="match_parent">


   <android.support.design.widget.CoordinatorLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent">

           <android.support.v7.widget.RecyclerView
               android:id="@+id/recyclerview_forecast"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               app:layout_behavior="@string/appbar_scrolling_view_behavior" />


       <android.support.design.widget.AppBarLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content">


           <android.support.v7.widget.Toolbar
               android:id="@+id/toolbar"
               android:layout_width="match_parent"
               android:layout_height="?attr/actionBarSize"
               android:elevation="0dp"
               app:layout_scrollFlags="scroll|enterAlways"
               app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
               app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />


           <ImageView
               android:layout_width="match_parent"
               android:layout_height="?attr/listPreferredItemHeight"
               android:layout_gravity="center"
               android:contentDescription="@string/app_name"
               android:scaleType="center"
               android:src="@drawable/ic_logo"
               app:layout_scrollFlags="scroll|enterAlways" />
       </android.support.design.widget.AppBarLayout>


       <!-- empty list -->
       <TextView
           android:id="@+id/recyclerview_forecast_empty"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:gravity="center_horizontal"
           android:paddingBottom="@dimen/activity_vertical_margin"
           android:paddingEnd="@dimen/activity_horizontal_margin"
           android:paddingLeft="@dimen/activity_horizontal_margin"
           android:paddingRight="@dimen/activity_horizontal_margin"
           android:paddingStart="@dimen/activity_horizontal_margin"
           android:paddingTop="@dimen/activity_vertical_margin"
           android:text="@string/empty_forecast_list" />


   </android.support.design.widget.CoordinatorLayout>


</FrameLayout>


Some interesting thing~
if u want ot make a appbar have Elevation when scroll up,and no Elevation when all show,like this:

cau use :
computeVerticalScrollOffset can get how much di the Recycle view scroll relative to it orginal position


mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
           @TargetApi(Build.VERSION_CODES.LOLLIPOP)
           @Override
           public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
               super.onScrolled(recyclerView, dx, dy);
               Log.d("onScrolled", "onScrolled");


               if (mRecyclerView.computeVerticalScrollOffset() == 0) {
                   appBar.setElevation(0);
               } else {


                   int i = (int) appBar.getTargetElevation();
                   Log.d("onScrolled", i + "");
                   appBar.setElevation(i);
               }
           }