MaterialDesign-大白话CollapsingToolbarLayout(可折叠式状态栏)以及综合效果

962 阅读3分钟

核心

  • 为了让我们随心所欲的制定我们想要的任意状态栏
  • 不能独立存在,设计之初就被限定只能作为AppBarLayout的直接子布局来使用
  • 而AppBarLayout又之能是CoordinatorLayout的子布局
  • 说白了,就一上滑效果,就是一堆谷歌自己封装的控件,我们拿来使用,就实现了酷酷的上滑效果而已

步骤

  • CoordinatorLayout嵌套AppBarLayout 说白了就一FrameLaytou视图头部上面放一个导航条而已
  • 在AppBarLayout中嵌套一个CollapsingToolbarLayout 说白了就是为了使得头部的视图触摸内容滚动的时候,头部上移而设计的玩意
  • 给CollapsingToolbarLayout制定黑色主题
  • 给CollapsingToolbarLayout制定layout_scrollFlags使其内容跟随滑动 scroll
  • 给CollapsingToolbarLayout的子控件设置layout_collapseMode,其中pin代表的意思是在折叠的过程中位置始终保持不变,parallax表示在折叠的过程中产生一定的错位偏移,这种模式的视觉效果比较好
  • 紧接着在AppBarLayout外面使用NestedScrollView或者其他可滚动的View,并制定其layout_behavior布局行为。说白了,就是只有内容是可滚动的,手指才能上滑,不是么??
  • 不过NestedScrollView只允许内部有一个子视图
  • 我们可以在内部嵌套一个LinearLayout
  • 设置沉浸式状态栏
  • 给可滚动的部分设置app:layout_behavior="@string/appbar_scrolling_view_behavior" 属性,这是最关键的一步,说白了就是设置了它,CoordinatorLayout这个最外面的布局,才知道,滑动悬停的玩意从哪里开始。再简单点理解,就是你想让哪一个子View消费你的滑动行为?也就是你手指触摸了哪个可以滚动的子View,但是呢,子View虽然可以滚动,但是先不滚动,让其他的子弹(View)飞一会,等到其他的View不能动了,蹦跶够了,你手指摸的那个View再开始滚动!!!
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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">
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="250dp">
        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:contentScrim="@color/design_default_color_primary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            >
            
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

theme、contentScrim、layout_scrollFlags

  • 1: Theme指定主题
  • 2:contentScrim 用于指定趋于折叠状态以及折叠状态的背景色
  • 3:layout_scrollFlags
  • scroll 随着内容滚动而滚动
  • exitUnitlCollapsed 随着内容滚动完成折叠之后保留在界面上,不再移出屏幕
  • enterAlways 导航条随着滚动滑出屏幕
  • enterAlwaysCollapsed 也是随着往上滚动滑出屏幕,但是下拉的时候是优先展示下面的内容,下面的内容下拉到不能滚动之后,才展示导航条,而enterAlways则是,下拉就直接先展示导航条,再展示内容,即使是内容被遮挡

视差效果layout_collapseMode

  • parallax 折叠过程产生错位偏移
  • pin 折叠过程中位置始终保持不变

NestedScrollView

  • 内部只允许一个子布局

FloatingButton

  • 通过anchor指定位置
<com.google.android.material.floatingactionbutton.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"
        />

详情页所有代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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">
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="250dp">
        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:contentScrim="@color/design_default_color_primary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            >
            <ImageView
                android:id="@+id/fruitImageView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                />
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                />
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>
    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        >
        <com.google.android.material.card.MaterialCardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="15dp"
            android:layout_marginTop="35dp"
            android:layout_marginEnd="15dp"
            android:layout_marginStart="15dp"
            app:cardCornerRadius="4dp"
            >
            <TextView
                android:id="@+id/fruitContentTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                />
        </com.google.android.material.card.MaterialCardView>
    </androidx.core.widget.NestedScrollView>

    <com.google.android.material.floatingactionbutton.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"
        />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
  • 控制器
package com.example.materialdesigndemo

import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_fruit.*
import kotlinx.android.synthetic.main.fruit_item.*

class FruitActivity: AppCompatActivity() {

    companion object {
        const val FRUIT_NAME = "fruit_name"
        const val FRUIT_IMAGE_ID = "fruit_image_id"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_fruit)

        setSupportActionBar(toolbar)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        val fruitName = intent.getStringExtra(FRUIT_NAME) ?: ""
        val fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID, 0)
        collapsingToolbar.title = fruitName
        Glide.with(this)
                .load(fruitImageId)
                .into(fruitImageView)
        fruitContentTv.text = generateFruitContent(fruitName)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> {
                finish()
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }

    private fun generateFruitContent(fruitName: String): CharSequence? {
        return fruitName.repeat(500)
    }
}