I really like the folding of the toolbar in Material Design, which is used for the Bilibili Android client video details page. In the second part of this article we understand the use of CollapsingToolbarLayout by simply imitating the Bilibili video detail page implementation. In the third part of the article CollapsingToolbarLayout and TabLayout are introduced.
Those of you who have the basics can skip the first part.
I. Introduction of related basic attributes
Android Studio has an Activity template called ScrollingActivity, which implements a simple collapsible toolbar, and we added this template to the project.
The layout code for ScrollingActivity is as follows
<? The 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" xmlns:tools="http://schemas.android.com/tools" 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="@dimen/app_bar_height" android:fitsSystemWindows="true" 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:layout_scrollFlags="scroll|exitUntilCollapsed"> <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" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/text_margin" android:text="@string/large_text" /> </android.support.v4.widget.NestedScrollView> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" app:layout_anchor="@id/app_bar" app:layout_anchorGravity="bottom|end" /> </android.support.design.widget.CoordinatorLayout>Copy the code
AppBarLayout is an AppBar layout that supports scrolling gestures in response (such as toolbar roll-out or roll-in screen), while CollapsingToolbarLayout is specifically used to implement a layout in which different elements within a sublayout respond to scrolling details.
AppBarLayout combination of rolling layout (Recyclerview, NestedScrollView, etc.) need to set app:layout_behavior=”@string/ APPbar_scrolling_view_behavior “(above) Code set by the NestedScrollView control. Without this setting, AppBarLayout will not respond to scroll events for scrolling layouts.
CollapsingToolbarLayout has a slide bug when used with a ScrollView, note that NestedScrollView is used instead of a ScrollView in the CollapsingToolbarLayout view.
The child layout of AppBarLayout has 5 scroll identities (as in the app:layout_scrollFlags property in CollapsingToolbarLayout above) :
- Scroll: Associates the layout with the scroll time. This identifier is set before any other identifier, without which the layout will not scroll and the other identifier Settings will not be valid.
- EnterAlways: Any scroll down operation makes this layout visible. This identifier is often referred to as the “quick return” mode.
- EnterAlwaysCollapsed: Suppose you define a minimum height and enterAlways is defined, the view will start at this minimum height and expand slowly from this point until it rolls to the top.
- ExitUntilCollapsed: When you define a minHeight, the layout collapses when the roll reaches the minimum height.
- Snap: When a scrolling event ends, if the view is partially visible, it will be rolled to shrink or expand. For example, if only the bottom 25% of the view is displayed, it collapses. Conversely, if the bottom 75% of it is visible, it will be fully expanded.
CollapsingToolbarLayout CollapsingToolbarLayout can be set in app:contentScrim to collapse the toolbar layout color, or in app:statusBarScrim to collapse the status bar color. The default contentScrim is the color value of colorPrimary and statusBarScrim is the color value of colorPrimaryDark. This is going to come in later.
CollapsingToolbarLayout children CollapsingToolbarLayout has 3 collapse modes (App set in the Toolbar :layout_collapseMode)
- Off: This is the default, the layout will display normally, no folding behavior.
- Pin: CollapsingToolbarLayout Once collapsed, the layout will be fixed at the top.
- Parallax: CollapsingToolbarLayout
When CollapsingToolbarLayout child layout setting the parallax model, we can also through the app: layout_collapseParallaxMultiplier set parallax scrolling factor, the value is: 0 ~ 1.
The FloatingActionButton control is anchored below The AppBarLayout via the app: Layout_anchor setting. FloatingActionButton source code has a Behavior method, when the AppBarLayout shrinks, FloatingActionButton will change accordingly. For CoordinatorLayout and Behavior, I will study it with you in my next article.
You can create a new ScrollingActivity template and try it out.
Second, imitate bilibili client video details page
Let’s analyze the original interface.
Initially the view CollapsingToolbarLayout is expanded and the video cover is displayed in the CollapsingToolbarLayout. We scroll up the page and collapse the ToolbarLayout. When the AppBarLayout is completely collapsed the video av number is hidden, showing a small TV icon and “Play Now”. Click to fully expand the AppBarLayout and collapse the ToolbarLayout child collapses from ImageView into the video pop-up player.
Er… Danmu player…
B station very early open source a bullet curtain engine, but also a crazy dazzle of the name of the bomb curtain called “fiery Flame” (a look is the two-dimensional program ape works →_→), the source on Github, the project named DanmakuFlameMaster.
Let’s look at the finished layout first.
<? The 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:id="@+id/coordinatorLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="@dimen/app_bar_height" android:fitsSystemWindows="true" 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" app:contentScrim="?attr/colorPrimary" app:statusBarScrim="@android:color/transparent" app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> <! <ImageView android:id="@+id/ ImageView "Android :layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@drawable/diqiu" App: layout_collapseMode = "parallax" app: layout_collapseParallaxMultiplier = "0.7" android: fitsSystemWindows = "true" / > <! <FrameLayout android:id="@+id/video_danmu" Android :layout_width="match_parent" Android: layout_height = "match_parent" app: layout_collapseMode = "parallax" app: layout_collapseParallaxMultiplier = "0.7" android:fitsSystemWindows="true" android:visibility="gone"> <VideoView android:id="@+id/videoview" android:layout_width="match_parent" android:layout_height="match_parent" /> <! - bi li bi li barrage of open source control - > < master. Flame. Danmaku. UI. Widget. DanmakuView android: id = "@ + id/danmaku" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> <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" > <! - custom take pictures immediately play button - > <. Android support. V7. Widget. ButtonBarLayout android: id = "@ + id/playButton" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:visibility="gone"> <ImageView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:src="@mipmap/ic_play_circle_filled_white_48dp"/> <TextView Android :layout_width="wrap_content" Android: Layout_height ="wrap_content" Android :textColor="# FFFFFF "Android :text=" Play immediately" android:layout_gravity="center_vertical" /> </android.support.v7.widget.ButtonBarLayout> </android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_scrolling" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/fab_margin" android:src="@mipmap/ic_play_circle_filled_white_48dp" app:layout_anchor="@id/app_bar" app:layout_anchorGravity="bottom|end" /> </android.support.design.widget.CoordinatorLayout>Copy the code
I changed the color value of colorPrimary to “girl fan” of station B, and the playing icon was found from the Internet.
<color name="colorPrimary">#FA7199</color>Copy the code
Since we want to implement an immersive status bar, we need to set the entire activity to status bar transparent mode first. Then in the layout file, so as to realize the control of immersion in the CollapsingToolbarLayout set android: fitsSystemWindows = “true”, if not set, then the layout will be located below the status bar, did not extend to the status bar.
The layout is not complex, the next thing to achieve the function of no bullet screen playback.
We need to listen for the collapsed and expanded state of the CollapsingToolbarLayout. Oh my God, there is no official solution. .
CollapsingToolbarLayout the OnOffsetChangedListener interface that implements AppBarLayout According to the offset of AppBarLayout to realize the parallax movement of sub-layout and title and display of ContentScrim and StatusBarScrim. Then we can also by calling AppBarLayout addOnOffsetChangedListener method to monitor AppBarLayout displacement, judge CollapsingToolbarLayout state.
Start by writing an enumeration that defines CollapsingToolbarLayout expansion, collapse, and middle states.
private CollapsingToolbarLayoutState state;
private enum CollapsingToolbarLayoutState {
EXPANDED,
COLLAPSED,
INTERNEDIATE
}Copy the code
Then listen on AppBarLayout, determine the state of CollapsingToolbarLayout and implement the corresponding logic in CollapsingToolbarLayout.
In order to make the status more intuitive, I modified the title together with the status value.
When CollapsingToolbarLayout is in view, call methods such as setTitle() of the Toolbar in CollapsingToolbarLayout will have no effect. We need to modify the toolbar in CollapsingToolbarLayout by calling methods such as setTitle(). CollapsingToolbarLayout (˙-˙)
AppBarLayout app_bar=(AppBarLayout)findViewById(R.id.app_bar); app_bar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { if (verticalOffset == 0) { if (state ! = CollapsingToolbarLayoutState.EXPANDED) { state = CollapsingToolbarLayoutState.EXPANDED; / / modify state marked collapsingToolbarLayout. SetTitle (" EXPANDED "); / / set the title for the EXPANDED}} else if (Math. Abs (verticalOffset) > = appBarLayout. GetTotalScrollRange ()) {if (the state! = CollapsingToolbarLayoutState.COLLAPSED) { collapsingToolbarLayout.setTitle(""); // Set title not to display playbutton.setvisibility (view.visible); / / play button hidden state = CollapsingToolbarLayoutState. COLLAPSED; }} else {if (state! = CollapsingToolbarLayoutState.INTERNEDIATE) { if(state == CollapsingToolbarLayoutState.COLLAPSED){ playButton.setVisibility(View.GONE); / / by folding into a intermediate state hide the play button.} collapsingToolbarLayout setTitle (" INTERNEDIATE "); / / set the title for INTERNEDIATE state = CollapsingToolbarLayoutState. INTERNEDIATE; // Change the status to the middle}}}});Copy the code
Then set a listener on the play button, which calls the setExpanded(True) method of AppBarLayout to expand the toolbar.
The title on the CollapsingToolbarLayout client is fixed and can be achieved by calling the setTitleEnabled(false) method in the CollapsingToolbarLayout.
Video playback, call NestedScrollView setNestedScrollingEnabled (false) method can not make AppBarLayout response scroll event.
Careful friends may have noticed that bilibili app has added a gradient opacity layer to prevent the light color of the video cover image from affecting the display of status bar information.
Implementing the gradient mask layer is simple. First, a new XML file named Gradient was created in the res/ Drawable folder, with the following code:
<? The XML version = "1.0" encoding = "utf-8"? > <shape xmlns:android="http://schemas.android.com/apk/res/android"> <gradient android:startColor="#33000000" android:endColor="#00000000" android:angle="270" /> </shape>Copy the code
In the Shape node, you can use Android: Shape to set the shape. The default is rectangle. The value of Angle in the gradient node is 270 from top to bottom, 0 from left to right, and 90 from bottom to top. The starting color #33000000 is black with 20% opacity, and #00000000 indicates full transparency.
Then add a custom view under the ImageView code in the CollapsingToolbarLayout with the background set to the above gradient effect.
<View
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/gradient"
android:fitsSystemWindows="true"
/>Copy the code
Generally, the height of the status bar is about 20dp. I set the height to 40DP in order to make the gradient effect more natural and not affect mei piece (ZI) too much. (The status bar has a cameo appearance, and the girl has a nice cameo appearance)
I omitted the implementation of bullet screen playback. Next, I only need to write the hiding of cover picture, the initialization and playback logic of video and bullet screen control in the monitor of play button, and write other corresponding logic according to whether the video is playing in the three state monitor of AppBarLayout. Interested friends can download bilibili “flamemaster” source DanmakuFlameMaster to play.
A prompt control similar to Snackbar will appear in station B after you click “follow up” or “throw a coin”. You can use Snackbar through my last article. I have no time to explain. Android Snackbar fancy use guide to achieve, welcome interested friends to see.
It’s not that I’m too lazy to code, really… Gay friend: Hurry up, open black. Me: Wait for me, come right now! \ \ (≧ del ≦) /)
3. CollapsingToolbarLayout TabLayout
CollapsingToolbarLayout also works well in combination with TabLayout.
Look at the code in CollapsingToolbarLayout
<? The 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" xmlns:tools="http://schemas.android.com/tools" 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="250dp" android:fitsSystemWindows="true" 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" app:titleEnabled="false" android:fitsSystemWindows="true" app:contentScrim="@color/colorPrimary" app:statusBarScrim="@android:color/transparent" app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> <ImageView android:id="@+id/imageview" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" Android: adjustViewBounds = "true" app: layout_collapseMode = "parallax" app: layout_collapseParallaxMultiplier = "0.7" android:fitsSystemWindows="true" android:src="@drawable/girl2"/> <View android:layout_width="match_parent" android:layout_height="40dp" android:background="@drawable/gradient" android:fitsSystemWindows="true" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="96dp" android:minHeight="?attr/actionBarSize" android:gravity="top" app:layout_collapseMode="pin" app:title="hello" app:popupTheme="@style/AppTheme.PopupOverlay" app:titleMarginTop="15dp" /> <android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="45dp" android:layout_gravity="bottom" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpage" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </android.support.v4.view.ViewPager> </android.support.design.widget.CoordinatorLayout>Copy the code
TabLayout does not set app:layout_collapseMode, which will not collapse when CollapsingToolbarLayout collapses.
CollapsingToolbarLayout collapses as the Toolbar height, so we need to expand the Toolbar height to give TabLayout space so that the collapsed TabLayout doesn’t overlap the Toolbar.
As the Toolbar increases in height, the title moves down accordingly. The Android :gravity=”top” method places the title of the Toolbar above the Toolbar, then adjust the title height from the top via app:titleMarginTop so that the Toolbar looks the same as it did before.
CollapsingToolbarLayout can also be used in the CollapsingToolbarLayout with the Palette, but I feel that in practice the CollapsingToolbarLayout may not be exactly what you want because the picture in the CollapsingToolbarLayout is not clear.
If you are interested, check the usage in the Palette.
That’s it. [] ~ (~ ▽ ~) ~ *