日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自定义Behavior

發布時間:2023/12/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自定义Behavior 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.



Behavior簡介

CoordinatorLayout是個很牛的布局容器,使用它可以很方面的實現很多效果,比如支付寶首頁的折疊效果,知乎首頁等等,Behavior是它的一個內部抽象類,聲明Behavior屬性的View可以和他它依賴的兄弟元素交互,當然,這些元素都必須是CoordinatorLayout的子元素。

what?

該類是CoordinatorLayout子View之間交互的插件,有了它CoordinatorLayout的子View就可以產生聯動效果。比如一個子View跟隨另一個子View的移動而移動,或者是縮放,透明度變換等。

why?

一般情況下,如果要實現子View,隨著上拉消失,下拉出現,我們需要在Activity中監聽滾動事件,在里邊處理View的顯示邏輯,這樣就會導致Activity中代碼量變大,滾動事件中的邏輯也會變的復雜,有了CoordinatorLayout.behavior,不需要監聽滾動事件,只需要自定義一個Behavior的實現類,實現幾個方法就可以達到相應的效果,不需要修改activity中的代碼。

how?

Behavior是CoordinatorLayout的一個內部抽象類,里邊的方法有很多,如果不是要實現特別復雜的功能,只需要實現1,2個方法就可以了。常見的有兩種方式:

1. 如果要依賴于CoordinatorLayout中的某個子View實現某種變化,需要實現Behavior的layoutDependsOn()和onDependentViewChanged()方法,前者會在CoordinatorLayout中通過循環的方式,找到被依賴的View,返回true,表示找到了被依賴的View,后者在每次dependency的大小,位置變化的時候都會調用,可以在這里出child的變化邏輯。

/*** 在CoordinatorLayout中通過循環遍歷的方式找到被依賴的View** @param parent CoordinatorLayout* @param child 設置了該Behavior的View* @param dependency 被依賴的View* @return true 標識找到了被依賴的View*/@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {//...}/*** 每次dependency的大小或位置有所變化的時候都會調用該方法** @param parent* @param child* @param dependency* @return*/@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {//...}

2. 如果不需要依賴于任何子View,純粹只是想要根據滑動距離,做一些操作,可以實現onStartNestScroll()和onNestPreScroll()。

onNestedPreScroll(CoordinatorLayout?coordinatorLayout, V child,?View?target, int dx, int dy, int[] consumed, int type)

Called when a nested scroll in progress is about to update, before the target has consumed any of the scrolled distance.

該方法是在target消費調用任何的滾動距離之前調用的。這個時候還沒有更新

onNestedScroll(CoordinatorLayout?coordinatorLayout, V child,?View?target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type)

Called when a nested scroll in progress has updated and the target has scrolled or attempted to scroll.


自定義Behavior的使用方式:

1. 在res/values文件夾下定義字符串引用,然后再布局文件中引用

2.直接在布局文件中使用全路徑包名

實例1:

實現上拉消失,下拉顯示的效果。這個效果不需要依賴任何的View,所以重寫onStartNestScroll()和onNestPreScroll()即可,

在onStartNestScroll()中判斷View要位移的總距離,然后再onNestPreScroll()方法中進行邊界判斷并位移即可。

具體代碼:

public class DownToHiddenBehavior extends CoordinatorLayout.Behavior<View> {private int mOffsetY = 0;public DownToHiddenBehavior() {super();}public DownToHiddenBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) child.getLayoutParams();int total = params.bottomMargin + child.getHeight(); // Log.i("onNestedPreScroll", "------>trans:" + child.getTranslationY() + " ,total:" + total);mOffsetY += dy;//dy<0:表示下拉,offsetY<0:表示下拉的距離已經超出View的原始位置//一定要同時成立才行,否則先向上滑動,然后再快速向下滑動,View的位置會出現偏移。//dy<0的時候,moffsetY不一定小于0,相反也一樣if (dy < 0 && mOffsetY < 0) {mOffsetY = 0;}//邊界判斷if (dy > 0 && mOffsetY > total) {mOffsetY = total;}child.setTranslationY(mOffsetY);} }

注意:這里的構造方法一定要重載!!!不然會報錯的。因為Behavior是在CoordinatorLayout中使用反射進行調用的。需要用到兩參的構造方法。

接下來在布局文件中引用即可

<android.support.design.widget.FloatingActionButtonapp:layout_behavior="@string/behavior_down_to_hidden"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="floatButton"android:layout_gravity="bottom|right"android:layout_marginBottom="50dp"android:layout_marginRight="50dp"/>

實例2:

實現View跟隨ToolBar的消失和顯示進行縮放。向上滑動的時候Toolbar逐漸移除屏幕,view逐漸縮小直到消失。下拉的時候,Toolbar逐漸出現,View逐漸放大到原始大小。

很明顯,這里需要依賴于Toolbar,因此使用第一種方法,重寫layoutDependsOn()和onDependentViewChanged()方法

具體代碼:

public class ScaleToHiddenBehavior extends CoordinatorLayout.Behavior<View> {private float mToolbarHegiht;public ScaleToHiddenBehavior(Context context, AttributeSet attrs) {super(context, attrs);}/*** 在CoordinatorLayout中通過循環遍歷的方式找到被依賴的View** @param parent CoordinatorLayout* @param child 設置了該Behavior的View* @param dependency 被依賴的View* @return true 標識找到了被依賴的View*/@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {if (mToolbarHegiht == 0) {mToolbarHegiht = dependency.getHeight();}return dependency instanceof AppBarLayout;}/*** 每次dependency的大小或位置有所變化的時候都會調用該方法** @param parent* @param child* @param dependency* @return*/@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {Log.i("onDependentViewChanged", "------->height:" + mToolbarHegiht + ", top:" + dependency.getTop());float fraction = Math.abs(dependency.getTop()) / mToolbarHegiht;child.setScaleX(1 - fraction);child.setScaleY(1 - fraction);return super.onDependentViewChanged(parent, child, dependency);} }

同樣在布局文件中引用該類

<android.support.design.widget.FloatingActionButtonapp:layout_behavior="@string/behavior_scale_to_hidden"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="floatButton"android:layout_gravity="top|right"android:layout_marginTop="100dp"android:layout_marginRight="50dp"/>

實例3:

使用CoordinatorLayout實現支付寶首頁折疊效果 :

思路:

這里不需要自定義Behavior,但是需要監聽AppbarLayout的折疊距離,控制Toolbar的顯示效果。

整個Activity的布局文件activity_page_home_zfb.xml

頂部的搜索框Toolbar和需要折疊起來的布局全都放在CoolapsingToolbarLayout中,因為CoolapsingToolbarLayout繼承自FrameLayout,想要讓Toolbar顯示在頂部,并且看起來不覆蓋折疊布局,這里設置了給需要折疊的布局設置了marginTop,值剛好就是Toolbar的高度。

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"><android.support.design.widget.AppBarLayoutandroid:id="@+id/appbarLayout"android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.design.widget.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"><includeandroid:id="@+id/collapsLayout"layout="@layout/include_layout_collaps"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="?attr/actionBarSize"android:orientation="horizontal"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7"/><android.support.v7.widget.Toolbarandroid:id="@+id/toolbarContainer"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:contentInsetLeft="0dp"app:contentInsetStart="0dp"app:layout_collapseMode="pin"><includelayout="@layout/include_layout_toolbar_1"android:id="@+id/toolbar1"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"/><includeandroid:visibility="gone"layout="@layout/include_layout_toolbar_2"android:id="@+id/toolbar2"android:layout_width="match_parent"android:layout_height="match_parent"/></android.support.v7.widget.Toolbar></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><android.support.v4.widget.NestedScrollViewandroid:id="@+id/nestScrollView"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_behavior="@string/appbar_scrolling_view_behavior"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="200dp"android:background="#bac"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:background="#abc"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:background="#cba"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="150dp"android:background="#bba"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="150dp"android:background="#aab"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="200dp"android:background="#ccb"/></LinearLayout></android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>

支付寶的效果是,剛進入頁面折疊布局完全展開,并且Toolbar顯示的是搜索框。上拉時搜索框逐漸隱藏,然后Toolbar開始逐漸顯示4個按鈕的布局,全程展開的折疊布局逐漸折疊起來,并且透明度逐漸降低。

這里參考了網上的思路,當折疊到一半高度的時候開始切換Toolbar的布局。

具體代碼如下:

public class ZFBHomePageActivity extends BaseActivity {private AppBarLayout mAppbarLayout;private LinearLayout mToolbar1,mToolbar2;private LinearLayout mCollapsLayout;@Overrideprotected void initView() {mAppbarLayout=findViewById(R.id.appbarLayout);mToolbar1=findViewById(R.id.toolbar1);mToolbar2=findViewById(R.id.toolbar2);mCollapsLayout=findViewById(R.id.collapsLayout);mAppbarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {@Overridepublic void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {float value=Math.abs(verticalOffset);int total=mAppbarLayout.getTotalScrollRange();int midHeight=total/2;if (value<=midHeight){//toolbar1的alpha值從1-0float fraction = value / midHeight * 1.0f;mToolbar1.setVisibility(View.VISIBLE);mToolbar2.setVisibility(View.GONE);mToolbar1.setAlpha(1-fraction);}else {//toolbar2的alpha值從0-1float fraction=(value-midHeight)/(total-midHeight)*1.0f;mToolbar1.setVisibility(View.GONE);mToolbar2.setVisibility(View.VISIBLE);mToolbar2.setAlpha(fraction);Log.i("onOffsetChanged","---->value:"+value+", fraction:"+fraction+(mToolbar2.getVisibility()==View.VISIBLE));}//折疊的布局alpha值從1-0mCollapsLayout.setAlpha(1-(value/total*1.0f));}});} 非常簡單,只需要在給AppbarLayout注冊addOffsetChangedListener()監聽,根據折疊的偏移量,在偏移量小于總偏移量的1/2時,顯示搜索布局,隱藏四個按鈕,并降低搜索布局的透明度;當偏移量大于一半時,隱藏搜索布局,逐漸顯示4個按鈕。折疊布局的透明度,要開始折疊,一直到完全折疊起來逐漸降低。




總結

以上是生活随笔為你收集整理的自定义Behavior的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。