編輯:關於Android編程
以前我們創建項目時候,一個頁面的布局是線性或者相對等,當我在AS上新建一個module時,系統默認的最外層布局不再是我們熟悉的五大布局中的一種,而是一個全新的布局:CoordinatorLayout。它是Material風格的重要組件, 作為布局的頂層控件,協調(Coordinate)其他組件, 實現聯動。
activity_main.xml主布局
content_main.xml
看看效果圖如下:
??很明顯,狀態欄是有問題的,我們只需要將主布局的
android:fitsSystemWindows=”true”取調即可
以下是去掉之後的顯示狀態
以上的布局需要注意幾個點:
app:layout_scrollFlags=”scroll"enterAlways”
app:layout_behavior=”@string/appbar_scrolling_view_behavior”
其中控制ToolBar是否可以滾出屏幕的屬性是由app:layout_scrollFlags=”scroll|enterAlways”
enterAlwaysCollapsed: 顧名思義,這個flag定義的是何時進入(已經消失之後何時再次顯示)。假設你定義了一個最小高度(minHeight)同時enterAlways也定義了,那麼view將在到達這個最小高度的時候開始顯示,並且從這個時候開始慢慢展開,當滾動到頂部的時候展開完。
exitUntilCollapsed: 同樣顧名思義,這個flag時定義何時退出,當你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失
我們來了解下,如何自定義Behavior
CoordinatorLayout的工作原理是搜索定義了CoordinatorLayout Behavior 的子view,不管是通過在xml中使用app:layout_behavior標簽還是通過在代碼中對view類使用@DefaultBehavior修飾符來添加注解。當滾動發生的時候,CoordinatorLayout會嘗試觸發那些聲明了依賴的子view。要自己定義CoordinatorLayout Behavior,你需要實現layoutDependsOn() 和onDependentViewChanged()兩個方法。
android.support.design.widget.AppBarLayout$ScrollingViewBehavior
其實它並不是一個字符串資源,而它代表的是一個類
public static class ScrollingViewBehavior extends ViewOffsetBehaviorclass ViewOffsetBehavior extends Behavior
1.某個view需要根據監聽另一個的行為來控制自己的行為,這個時候我們需要重寫2個方法
public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) { return false; }
public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) { return false; }
結合我們一個列子來理理思路,首先看例子的效果圖:
先看這個例子的主布局activity_main.xml
上面的主布局中,我們為FloatingActionButton增加了一個自定義的屬性行為
app:layout_behavior="com.example.administrator.myapplication.FooterBehavior"
意思就是:這個FloatingActionButton根據監聽AppBarLayout滑動的行為來控制自己的行為
content_main.xml
FooterBehavior
package com.example.administrator.myapplication; import android.content.Context; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.util.AttributeSet; import android.view.View; public class FooterBehavior extends CoordinatorLayout.Behavior{ public FooterBehavior(Context context,AttributeSet attributeSet){ super(context,attributeSet); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return dependency instanceof AppBarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { float scaleY = Math.abs(dependency.getY()) / dependency.getHeight(); child.setTranslationY(child.getHeight() * scaleY); return true; } }
這兩個方法的參數都是一樣的,解釋一下,第一個不用說,就是當前的CoordinatorLayout,第二個參數是我們設置這個Behavior的View,也就是FloatingActionButton, 第三個是我們關心的那個View。如何知道關心的哪個呢?layoutDependsOn的返回值決定了一切!
我們的例子layoutDependsOn方法中,return dependency instanceof AppBarLayout;是關心的AppBarLayout,也就是Toolbar(AppBarLayout)變化位置,引起FloatingActionButton的位置變化
onDependentViewChanged方法意思是什麼呢?
先計算出Toolbar(AppBarLayout)暴露在屏幕的比例大小
然後計算出FloatingActionButton需要移動到的位置
以下是log日志
Log.i("TAG","scaleY-->>"+scaleY+",,child.getHeight() * scaleY-->>"+child.getHeight() * scaleY);
I/TAG: scaleY-->>0.05952381,,child.getHeight() * scaleY-->>8.928572 I/TAG: scaleY-->>0.31547618,,child.getHeight() * scaleY-->>47.321426 I/TAG: scaleY-->>0.8214286,,child.getHeight() * scaleY-->>123.21429 I/TAG: scaleY-->>1.0,,child.getHeight() * scaleY-->>150.0 I/TAG: scaleY-->>0.875,,child.getHeight() * scaleY-->>131.25 I/TAG: scaleY-->>0.10119048,,child.getHeight() * scaleY-->>15.178572 I/TAG: scaleY-->>0.0,,child.getHeight() * scaleY-->>0.0
2、第二種情況,滑動。因為這個是根據CoordinatorLayout裡子view的滾動行為來改變我們的狀態的,所以情況1中的2個方法我們就不需要重寫了。下面,我們用情況2來實現上面的效果。
package com.example.administrator.myapplication; import android.content.Context; import android.support.design.widget.CoordinatorLayout; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.View; public class FooterBehavior extends CoordinatorLayout.Behavior{ private float targetY = -1; private static final String TAG = "FooterBehavior"; public FooterBehavior(Context context,AttributeSet attributeSet){ super(context, attributeSet); } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { if(targetY == -1){ targetY = target.getY(); } return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); float scrooY = targetY - Math.abs(target.getY()); float scaleY = scrooY / targetY; child.setTranslationY(child.getHeight() * scaleY); } }
在方法onStartNestedScroll中,首先獲取target在Y軸上距離屏幕頂端的距離,然後判斷是否是在Y軸上滾動。
方法onNestPreScroll中,就是時時根據target距離屏幕頂端的距離計算出滾動的距離,然後根據比例計算出child移動的距離。
我們簡單看下源碼
* @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is * associated with * @param child the child view of the CoordinatorLayout this Behavior is associated with * @param directTargetChild the child view of the CoordinatorLayout that either is or * contains the target of the nested scroll operation * @param target the descendant view of the CoordinatorLayout initiating the nested scroll * @param nestedScrollAxes the axes that this nested scroll applies to. See * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, * {@link ViewCompat#SCROLL_AXIS_VERTICAL} * @return true if the Behavior wishes to accept this nested scroll * * @see NestedScrollingParent#onStartNestedScroll(View, View, int) */ public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) { return false; }
百度翻譯如下:
child:coordinatorlayout孩子的這種行為是與(本例就是FloatingActionButton)
target :啟動嵌套滾動coordinatorlayout後裔的觀點(本例就是AppBarLayout)
directTargetChild 這個涉及到深層次的布局問題,我們的布局中只有一個控件FloatingActionButton
最近項目裡把圖片加載框架從xUtils換到了Picasso,一些下載和緩存的策略也因此發生變化,Picasso的緩存沒有xUtils自動化那麼高,使用起來遇到了一些困難,
一、前言前一段時間在做視頻開發,由於本人剛接觸視頻開發這塊,所以領導沒有對我提很高的要求,僅僅要求能夠播放本地視頻即可。我想怎麼簡單怎麼做。於是選擇用Android Vi
在Api中關於這個類的介紹大致就是這是一個可以顯示網頁的視圖,如:webView.loadUrl(http://www.baidu.com/);顯示結果:還可以加載一些h
先上效果圖: Title的Layout為: 彈出的dialog的Layout為