特別喜歡稀土掘金我的界面的樣子,那咱們就來看看如何實現這個效果吧,要想實現這個效果,確定須要的是Material Design風格,那就須要學會使用如下控件:CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout,Toolbar,TabLayout等,若是你作出這個效果來,那這些控件你就基本掌握了。html
介紹以前,咱們先來看看效果對比圖:android
CoordinatorLayout做爲「super-powered FrameLayout」基本實現兩個功能:git
做爲頂層佈局程序員
調度協調子佈局github
CoordinatorLayout使用新的思路經過協調調度子佈局的形式實現觸摸影響佈局的形式產生動畫效果。CoordinatorLayout經過設置子View的 Behaviors來調度子View。系統(Support V7)提供了AppBarLayout.Behavior, AppBarLayout.ScrollingViewBehavior, FloatingActionButton.Behavior, SwipeDismissBehavior<V extends View> 等。web
使用CoordinatorLayout須要在Gradle加入Support Design Library:segmentfault
compile 'com.android.support:design:22.2.1'
具體的怎麼協調子控件的,建議你們看下面的參考文章,寫的很是好,看完你就基本明白了:
https://segmentfault.com/a/1190000005024216?utm_source=Weibo&utm_medium=shareLink&utm_campaign=socialShare&from=singlemessage&isappinstalled=0微信
AppBarLayout 是一個豎直排列的線性佈局,它實現了不少Material Design風格app bar的設計概念,換句話說就是滾動手勢。app
在AppBarLayout裏面的View,經過app:layout_scrollFlags屬性來控制,滾動時候的表現。其中有4種Flag的類型。ide
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
咱們的例子中用的是 scroll 和 exitUntilCollapsed。
翻譯的比較爛,英文好的,看上面的英文解釋。
Scroll: 表示向下滾動時,這個View會被滾出屏幕範圍直到隱藏.
enterAlways: 表示向上滾動時,這個View會隨着滾動手勢出現,直到恢復原來的位置.
enterAlwaysCollapsed: 顧名思義,這個flag定義的是什麼時候進入(已經消失以後什麼時候再次顯示)。假設你定義了一個最小高度(minHeight)同時enterAlways也定義了,那麼view將在到達這個最小高度的時候開始顯示,而且從這個時候開始慢慢展開,當滾動到頂部的時候展開完。
exitUntilCollapsed: 一樣顧名思義,這個flag時定義什麼時候退出,當你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失。
因此咱們就在AppBarLayout裏面的CollapsingToolbarLayout進行了以下設置:
<android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar_layout" android:layout_width="match_parent" android:layout_height="280dp" android:fitsSystemWindows="true" app:collapsedTitleTextAppearance="@style/ToolBarTitleText" app:contentScrim="#46a8ba" app:expandedTitleMarginEnd="48dp" app:expandedTitleMarginStart="48dp" app:expandedTitleTextAppearance="@style/transparentText" app:layout_scrollFlags="scroll|exitUntilCollapsed"> </android.support.design.widget.CollapsingToolbarLayout>
記住:咱們剛纔上面也說了AppBarLayout是一個豎直方向的線性佈局,若是裏面包含多個子View時,要想有摺疊動畫效果,必須把帶有scroll flag的view放在前面,這樣收回的view才能讓正常退出,而固定的view繼續留在頂部。
CollapsingToolbarLayout做用是提供了一個能夠摺疊的Toolbar,它繼承至FrameLayout,給它設置layout_scrollFlags,它能夠控制包含在CollapsingToolbarLayout中的控件在響應layout_behavior事件時做出相應的scrollFlags滾動事件(移除屏幕或固定在屏幕頂端)。它是設計用於直接AppBarLayout的子視圖。
CollapsingToolbarLayout的子View中能夠設置這兩個屬性
ayout_collapseMode (摺疊模式) - 有兩個值:
pin - 設置爲這個模式時,當CollapsingToolbarLayout徹底收縮後,Toolbar還能夠保留在屏幕上。
parallax - 設置爲這個模式時,在內容滾動時,CollapsingToolbarLayout中的View(好比ImageView)也能夠同時滾動,實現視差滾動效果,一般和layout_collapseParallaxMultiplier(設置視差因子)搭配使用。
layout_collapseParallaxMultiplier(視差因子) - 設置視差滾動因子,值爲:0~1。
app:collapsedTitleTextAppearance 這是在收縮時Title文字特色外形的設置
app:expandedTitleTextAppearance 同理這是在展開時Title文字特色外形的設置
app:contentScrim 這是toolbar 標題工具欄停留在頂部時候背景的設置
app:expandedTitleMarginStart 設置擴張時候(尚未收縮時)title向左填充的距離
app:expandedTitleMarginEnd 這個同理是收縮結束時向左填空的距離
其餘的就不一一介紹了,具體的去查看API文檔便可獲知。
我在作這裏的時候遇到一個問題,那就是CollapsingToolbarLayout裏的Title的問題,通常默認是顯示的,即便你不寫,它也有會一個默認值一直顯示在那裏,等摺疊收縮完的時候,停留在標題工具欄上。怎麼消除這個默認值呢?怎麼知道收縮完成了,再把這個值設置出來呢?這裏我對AppBarLayout設置了一個監聽,它有一個監聽方法:addOnOffsetChangedListener監聽摺疊收縮的位移。以下:
app_bar_layout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { if (verticalOffset <= -head_layout.getHeight() / 2) { mCollapsingToolbarLayout.setTitle("澀郎"); } else { mCollapsingToolbarLayout.setTitle(" "); } } });
Toolbar 是在 Android 5.0 開始推出的一個 Material Design 風格的導航控件 ,Google 很是推薦你們使用 Toolbar 來做爲Android客戶端的導航欄,以此來取代以前的 Actionbar 。與 Actionbar 相比,Toolbar 明顯要靈活的多。它不像 Actionbar 同樣,必定要固定在Activity的頂部,而是能夠放到界面的任意位置。除此以外,在設計 Toolbar 的時候,Google也留給了開發者不少可定製修改的餘地,這些可定製修改的屬性在API文檔中都有詳細介紹,如:
設置導航欄圖標;
設置App的logo;
支持設置標題和子標題;
支持添加一個或多個的自定義控件;
支持Action Menu;
Toolbar的具體使用方法,我在這裏就不過多的贅述了,學習的點太多了,簡單介紹完了,我給你們推薦兩篇參考學習使用的文章就好了,寫的很詳細和完整,以前咱們公衆號也推送過D_clock寫的文章。
學習參考文章:
毫無疑問,TabLayout也是Material Design設計風格,固然也是5.0之後出來的。TabLayout提供一個水平佈局來顯示選項卡。TabLayout通常都是配合ViewPager一塊兒來使用。TabLayout設置Tab標籤有兩種方法以下:
TabLayout tabLayout = ...; tabLayout.addTab(tabLayout.newTab().setText("Tab 1")); tabLayout.addTab(tabLayout.newTab().setText("Tab 2")); tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
<android.support.design.widget.TabLayout android:layout_height="wrap_content" android:layout_width="match_parent"> <android.support.design.widget.TabItem android:text="@string/tab_text"/> <android.support.design.widget.TabItem android:icon="@drawable/ic_android"/> </android.support.design.widget.TabLayout>
使用TabLayout有個坑,這個坑若是通常用戶不知道,解決起來比較麻煩,固然看到這篇文章的人有福了,由於你找到解決方法。
若是設計的需求不要求選項卡在切換時附帶有圖標的切換效果,僅僅文字的顏色發生變化以響應用戶的點擊事件,那麼TabLayout和ViewPager創建聯繫能夠用官方提供的方法,它能夠作到交互雙向聯動,也就是點擊tab,viewpager就會去變更,滑動viewpager,tab也會自動變。相互創建聯繫的方法以下:
setupWithViewPager(ViewPager viewPager)
若是選項卡里帶有圖標或者僅僅只有圖標時就麻煩了,那個選項卡會變得什麼都沒有了。解決方法其實很簡單就是不使用上面的方法,並且這樣用:
viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(tabLayout)); tabLayout.setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager));
其實這個setupWithViewPager(ViewPager viewPager)方法,跟進到源碼裏,你能夠看到,就是調用了上面的兩種方式。
到這裏基本就講完了,所有的佈局代碼以下:
<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" tools:context=".MainActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar_layout" android:layout_width="match_parent" android:layout_height="280dp" android:fitsSystemWindows="true" app:collapsedTitleTextAppearance="@style/ToolBarTitleText" app:contentScrim="#46a8ba" app:expandedTitleMarginEnd="48dp" app:expandedTitleMarginStart="48dp" app:expandedTitleTextAppearance="@style/transparentText" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <LinearLayout android:id="@+id/head_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layout_collapseMode="pin" app:layout_collapseParallaxMultiplier="0.7"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:padding="20dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="澀郎" android:textColor="#ffffff" android:textSize="16sp" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:text="Android開發工程師 @ 非著名程序員" android:textColor="#ffffff" android:textSize="13sp" android:textStyle="bold" /> </LinearLayout> <ImageView android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:scaleType="centerCrop" android:src="@mipmap/bg" /> </RelativeLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="40dp" android:ellipsize="end" android:maxLines="2" android:text="關注我(微博@澀郎,微信公衆號:非著名程序員),我與你閒扯技術大話,笑談科技人生。以幽默詼諧的態度,面對乏味無聊的技術,用扯淡的方式,分享技術的內涵。談的是技術,更是咱們的人生。" android:textColor="#ffffff" android:textSize="12sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:padding="20dp"> <LinearLayout android:id="@+id/one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="分享" android:textColor="#ffffff" android:textSize="12sp" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="50篇" android:textColor="#ffffff" android:textSize="12sp" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:id="@+id/two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:layout_toRightOf="@id/one" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="得到收藏" android:textColor="#ffffff" android:textSize="12sp" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="3000次" android:textColor="#ffffff" android:textSize="12sp" android:textStyle="bold" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:layout_toRightOf="@id/two" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="被閱讀" android:textColor="#ffffff" android:textSize="12sp" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="60000次" android:textColor="#ffffff" android:textSize="12sp" android:textStyle="bold" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:background="@drawable/setting_bg" android:paddingBottom="3dp" android:paddingLeft="6dp" android:paddingRight="6dp" android:paddingTop="3dp" android:text="設置" android:textColor="#ffffff" android:textSize="12sp" /> </RelativeLayout> </LinearLayout> <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/ThemeOverlay.AppCompat.Light" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> </android.support.design.widget.CollapsingToolbarLayout> <android.support.design.widget.TabLayout android:id="@+id/toolbar_tab" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_gravity="bottom" android:background="#ffffff" android:fillViewport="false" app:layout_scrollFlags="scroll" app:tabIndicatorColor="#0835f8" app:tabIndicatorHeight="2.0dp" app:tabSelectedTextColor="#0835f8" app:tabTextColor="#ced0d3"> <android.support.design.widget.TabItem android:layout_width="match_parent" android:layout_height="match_parent" android:icon="@drawable/tab_selector" /> <android.support.design.widget.TabItem android:layout_width="match_parent" android:layout_height="match_parent" android:text="分享" /> <android.support.design.widget.TabItem android:layout_width="match_parent" android:layout_height="match_parent" android:text="收藏" /> <android.support.design.widget.TabItem android:layout_width="match_parent" android:layout_height="match_parent" android:text="關注" /> <android.support.design.widget.TabItem android:layout_width="match_parent" android:layout_height="match_parent" android:text="關注者" /> </android.support.design.widget.TabLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:scrollbars="none" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v4.view.ViewPager android:id="@+id/main_vp_container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
package com.loonggg.coordinatorlayoutdemo; import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; import android.support.design.widget.TabLayout; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.LinearLayout; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private LinearLayout head_layout; private TabLayout toolbar_tab; private ViewPager main_vp_container; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AppBarLayout app_bar_layout = (AppBarLayout) findViewById(R.id.app_bar_layout); Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(mToolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); head_layout = (LinearLayout) findViewById(R.id.head_layout); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.bg); head_layout.setBackgroundDrawable(new BitmapDrawable(BlurUtil.fastblur(this, bitmap, 180))); //使用CollapsingToolbarLayout必須把title設置到CollapsingToolbarLayout上,設置到Toolbar上則不會顯示 final CollapsingToolbarLayout mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout); mCollapsingToolbarLayout.setContentScrim(new BitmapDrawable(BlurUtil.fastblur(this, bitmap, 180))); app_bar_layout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { if (verticalOffset <= -head_layout.getHeight() / 2) { mCollapsingToolbarLayout.setTitle("澀郎"); } else { mCollapsingToolbarLayout.setTitle(" "); } } }); Toolbar.OnMenuItemClickListener onMenuItemClick = new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { String msg = ""; switch (menuItem.getItemId()) { case R.id.webview: msg += "博客跳轉"; break; case R.id.weibo: msg += "微博跳轉"; break; case R.id.action_settings: msg += "設置"; break; } if (!msg.equals("")) { Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } return true; } }; mToolbar.setOnMenuItemClickListener(onMenuItemClick); toolbar_tab = (TabLayout) findViewById(R.id.toolbar_tab); main_vp_container = (ViewPager) findViewById(R.id.main_vp_container); ViewPagerAdapter vpAdapter = new ViewPagerAdapter(getSupportFragmentManager(), this); main_vp_container.setAdapter(vpAdapter); main_vp_container.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(toolbar_tab)); toolbar_tab.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(main_vp_container)); //tablayout和viewpager創建聯繫爲何不用下面這個方法呢?本身去研究一下,可能收穫更多 //toolbar_tab.setupWithViewPager(main_vp_container); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } }
源碼下載地址:https://github.com/loonggg/CoordinatorLayoutDemo
記得star一下哦。
公衆號:非著名程序員(smart_android) 歡迎你們關注,天天一篇原創技術文章。