滚动时带阴影效果的透明工具栏

Transparent toolbar on scrolling with shadow effect

我正在尝试获得类似于 google 消息应用程序中工具栏的效果。

基本上工具栏有一个纯色,当用户滚动时它变成透明底部有阴影。

我弄到了阴影效果,但是我弄不到透明效果。

这就是我要实现的目标:

这就是我能得到的:

这是我的 XML 带有工具栏的 AppBarLayout:

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:liftOnScroll="true">

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:minHeight="?attr/actionBarSize"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true"
    app:titleTextColor="@color/colorTextMain"
    android:background="@color/colorPrimary">
</androidx.appcompat.widget.Toolbar>

</com.google.android.material.appbar.AppBarLayout>

我认为你必须让你的应用栏位于一个视图上。 尝试这样的事情:

<androidx.constraintlayout.widget.ConstraintLayout android:layout_height="match_parent"
    android:layout_width="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/transparent_color"
        app:liftOnScroll="true">

        <androidx.appcompat.widget.Toolbar
            android:background="@color/colorPrimary"
            android:fitsSystemWindows="true"
            android:id="@+id/toolbar"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:background="@color/transparent_color"
            android:minHeight="?attr/actionBarSize"
            app:titleTextColor="@color/colorTextMain"/>

    </com.google.android.material.appbar.AppBarLayout>

    <fragment
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

解决方案

我得到了我想要的!我认为它更容易得到它,但是,我写了我的解决方案以防它有用并且有人想要改进它!

首先,google应用消息方式。

当用户不滚动时,工具栏高度为 0。

当用户滚动时,工具栏高度改变,整个工具栏和状态栏(注意状态栏)是透明的!

我的看起来怎么样?

让我们在 ToolBar、NestedScrollView 和 LinearLayout 中创建一个 CoordinatorLayout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:background="@color/colorPrimary">

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorToolbar"
    android:elevation="0dp"
    app:titleTextColor="@color/colorTextMain"
    android:fitsSystemWindows="true"/>

<androidx.core.widget.NestedScrollView
    android:id="@+id/myScroll"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/linear_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

      ... place page content here ...

    </LinearLayout>

</androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

现在,在您的 class OnCreate 方法中

    // find the toolbar view inside the activity layout
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    toolbar.setTitleTextAppearance(this, R.style.FontStyle);
    Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setDisplayShowHomeEnabled(true);
    getSupportActionBar().setTitle(getString(R.string.about));
    toolbar.setElevation(1); // required or it will overlap linear layout
    toolbar.setBackgroundColor(Color.TRANSPARENT); // required to delete elevation shadow

    // status bar height programmatically , notches...
    statusBarHeight = getStatusBarHeight();
    linearLayout = findViewById(R.id.linear_layout);
    linearLayout.setPadding(1,180+statusBarHeight,1,0);
    ViewGroup.LayoutParams params = toolbar.getLayoutParams();
    params.height = 180+statusBarHeight;
    toolbar.setLayoutParams(params);

由于我们有刘海屏 ( :-( ),我们必须以编程方式计算状态栏高度。默认状态栏高度为 24dp。不幸的是,并非所有刘海屏手机都使用 24dp。How to calculate status bar height programatically

现在我们需要处理工具栏提升,无论用户是否沿着页面移动。在你的 class OnCreate 方法中

NestedScrollView scroller = findViewById(R.id.myScroll);
    scroller.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {

        if (scrollY > oldScrollY) {
            // when user scrolls down set toolbar elevation to 4dp
            toolbar.setElevation(4);
            toolbar.setBackgroundColor(getColor(R.color.colorToolbar));
        }
        if (scrollY < oldScrollY) {
            // when user scrolls up keep toolbar elevation at 4dp
            toolbar.setElevation(4);
            toolbar.setBackgroundColor(getColor(R.color.colorToolbar));
        }

        if (scrollY == 0) {
            // if user is not scrolling it means
            // that he is at top of page 
            toolbar.setElevation(1); // required or it will overlap linear layout
            toolbar.setBackgroundColor(Color.TRANSPARENT); // required to delete elevation shadow
        }
    });

几乎完成!这是很关键的一环!再次进入你的 class OnCreate 方法

switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
        case Configuration.UI_MODE_NIGHT_YES:
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
            break;
        case Configuration.UI_MODE_NIGHT_NO:
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
            break;
    }

Configuration.UI_MODE_NIGHT_YES 和 Configuration.UI_MODE_NIGHT_NO:是一种处理深色和浅色主题的方法。由于我们要将页面的所有内容都放在状态栏上,因此我们将无法再控制状态栏图标的颜色(可通过样式获得),因此我们需要检测是否以编程方式启用了浅色或深色主题设置状态栏图标颜色!