coordinatorlayout_一篇文章学会Coordinatorlayout+AppbarLayout
點擊上方藍字關注???
來源:? 奔跑吧李博
https://www.jianshu.com/p/cd93da2b7a24
前言
現如今,折疊式布局在App中相當常見,給人一種科技感,充滿良好的用戶體驗。Coordinatorlayout+AppbarLayout+CollapsingToolbarLayout這三個臭皮匠聯合起來用千變萬化,啊,我重來沒有見過如此超凡脫俗之效果。
網上大多來不來就將這仨揉在一起,布局也是直接全部嵌套完成搬上來,但是你真的理解它們之間的協作關系嗎?相互聯動的原理是什么呢?一個個控件都沒整明白寫出這個功能也沒有意義呀。那我就一個一個拆開來講,分別來個功能,再一個接一個拼接。接下來,讓我們一起走進它們的內心世界。
先上效果圖:
ToolBar(因為涉及到,所以講一下)
從Android3.0后出現ActionBar,但是這效果,誰用誰知道啊。顏色不好看不說,布局也是無法訂制,都不如自定義ActionBar的好。使用方式:1.首先在Activity主題里面將默認Actionbar改為NoActionbar
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">2.綁定toolbar ,setSupportActionBar(toolbar) 設置toolbar為標題欄3.設置常用屬性:
toolbar.setNavigationIcon(int resId);toolbar.setLogo(int resId);toolbar.setTitle("");toolbar.setSubtitle("");toolbar.setOnMenuItemClickListener(Toolbar.OnMenuItemClickListener listener);4.引用菜單
@Overridepublic boolean onCreateOptionsMenu(Menu menu) {//引入options菜單getMenuInflater().inflate(R.menu.menu,menu);return true;
}
5.在menu文件夾中設置菜單
xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><item android:id="@+id/menu_1"android:title="菜單1"android:icon="@mipmap/make_music_voice_changer_female"app:showAsAction="collapseActionView"/><item android:id="@+id/menu_2"android:title="菜單2"android:icon="@mipmap/make_music_voice_changer_female"app:showAsAction="collapseActionView"/><item android:id="@+id/menu_3"android:title="菜單3"android:icon="@mipmap/make_music_voice_changer_female"app:showAsAction="collapseActionView"/><item android:id="@+id/menu_4"android:title="菜單4"android:icon="@mipmap/make_music_voice_changer_female"app:showAsAction="collapseActionView"/>menu>或者直接在布局中添加子view使用
<android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin"app:popupTheme="@style/ThemeOverlay.AppCompat.Light" ><TextViewandroid:id="@+id/tv1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="返回"android:textSize="13sp"android:textColor="@android:color/white" /><TextViewandroid:id="@+id/tv2"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="right"android:layout_centerHorizontal="true"android:layout_marginRight="6dp"android:gravity="center"android:padding="4dp"android:textColor="#fff"android:textSize="14sp"android:text="菜單"/>android.support.v7.widget.Toolbar>ifRoom ? ?會顯示在Item中,空間不足會將后面item收起來,如果已經有4個或者4個以上的Item時會隱藏在溢出列表中。
never ? ?永遠不會顯示。只會在藏出列表中顯示,而且只顯示標題,所以在定義item的時候,最好把標題都帶上。
always ? ?無論是否超出空間,總會顯示。
withText ? ?withText值示意Action bar要顯示文本標題。Action bar會盡可能的顯示這個標題,但是,如果圖標有效并且受到Action bar空間的限制,文本標題有可能顯示不全。
collapseActionView ? ? ?聲明了這個操作視窗應該被折疊到一個按鈕中,當用戶選擇這個按鈕時,這個操作視窗展開。否則,這個操作視窗在默認的情況下是可見的,并且即便在用于不適用的時候,也要占據操作欄的有效空間。
例如效果:
Coordinatorlayout
定義:is a super-powered Framelayout
是一個超級有力量的爸爸,官方給的定義就足以證明它的強大。
作用:協調子view的相互關系,比如位置、大小,就像有幾個調皮孩子的爸爸,要管管孩子的行為。
Behavior:
打開Coordinatorlayout看,Behavior是CoordinatorLayout的一個泛型抽象內部類(這么長累不累呀),所以給子view添加layout_behavior屬性是來自于它。
我寫了一個例子來理解CoordinatorLayout的工作原理:
這是一個大叔跟隨女孩的故事
s:tools="http://schemas.android.com/tools"xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/coordinatorLayout"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.example.md.mdview.CoordinatorLayoutActivity">
android:id="@+id/view_girl"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginLeft="200dp"
android:background="@mipmap/make_music_voice_changer_female" />
android:id="@+id/view_uncle"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@mipmap/make_music_voice_changer_uncle"
app:layout_behavior="com.example.md.mdview.RunBehavior"/>
布局:兩個子view,操作viewgirl,viewuncle也會相應跟著走,這就要寫一個聯動關系,用自定義Behavior實現
public class RunBehavior extends CoordinatorLayout.Behavior<View>{public RunBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {int top = dependency.getTop();int left = dependency.getLeft();
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) child.getLayoutParams();
params.topMargin = top - 400;
params.leftMargin = left;
child.setLayoutParams(params);return true;
}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {return true;
}
}
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) ?方法:
根據條件過濾判斷返回值,返回true聯動,返回flase不聯動,即behavior不生效
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency)
當 dependency這個哥哥發生變化時, 另一個child弟弟也要跟著去玩
一個view根據另一個view的變化而變化, ?dependency被 child監聽
功能是child的y值永遠比dependency大400像素(廢話,還用說嗎)
這里一定要寫上帶參數的構造方法,因為coordinatorlayout是根據反射(所以是包名.類名路徑)獲取這個behavior,是從這個構造方法獲得對象的,否則會報
@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:params.leftMargin = (int) (event.getX() - viewGirl.getMeasuredWidth() / 2);params.topMargin = (int) (event.getY() - viewGirl.getMeasuredHeight() / 2);viewGirl.setLayoutParams(params);break;case MotionEvent.ACTION_MOVE:params.leftMargin = (int) (event.getX() - viewGirl.getMeasuredWidth() / 2);params.topMargin = (int) (event.getY() - viewGirl.getMeasuredHeight() / 2);
viewGirl.setLayoutParams(params);break;
}return true;
}
最后是在界面監聽手指的位置,給viewGirl設置手指的位置,viewgril變化了,viewuncle也就隨之變化了。
好,在會了Coordinatorlayout的用法,最外層父布局有了,該添加兩個子view了。這里里面分別加入AppbarLayout和NestedScrollView作子view,給NestedScrollView加上behavior,就可以讓AppbarLayout跟隨NestedScrollView的Behavior聯動。Android已經自帶了app:layout_behavior="@string/appbar_scrolling_view_behavior",只要滾動發生,就會給自己的子view(if
instance of Appbarlayout)添加滾動事件。不明白這倆控件緊接著看后面講解。當前布局變為:
NestedScrollView(viewgirl的角色)
NestedScrolling機制能夠讓父View和子View在滾動式進行配合,其基本流程如下:
當子view開始滾動之前,可以通知父View,讓其先于自己進行滾動;
子View自己進行滾動;子view滾動之后,還可以通知父view繼續滾動。
而要實現這樣的交互機制,首先父view要實現NestedScrollingParent接口,而子View需要實現NestedScrollingChild接口,在這套機制中子View是發起者,父view是接受回調并做出響應的。
以下是幾個關鍵的類和接口
* NestedScrollView is just like {@link android.widget.ScrollView}, but it supports acting
* as both a nested scrolling parent and child on both new and old versions of Android.
* Nested scrolling is enabled by default.
*/public class NestedScrollView extends FrameLayout implements NestedScrollingParent,NestedScrollingChild, ScrollingView {static final int ANIMATED_SCROLL_GAP = 250;static final float MAX_SCROLL_FACTOR = 0.5f;private static final String TAG = "NestedScrollView";/**
* Interface definition for a callback to be invoked when the scroll
* X or Y positions of a view change.
*
*
This version of the interface works on all versions of Android, back to API v4.
*
* @see #setOnScrollChangeListener(OnScrollChangeListener)
*/public interface OnScrollChangeListener {/**
* Called when the scroll position of a view changes.
*
* @param v The view whose scroll position has changed.
* @param scrollX Current horizontal scroll origin.
* @param scrollY Current vertical scroll origin.
* @param oldScrollX Previous horizontal scroll origin.
* @param oldScrollY Previous vertical scroll origin.
*/void onScrollChange(NestedScrollView v, int scrollX, int scrollY,int oldScrollX, int oldScrollY);
}private long mLastScroll;private final Rect mTempRect = new Rect();private OverScroller mScroller;private EdgeEffect mEdgeGlowTop;private EdgeEffect mEdgeGlowBottom;
······
//主要接口NestedScrollingChildNestedScrollingParent//幫助類NestedScrollingChildHelperNestedScrollingParentHelper
AppbarLayout(viewuncle的角色)
繼承自Linearlayout,且方向是vertical,它可以讓你定制當某個可滾動View的滾動手勢發生變化時,其內部的子View實現何種動作。
AppBarLayout子View的動作內部的子View通過在布局中加app:layout_scrollFlags設置執行的動作
·scroll? :子view會跟隨滾動事件一起滾動,相當于添加到scrollview頭部
·enterAlways? :只要屏幕下滑,view就會立即拉下出來。
·snap :這個屬性讓控件變得有彈性,如果控件下拉了75%的高度,就會自動展開,如果只有25%顯示,就會反彈回去關閉。(去試試支付寶首頁吧,就是加了彈性這個效果)
·exitUntilCollapsed? :當scrollview滑到訂部,再將子view折疊起來
可以給ViewPager設置行為,就不需要使用NestedScrollView的滑動,實現與AppBarLayout聯動。
app:layout_behavior="@string/appbar_scrolling_view_behavior"
setExpande(boolean ) ?設置展開和關閉狀態,默認有開關動畫
使用示例:
CollapsingToolbarLayout
CollapsingToolbarLayout作用是提供了一個可以折疊的Toolbar,它繼承自FrameLayout。
CollapsingToolbarLayout屬性 ? 含義
app:title ? 設置標題
app:collapsedTitleGravity="center" ?設置標題位置
app:contentScrim ? ?設置折疊時toolbar的顏色,默認是colorPrimary的色值
app:statusBarScrim ?設置折疊時狀態欄的顏色 ,默認是colorPrimaryDark的色值
app:layout_collapseParallaxMultiplier ? 設置視差
app:layout_collapseMode="parallax" ?視差模式,在折疊的時候會有個視差折疊的效果
app:layout_collapseMode="pin" ? 固定模式,在折疊的時候最后固定在頂端
使用示例:讓圖片折疊,讓toolbar固定
<android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><android.support.design.widget.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="200dp"android:background="@mipmap/bg"app:layout_collapseMode="parallax"/><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="50dp"android:background="#000"app:layout_collapseMode="pin"/>android.support.design.widget.CollapsingToolbarLayout>android.support.design.widget.AppBarLayout>添加flags可以設置系統狀態欄為透明,如果最頂上是背景這樣用效果更佳
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);setContentView(R.layout.activity_main);
實現toolbar漸變顏色:AppbarLayout提供了滑動偏移監聽,偏移量除以appbar總高度可以得到當前滑動百分比。注意:這個verticalOffset是0或者負數,需要轉絕對值。
appbarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {@Overridepublic void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {//verticalOffset始終為0以下的負數float percent = (Math.abs(verticalOffset * 1.0f)/appBarLayout.getTotalScrollRange());}
});
這Matial Design的設計真好,但是這名取得,一個個兒的也忒長了吧,google什么時候把名字精簡了啊?
好了,以后會持續更新的!
github代碼直通車: https://github.com/18380438200/CoordinatorlayoutFull
—————END—————
? ? ?
? ?創作不易,點個“在看”
總結
以上是生活随笔為你收集整理的coordinatorlayout_一篇文章学会Coordinatorlayout+AppbarLayout的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JDBC练习四
- 下一篇: java请实现程序输出以下星塔||输出菱