Material Design(四)--AppBarLayout

本節(jié)主要講AppBarLayout,但是一講到AppBarLayout必然會講另外兩個布局,CoordinatorLayout和CollapsingToolbarLayout ,因為這三個布局一起使用的時候會產(chǎn)生非常炫酷的效果!前一篇文章我們講過CoordinatorLayout,說它是一個加強版的FrameLayout,不過它可以監(jiān)聽其所有子控件的各種事件,然后幫我們做出合理的相應(yīng)。但是它到底是怎樣監(jiān)聽各個子控件的呢?具體的用法接下來一一跟大家分享!

CoordinatorLayout

CoordinatorLayout.png

首先看看官方文檔的解釋:
加強版的Framelayout,兩種使用場景

  • 作為頂層布局使用
  • 作為具有一個或多個相互作用的子控件的容器

那么CoordinatorLayout是怎樣協(xié)調(diào)子view的呢?當(dāng)然是通過behavior。 app:layout_behavior="@string/appbar_scrolling_view_behavior"這是開發(fā)中最常見的behavior。通過給滑動控件設(shè)置behavior,CoordinatorLayout的子view通過這個behavior可以做出具體的響應(yīng)操作!對于behavior實怎樣操作的?內(nèi)部有哪些方法?我會單獨在討論的!

AppbarLayout

AppbarLayout .png

官網(wǎng)的描述是:AppbarLayout 是一個垂直方向的Linearlayout,它實現(xiàn)了material design控件的特征,通過手勢改變子view的動作。那么當(dāng)滑動手勢改變時,內(nèi)部的子view應(yīng)該提供怎樣的響應(yīng)動作呢?


image.png
app:layout_scrollFlags.//設(shè)置響應(yīng)動作
  • 注意點:


    image.png

    AppbarLayout 嚴重依賴于CoordinatorLayout,必須用于CoordinatorLayout 的直接子View,如果你將AppbarLayout 放在其他的ViewGroup 里面,那么它的這些功能是無效的。

app:layout_scrollFlags的值有哪些?具體的效果是什么?

layout_scrollFlags.png

layout_scrollFlags有5種動作,分別是 scroll,enterAlways,enterAlwaysCollapsed,exitUntilCollapsed,snap

  • scroll
int SCROLL_FLAG_SCROLL
The view will be scroll in direct relation to scroll events. 
This flag needs to be set for any of the other flags to take effect.
 If any sibling views before this one do not have this flag, then this value has no effect.

該屬性是:當(dāng)子view設(shè)置該屬性是,該子view會隨著滑動控件滾動而滾動。

<?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.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll"
            />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginTop="35dp"
                app:cardCornerRadius="4dp">

                <TextView
                    android:id="@+id/fruit_content_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"/>
            </android.support.v7.widget.CardView>
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>!
scoll.gif
  • enterAlways
 SCROLL_FLAG_ENTER_ALWAYS
When entering (scrolling on screen) the view will scroll on any downwards scroll event,
 regardless of whether the scrolling view is also scrolling. 
This is commonly referred to as the 'quick return' pattern.

當(dāng)子view設(shè)置該屬性的時候,當(dāng)NestedScrollView向下滑動的時候,改子view直接向下滑動,不管NestedScrollView是否在滑動。注意:要與scroll 搭配使用,否者是不能滑動的。

  <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways"
            />
    </android.support.design.widget.AppBarLayout>
enterAlways.gif
  • enterAlwaysCollapsed


    enterAlwaysCollapsed.png

    enterAlwaysCollapsed 是對enterAlways 的補充,當(dāng)NestedScrollView向下滑動的時候,滑動View(也就是設(shè)置了enterAlwaysCollapsed 的View)下滑至折疊的高度,當(dāng)NestedScrollView到達滑動范圍的結(jié)束值的時候,滑動View剩下的部分開始滑動。這個折疊的高度是通過View的minimum height (最小高度)指定的
    補充說明:要配合scroll|enterAlways 一起使用

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
            />
    </android.support.design.widget.AppBarLayout>
enterAlwaysCollapsed
  • exitUntilCollapsed


    image.png

    當(dāng)ScrollView 滑出屏幕時(也就時向上滑動時),滑動View先響應(yīng)滑動事件,滑動至折疊高度,也就是通過minimum height 設(shè)置的最小高度后,就固定不動了,再把滑動事件交給 NestedScrollView 繼續(xù)滑動。

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            />
    </android.support.design.widget.AppBarLayout>
exitUntilCollapsed.gif
  • snap


    snap.png

    在滾動結(jié)束時,如果視圖只是部分可見,那么它將被斷開并滾動到它最接近的邊緣。例如,如果視圖只顯示底部的25%,那么它將會被完全關(guān)閉。相反,如果它的底部75%是可見的,那么它就會被完全地滾動到視圖中。

snap.gif

介紹一下AppbarLayout幾個常用且重要的方法

  • addOnOffsetChangedListener 當(dāng)AppbarLayout 的偏移發(fā)生改變的時候回調(diào),也就是子View滑動。
  • getTotalScrollRange 返回AppbarLayout 所有子View的滑動范圍
  • removeOnOffsetChangedListener 移除監(jiān)聽器
  • setExpanded (boolean expanded, boolean animate)設(shè)置AppbarLayout 是展開狀態(tài)還是折疊狀態(tài),animate 參數(shù)控制切換到新的狀態(tài)時是否需要動畫
  • setExpanded (boolean expanded) 設(shè)置AppbarLayout 是展開狀態(tài)還是折疊狀態(tài),默認有動畫

CollapsingToolbarLayout

CollapsingToolbarLayout .png

CollapsingToolbarLayout 是對Toolbar的包裝并且實現(xiàn)了折疊app bar效果,使用時,要作為 AppbarLayout 的直接子View。CollapsingToolbarLayout有以下特性:

  • Collapsing title


    image.png

    當(dāng)布局全部可見的時候,title 是最大的,當(dāng)布局開始滑出屏幕,title 將變得越來越小,你可以通過setTitle(CharSequence) 來設(shè)置要顯示的標(biāo)題。

  • Content scrim(內(nèi)容紗布)


    image.png

當(dāng)
CollapsingToolbarLayout.gif

滑動到一個確定的閥值時將顯示或者隱藏內(nèi)容紗布,可以通過setContentScrim(Drawable)來設(shè)置紗布的圖片。

提醒:紗布可以是圖片也可以是顏色色值,如果要顯示顏色,在xml 布局文件中用contentScrim屬性添加,代碼如下:app:contentScrim="@color/colorPrimary"

  • Status bar scrim(狀態(tài)欄紗布)


    image.png

當(dāng)CollapsingToolbarLayout滑動到一個確定的閥值時,狀態(tài)欄顯示或隱藏紗布,你可以通過setStatusBarScrim(Drawable)來設(shè)置紗布圖片。

  • Parallax scrolling children(有視差地滾動子View)


    image.png

    讓CollapsingToolbarLayout 的子View 可以有視差的滾動,需要在xml中用 添加如下代碼:

app:layout_collapseMode="parallax"

  • Pinned position children(固定子View的位置)


    image.png

    子View可以固定在全局空間內(nèi),這對于實現(xiàn)了折疊并且允許通過滾動布局來固定Toolbar 這種情況非常有用。在xml 中將collapseMode設(shè)為pin,代碼如下:

app:layout_collapseMode="pin"

接下來要實現(xiàn)這樣的效果:


CollapsingToolbarLayout.gif

布局

<?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:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/fruit_image_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android: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.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginTop="35dp"
                app:cardCornerRadius="4dp">

                <TextView
                    android:id="@+id/fruit_content_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp" />
            </android.support.v7.widget.CardView>
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_comment"
        app:layout_anchor="@id/appBar"
        app:layout_anchorGravity="bottom|end" />
</android.support.design.widget.CoordinatorLayout>

代碼:

package com.jimmy.xg.materialdesigndemo;

import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

public class FruitActivity extends AppCompatActivity {

    public static final String FRUIT_NAME = "fruit_name";

    public static final String FRUIT_IMAGE_ID = "fruit_image_id";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fruit);
        Intent intent = getIntent();
        String fruitName = intent.getStringExtra(FRUIT_NAME);
        int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID, 0);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        ImageView fruitImageView = (ImageView) findViewById(R.id.fruit_image_view);
        TextView fruitContentText = (TextView) findViewById(R.id.fruit_content_text);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
        collapsingToolbar.setTitle(fruitName);
        Glide.with(this).load(fruitImageId).into(fruitImageView);
        String fruitContent = generateFruitContent(fruitName);
        fruitContentText.setText(fruitContent);
    }

    private String generateFruitContent(String fruitName) {
        StringBuilder fruitContent = new StringBuilder();
        for (int i = 0; i < 500; i++) {
            fruitContent.append(fruitName);
        }
        return fruitContent.toString();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容