一起玩轉CoordinatorLayout

作為Material Design風格的重要組件,CoordinatorLayout協調多種組件的聯動,實現各種復雜的效果,在實際項目中扮演著越來越重要的角色。本篇博客將由淺到深,帶你一起玩轉CoordinatorLayout。

官方文檔對CoordinatorLayout是這樣描述的:

這里寫圖片描述

CoordinatorLayout是一個加強版的FrameLayout,本質是一個ViewGroup,主要有兩個用途:
1.用作應用的頂層布局管理器,作為界面其他控件的父容器
2.用作相互之間有特定交互行為的控件的父容器
通過為CoordinatorLayout的子View指定不同的Behavior(默認的Behavior或自定義的Behavior),就可以實現它們之間許多復雜的交互行為,例如側滑,移動,滑動等。Behavior在后面會詳談,最后我們再來瞅一眼源碼:

public class CoordinatorLayout extends ViewGroup implements NestedScrollingParent {}

先來了解一下NestedScrolling—Android嵌套滑動機制,用來完成復雜的滑動效果。要完成這樣的交互,父View需要實現 NestedScrollingParent 接口,而子View需要實現 NestedScrollingChild 接口。CoordinatorLayout其實是NestedScrollingParent的實現類,也就意味著它的子View一定會實現NestedScrollingChild接口,這樣一起協同完成復雜的滑動交互。

介紹工作就到這里,接下來通過三個例子,一起學習CoordinatorLayout(協調布局)。

一.CoordinatorLayout與AppBarLayout

官方文檔中對AppBarLayout是這樣描述的:AppBarLayout是一個垂直的LinearLayout,只有作為CoordinatorLayout的直接子View時才能正常工作,可以通過設置layout_scrollFlags屬性或setScrollFlags()方法讓AppBarLayout的子View具有“滾動行為”。我們先來看一個例子,再來分析這段描述。

這里寫圖片描述

列表向上滑動,布局收縮;列表向下滑動,布局向下展開到一定高度,待列表完全向下滑動到起始位置,布局再次向下展開。看看怎么實現的:

布局代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:background="@color/colorPrimary"android:minHeight="50dp"app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"></LinearLayout><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"></android.support.v7.widget.Toolbar></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v7.widget.RecyclerView></android.support.design.widget.CoordinatorLayout></LinearLayout>

CoordinatorLayout中,AppBarLayout與RecyclerView豎直排列;AppBarLayout中,LinearLayout與Toolbar豎直排列。AppBarLayout的官方文檔告訴我們,通過設置layout_scrollFlags屬性可以讓子View具有滑動行為。結合布局文件可以看到,我們給LinearLayout設置了三個屬性,都代表什么意思呢:

scroll:設成這個值的效果就是該View和scrolling view形成一個整體,示例中我們滑動RecyclerView時,LinearLayout也會響應滑動。有一點特別需要我們的注意,為了其他的滾動行為生效,必須同時指定scroll和其他標記。
exitUntilCollapsed:設成這個值的效果就是該View離開屏幕時,會被折疊到最小高度。該View已完全折疊后,再向下滾動scrolling view,直到scrolling view頂部的內容完全顯示后,該View才會開始向下滾動以顯現出來。
enterAlways:設成這個值的效果就是當scrolling view向下滾動時,該View會一起跟著向下滾動,示例圖中有所體現。
enterAlwaysCollapsed:設成這個值的效果就是當我們開始向下滾動scrolling view時,該View會一起跟著滾動直到達到其最小高度。然后當scrolling view滾動至頂部內容完全顯示后,再向下滾動scrolling view,該View會繼續滾動到完全顯示出來。示例圖中有所體現。

篇幅有限,這里就不多做演示了,大家可以自己試試,組合成不同的效果。

通過分析CoordinatorLayout我們知道它的子View一定會實現NestedScrollingChild接口,這樣一起完成復雜的滑動交互,我們看到布局中有一個RecyclerView,先瞅一眼源碼:

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {}

Bingo!RecyclerView其實就是NestedScrollingChild的實現類,這也就解釋了嵌套滑動的實現。這里如果使用NestedScrollView,然后在里面嵌套一個布局也是可以的。最后我們還為RecyclerView設置了這樣一個屬性:

 app:layout_behavior="@string/appbar_scrolling_view_behavior">

這是因為CoordinatorLayout包含的子視圖中,帶有滾動屬性的View必須設置app:layout_behavior屬性,設置的這個屬性到底是什么呢:

android.support.design.widget.AppBarLayout$ScrollingViewBehavior

原來是AppBarLayout自帶一個Behivior,直接在源碼里注解聲明的,這個Behivior也只能用于AppBarLayout,作用是讓他根據CoordinatorLayout上的手勢進行一些效果(比如收縮,滾動)。關于CoordinatorLayout與Behivior工作原理,我們后面再談。

二.CoordinatorLayout與CollapsingToolbarLayout
CollapsingToolbarLayout(折疊布局)繼承至FrameLayout,通過給它設置layout_scrollFlags,它以控制子View響應layout_behavior事件并作出相應的變化(移除屏幕或固定在屏幕頂端)。我們看一個例子:

這里寫圖片描述

很常見也很好看的一個界面,看看布局代碼:

<?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:layout_width="match_parent"android:layout_height="match_parent"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="250dp"><android.support.design.widget.CollapsingToolbarLayoutandroid:id="@+id/collapsing_toolbar"android:layout_width="match_parent"android:layout_height="match_parent"app:contentScrim="?attr/colorPrimary"app:expandedTitleMarginEnd="60dp"app:expandedTitleMarginStart="50dp"app:layout_scrollFlags="scroll|exitUntilCollapsed"><ImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY"android:src="@drawable/bg"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7" /><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin" /></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><android.support.v7.widget.RecyclerViewandroid:id="@+id/recycler"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior" /></android.support.design.widget.CoordinatorLayout>

結合代碼我們看看CollapsingToolbarLayout的使用方法:

1.AppBarLayout與Toolbar的高度一定要設置具體值,這是最后展開與固定的值
2.CollapsingToolbarLayout的屬性設置:layout_scrollFlags一定是必不可少的,屬性值上文提過,這里不再重復了;contentScrim設置CollapsingToolbarLayout折疊后的背景顏色;expandedTitleMarginStart 設置沒有收縮時title向左填充的距離;expandedTitleMarginEnd設置收縮結束時title向左填充的距離
3.ImageView的屬性設置:layout_collapseMode (折疊模式)一定是必不可少的,一共有兩種模式。pin:設置為這個模式時,當CollapsingToolbarLayout完全收縮后,Toolbar還可以保留在屏幕上;parallax:設置為這個模式時,在內容滾動時,CollapsingToolbarLayout中的View(比如ImageView)也可以同時滾動,實現視差滾動效果,通常和視差因子搭配使用;layout_collapseParallaxMultiplier設置視差滾動因子,值為0~1,值越大視察越大。
4.CollapsingToolbarLayout的折疊、展開狀態監聽: CollapsingToolbarLayout是通過實現AppBarLayout的OnOffsetChangedListener接口,根據AppBarLayout的偏移來實現子View視差移動和顯示。通過調用AppBarLayout的addOnOffsetChangedListener方法監聽AppBarLayout的位移,從而判斷CollapsingToolbarLayout的狀態。

三.CoordinatorLayout與Behavior

前面提到,CoordinatorLayout的子View之間許多復雜的交互行為是通過指定Behavior實現的。那么實現原理是什么,我們看個例子:

這里寫圖片描述

TextView的位置會隨著Button的改變而改變,并且顯示當前的坐標。其實Behavior的原理就是觀察者模式的應用,被觀察者就是事件源dependency,觀察者就是做出改變的child。具體看看怎么實現的:

public class FollowBehavior extends CoordinatorLayout.Behavior<TextView> {public FollowBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) {return dependency instanceof Button;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) {child.setX(dependency.getX() + 200);child.setY(dependency.getY() + 200);child.setText("觀察者:" + dependency.getX() + "," + dependency.getY());return true;}
}

1.自定義一個FollowBehavior繼承自Behavior,泛型就是child的類型,也就是觀察者View
2.重寫構造函數,因為CoordinatorLayout源碼中會通過反射調用這個構造函數
3.重寫layoutDependsOn():用來確定本次交互行為中的dependent view,在上面的代碼中,當dependency是Button類的實例時返回true,就可以讓系統知道布局文件中的Button就是本次交互行為中的被觀察者。
4.重寫onDependentViewChanged:當dependent view發生變化時,這個方法會被調用,參數中的child相當于本次交互行為中的觀察者,觀察者可以在這個方法中對被觀察者的變化做出響應,從而完成一次交互行為。

代碼布局中的應用:

<?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:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_behavior=".FollowBehavior" /><Buttonandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="被觀察者" /></android.support.design.widget.CoordinatorLayout>btn.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_MOVE) {v.setX(event.getRawX() - v.getWidth() / 2);v.setY(event.getRawY() - v.getHeight() / 2 - getStatusBarHeight(getApplicationContext()));}return true;}});

xml布局文件中,只需指定

app:layout_behavior=“你的Behavior包含包名的類名”

CoordinatorLayout就會反射生成你的Behavior,這樣自定義的Behavior就能工作了。在Activity代碼中,添加OnTouchListener,獲取觸摸點坐標,這里豎直方向上減去了狀態欄的高度。

既然熟悉了Behavior的原理,這里我在之前的例子上升級了一下。先看效果圖:

這里寫圖片描述

折疊布局中加了一個圓形頭像,并且圓形頭像的大小,位置會隨著列表上下滑動而改變。沒有美工設計,交互是自己瞎想的,大家湊合看看。重點是掌握自定義Behavior。

這里的圓形ImageView就是我們的觀察者,給它指定Behavior,從而響應手勢事件。誰是被觀察者呢?這里我選擇的是AppBarLayout,因為上文提到過,可以通過AppBarLayout的addOnOffsetChangedListener方法監聽AppBarLayout的位移,從而判斷CollapsingToolbarLayout的狀態。既然能夠獲取到這個位移,那就可以讓觀察者對被觀察者的位移變化做出響應。看看具體實現:

public class FollowBehavior extends CoordinatorLayout.Behavior<ImageView> {private int width, height, top, left;public FollowBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, ImageView child, View dependency) {return dependency instanceof AppBarLayout;}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, ImageView child, View dependency) {if (dependency.getY() == 0) {width = child.getWidth();height = child.getHeight();top = child.getTop();left = child.getLeft();}float percent = Math.abs(dependency.getY()) / SixActivity.scrollRange;float yPercent = (float) (percent * 0.85);child.setY(top * (1 - yPercent));child.setX(left + 300 * percent);CoordinatorLayout.LayoutParams layoutParams =(CoordinatorLayout.LayoutParams) child.getLayoutParams();layoutParams.width = (int) (width * (1 - percent * 3 / 4));layoutParams.height = (int) (height * (1 - percent * 3 / 4));child.setLayoutParams(layoutParams);return true;}
}

具體分析一下onDependentViewChanged這個方法,AppBarLayout的折疊范圍scrollRange是通過 appBarLayout.getTotalScrollRange()獲取到的,這里我設置成了靜態常量;當AppBarLayout完全展開,沒有折疊時,獲取到ImageView的基本屬性;當AppBarLayout狀態改變時,同時改變ImageView的坐標與大小,達到示例效果。使用時很簡單,直接在CoordinatorLayout的XML布局加上即可。

    <de.hdodenhof.circleimageview.CircleImageViewandroid:id="@+id/img"android:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="center"android:layout_marginTop="-340dp"android:src="@drawable/head"app:layout_behavior=".FollowBehavior" />

關于CoordinatorLayout的用法到這里差不多也就結束了,希望能對你有所幫助,如有不足與錯誤的地方隨時向我提問,我會認真采納。項目源碼已經同步上傳到我的github上,歡迎star,fork,提issues,一起進步!

https://github.com/18722527635/AndroidArtStudy

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457365.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457365.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457365.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

離散數學圖論旅行規劃問題_2020年MathorCup高校數學建模挑戰賽——C 題 倉內揀貨優化問題...

下面的鏈接是精華版思路&#xff0c;亮點是對第六問的探討。高度概括一下&#xff1a;第一問曼哈頓&#xff0c;第二問用免疫&#xff0c;三問增加任務單&#xff0c;四問增加揀貨員&#xff0c;五問改變復核臺&#xff0c;六問亮點來探討~ 有點皮MathorCup C題 倉內揀貨優化問…

Asp.NetWebForm的控件屬性

一&#xff1a;GridView&#xff1a; 1.綁定ID 的值&#xff1a;DataKeyNames"Id", 2.自動產生列的意思:AutoGenerateColumns 3.如何注冊腳本&#xff1a;ClientScript.RegisterStartupScript(this.GetType(),"text","alert(刪除成功)"&#xf…

【VBA編程】10.自定義集合

自定義集合類型&#xff0c;類似于變量聲明&#xff0c;只是要將Dim關鍵字和New collection關鍵字搭配起來使用&#xff0c;其語法描述如下&#xff1a;其中集合名的命名方式同于標準變量的命名 Dim 集合名 As New collection 對于已經定義的集合對象&#xff0c;可以使用集合的…

git fork clone 區別_Working with Git | Git 與 GitHub

關于各位好&#xff0c;這里是 Chinas Prices Project 項目的知乎專欄。關于 CPP 項目&#xff0c;您可以在這篇文章里了解到更多的信息。若您對這個項目感興趣&#xff0c;我們非常歡迎您與我們交流您的想法與見解。在一個團隊的成員同時為一個項目進行開發工作時&#xff0c;…

舒適的路線(codevs 1001)

題目描述 DescriptionZ小鎮是一個景色宜人的地方&#xff0c;吸引來自各地的觀光客來此旅游觀光。Z小鎮附近共有N(1<N≤500)個景點&#xff08;編號為1,2,3,…,N&#xff09;&#xff0c;這些景點被M&#xff08;0<M≤5000&#xff09;條道路連接著&#xff0c;所有道路都…

PHP_Smarty

模板 數據與表現層的標簽分離 smarty是PHP 與 HTML代碼的分離 小型模板類 $smarty 的工作流程&#xff1a; 把需要顯示的全局變量&#xff0c;賦值塞到對象內部的屬性上&#xff0c;一個數組中.編譯模板&#xff0c;把{$標簽},解析成相應的<?php echo 代碼引入編譯后的PHP文…

讀中文_挑戰來了!康輝喊你讀中文十級繞口令!

文章來源&#xff1a;央視頻漢語橋木甬讀桶不讀涌&#xff0c;月農讀膿不讀朧。米更讀粳不讀梗&#xff0c;日青讀晴不讀睛。米宗讀粽不讀綜&#xff0c;言丁讀訂不讀釘。土竟讀境不是鏡&#xff0c;土平讀坪不是評。耳令讀聆不讀嶺&#xff0c;火登讀燈不讀澄。言甬讀誦不讀蛹…

ios 自定義鍵盤

由于項目需要&#xff0c;需要自定義鍵盤。ios系統鍵盤會緩存鍵盤輸入&#xff0c;并保存在系統目錄下的文件里&#xff0c;并且是明文存儲&#xff0c;存在帳號密碼泄漏風險。在別人代碼基礎上修改了下&#xff0c;美化了下界面&#xff0c;去掉了字符輸入&#xff0c;加了點擊…

對象入參指定泛型類型_為什么要使用泛型,而不是直接將類型作為參數傳遞?

其實很多類型系統都是用類型參數的的形式來實現Universal Type的&#xff0c;Parametric Polymorphism 和System F可以了解一下&#xff0c;如果只局限于一兩個熱門語言的話&#xff0c;可能會有此疑問&#xff0c;但是從type theory的角度來說&#xff0c;高階類型本身就是typ…

【GOF23設計模式】迭代器模式

【GOF23設計模式】迭代器模式 來源&#xff1a;http://www.bjsxt.com/ 一、【GOF23設計模式】_迭代器模式、JDK內置迭代器、內部類迭代器 1 package com.test.iterator;2 /**3 * 自定義的迭代器接口4 */5 public interface MyIterator {6 void first(); //將游標指向第…

SQLServer 維護腳本分享(08)臨時數據庫(tempdb)

dbcc sqlperf(logspace) --各數據庫日志大小及使用百分比dbcc loginfo --查看當前數據庫的虛擬日志文件--臨時表Tempdb最近使用情況 SELECT t1.session_id ,t1.internal_objects_alloc_page_count*8.0/1024 as internal_objects_alloc_MB ,t1.internal_objects_dealloc_p…

51單片機50個實例代碼_【附代碼】51單片機電子密碼鎖教程

簡介大家好&#xff0c;這篇文章的內容是關于如何用51單片機來制作一個電子密碼鎖的教程&#xff0c;通過這篇教程可以讓剛入門的朋友了解矩陣鍵盤、LCD1602的使用方法&#xff0c;以及密碼輸入和修改的程序介紹&#xff0c;我會對每個部分進行詳細的介紹。首先我們來看一下這個…

旋轉的正方體

<!DOCTYPE html><html lang"zh-cmn-Hans"><head><meta charset"utf-8" /><title>backface-visibility_CSS參考手冊_web前端開發參考手冊系列</title><meta name"author" content"Joy Du(飄零霧雨),…

8數據提供什么掩膜產品_博碩能為你提供什么產品?

自動噴漆設備應用于線條、木門、櫥柜、樓梯、套房家具、辦公家具、木飾面板、外墻保溫裝飾一體板板等產品領域&#xff0c;針對NC、PU、UV、水性漆和氟碳漆等不同種類的油漆&#xff0c;進行自動化噴涂和干燥作業。自動噴漆設備有多種規格型號&#xff0c;分為不同的噴涂方式。…

python3 實現對比conf 文件差異

用法&#xff1a; ./conf.py nginx1.conf nginx2.conf > diff.htmlconf.py#!/usr/bin/python import difflib import sys #### Usage: compare_nginx.conf.py filename1 filename2 >diff.html try:textfile1 sys.argv[1]textfile2 sys.argv[2] except Exception as…

mysql----innodb統計信息

對innodb 統計信息的控制可以通過如下幾個常用的variables 來實現 1、innodb_stats_persistent&#xff1a; 這個參數控制著innodb的統計信息是否持久化到磁盤&#xff0c;先說明一下持久化到磁盤是什么意思&#xff1b;通常來說統計信息只保存在內存中&#xff0c;也就是說如果…

linux pid t 頭文件_linux系統調用相關頭文件

Linux C 一些函數 所屬的頭文件 2011-03-07 10:25:07分類&#xff1a; LINUX在編寫程序時&#xff0c;有時總是不記得所使用的函數在哪個庫函數中。現在先把自己以前經常用到的函數頭文件總結一下。 有不對的地方還請指教。1&#xff0c;系統調用 文件的操作函數#inlclude &…

jsp頁面驗證碼(完整實例)

項目結構如下&#xff0c;MyEclipse中新建一個Web Project&#xff0c;取名servlet 1、src下new一個servlet類 package com.servlet;import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOExcept…

開源oa_圈子哥推薦一款基于 Spring Boot 開發 OA 開源產品,學習/搞外快都是不二選擇!...

點擊上方藍字關注「程序員的技術圈子」今天圈子哥給大家推薦一套Spring Boot 開發 OA系統&#xff0c;系統功能齊全&#xff0c;不管是用來學習或者搞外快都是不錯的選擇&#xff0c;clone下來吧&#xff01;辦公自動化(OA)是面向組織的日常運作和管理&#xff0c;員工及管理者…

iOS網絡編程實踐--NSStream實現TCP Socket iPhone客戶端

客戶端我們使用iPhone應用程序&#xff0c;畫面比較簡單。點擊發送按鈕&#xff0c;給服務器發送一些字符串過去。點擊接收按鈕就會從服務器讀取一些字符串&#xff0c;并且顯示在畫面上。 有關客戶端應用的UI部分不再介紹了&#xff0c;我們直接看代碼部分&#xff0c;Socket客…