Android CollapsingToolbarLayout is a wrapper for Toolbar
which implements a collapsing app bar. It is designed to be used as a direct
child of a AppBarLayout. CollapsingToolbarLayout is the newly introduced in
Lollipop , using which you can create awesome scrolling effect.
The following sample will explain you how to achieve this CollapsingToolbarLayout
Build Gradle
file : build.gradle
dependencies {
compile
'com.android.support:design:23.0.1'
compile
'de.hdodenhof:circleimageview:2.2.0'
}
XML Layout
activity_main.xml
content_main.xml<?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:background="@color/color_grey_lite" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/id_app_bar_lay" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collaps_toolbar_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <LinearLayout android:layout_width="match_parent" android:layout_height="250dp" app:layout_collapseMode="parallax" android:orientation="vertical" android:gravity="center" android:layout_gravity="center" android:adjustViewBounds="true" android:background="@drawable/orange"> <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/profile_image" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="96dp" android:src="@drawable/app_icon" app:civ_border_width="2dp" app:civ_border_color="#FFFFFF"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textColor="@color/color_black" android:text="MrBrown's Android"/> </LinearLayout> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_collapseMode="pin" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" app:backgroundTint="@color/colorPrimary" app:srcCompat="@android:drawable/ic_dialog_map" /> </android.support.design.widget.CoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.NestedScrollView 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" android:paddingBottom="@dimen/cardview_margin" android:paddingLeft="@dimen/cardview_margin" android:paddingRight="@dimen/cardview_margin" android:paddingTop="@dimen/cardview_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <FrameLayout android:id="@+id/content_main_frame" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.CardView android:id="@+id/id_card_one" android:layout_width="match_parent" android:layout_height="100dp" app:cardCornerRadius="5dp" android:layout_marginBottom="10dp" app:cardBackgroundColor="@color/color_white"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="CARD VIEW" android:gravity="center" android:layout_gravity="center" android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textStyle="bold"/> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:id="@+id/id_card_two" android:layout_below="@+id/id_card_one" android:layout_width="match_parent" android:layout_height="100dp" app:cardCornerRadius="5dp" android:layout_marginBottom="10dp" app:cardBackgroundColor="@color/color_white"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="CARD VIEW" android:gravity="center" android:layout_gravity="center" android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textStyle="bold"/> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:id="@+id/id_card_three" android:layout_below="@+id/id_card_two" android:layout_width="match_parent" android:layout_height="100dp" app:cardCornerRadius="5dp" android:layout_marginBottom="10dp" android:background="@color/color_white"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="CARD VIEW" android:gravity="center" android:layout_gravity="center" android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textStyle="bold"/> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:id="@+id/id_card_four" android:layout_below="@+id/id_card_three" android:layout_width="match_parent" android:layout_height="100dp" app:cardCornerRadius="5dp" android:layout_marginBottom="10dp" android:background="@color/color_white"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="CARD VIEW" android:gravity="center" android:layout_gravity="center" android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textStyle="bold"/> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:id="@+id/id_card_five" android:layout_below="@+id/id_card_four" android:layout_width="match_parent" android:layout_height="100dp" app:cardCornerRadius="5dp" android:layout_marginBottom="10dp" app:cardBackgroundColor="@color/color_white"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="CARD VIEW" android:gravity="center" android:layout_gravity="center" android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textStyle="bold"/> </android.support.v7.widget.CardView> </RelativeLayout> </FrameLayout> </android.support.v4.widget.NestedScrollView>
Let us understand the XML Tags in
the above xml layout
1. CoordinatorLayout
A powerful FrameLayout that
specifies behavior for child views for various interactions. Allows floating views
to be anchored in layout.
2. AppBarLayout
Is essentially a LinearLayout
(vertical). It helps respond to its children’s scroll events (scroll gestures).
Responsible for implementing many features of material design’s app bar.
Depends heavily on being used as a direct child within CoordinatorLayout.
3. CollapsingToolbarLayout
Wrapper for Toolbar that makes
the header image collapse into the Toolbar adjusting its title size.What’s left
is the ImageView which holds our actual header’s image and Toolbar which we’re
familiar with.
4. NestedScrollView
It’s an special scroll view for
the smooth scrolling effect, inside this place the desired content . Here in
this example will add several Cards as its children.
Flags include :
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 .
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.
Collapse Mode
- Parallax scrolling with the ImageView is achieved by simply setting its layout_collapseMode to parallax.
- The Toolbar must use pin as its collapseMode because we want the Toolbar to persist and remain on top as the user scrolls down.
MainActivity.java
To make the toolbar color
transparent on non-collapse
appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override public void onStateChanged(AppBarLayout appBarLayout, State state) { int toolbarBackground = (state == AppBarStateChangeListener.State.COLLAPSED) ? R.color.colorPrimary : R.color.color_transparent; toolbar.setBackgroundColor(ContextCompat.getColor(MainActivity.this, toolbarBackground)); } });
To make actionbar title only on
collapse
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { if (scrollRange == -1) { scrollRange = appBarLayout.getTotalScrollRange(); } if (scrollRange + verticalOffset == 0) { collapsingToolbarLayout.setTitle(getResources().getString(R.string.app_name)); isShow = true; } else if(isShow) { collapsingToolbarLayout.setTitle(" "); isShow = false; } } });
MainActivity.java
public class MainActivity extends AppCompatActivity { private AppBarLayout appBarLayout; private Toolbar toolbar; CollapsingToolbarLayout collapsingToolbarLayout; boolean isShow = true; int scrollRange = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collaps_toolbar_layout); appBarLayout = (AppBarLayout) findViewById(R.id.id_app_bar_lay); toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); setTitle(getResources().getString(R.string.app_name)); collapsingToolbarLayout.setTitle(getResources().getString(R.string.app_name)); collapsingToolbarLayout.setContentScrimColor(getResources().getColor(R.color.color_yellow)); /*to make the toolbar color transparent on non-collapse*/ appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { @Override public void onStateChanged(AppBarLayout appBarLayout, State state) { int toolbarBackground = (state == AppBarStateChangeListener.State.COLLAPSED) ? R.color.colorPrimary : R.color.color_transparent; toolbar.setBackgroundColor(ContextCompat.getColor(MainActivity.this, toolbarBackground)); } }); /*to make actionbar title only on collapse*/ appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { if (scrollRange == -1) { scrollRange = appBarLayout.getTotalScrollRange(); } if (scrollRange + verticalOffset == 0) { collapsingToolbarLayout.setTitle(getResources().getString(R.string.app_name)); isShow = true; } else if(isShow) { collapsingToolbarLayout.setTitle(" "); isShow = false; } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); Drawable icon1 = menu.getItem(0).getIcon(); // change 0 with 1,2 ... icon1.mutate(); icon1.setColorFilter(getResources().getColor(R.color.color_white), PorterDuff.Mode.SRC_IN); Drawable icon2 = menu.getItem(1).getIcon(); icon2.mutate(); icon2.setColorFilter(getResources().getColor(R.color.color_white), PorterDuff.Mode.SRC_IN); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); //your click functions on actionbar icon here... return super.onOptionsItemSelected(item); } }
AppBarStateChangeListener.java
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { public enum State { EXPANDED, COLLAPSED, IDLE } private State mCurrentState = State.IDLE; @Override public void onOffsetChanged(AppBarLayout appBarLayout, int i) { if (i == 0) { if (mCurrentState != State.EXPANDED) { onStateChanged(appBarLayout, State.EXPANDED); } mCurrentState = State.EXPANDED; } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) { if (mCurrentState != State.COLLAPSED) { onStateChanged(appBarLayout, State.COLLAPSED); } mCurrentState = State.COLLAPSED; } else { if (mCurrentState != State.IDLE) { onStateChanged(appBarLayout, State.IDLE); } mCurrentState = State.IDLE; } } public abstract void onStateChanged(AppBarLayout appBarLayout, State state); }
_________________________________________________________________________________
Sourcecode:CollapsingToolbarLayoutSample.zip
Happy Coding...
Comments
Post a Comment