Reputation: 787
I'm trying to get an effect similar to that of the toolbar in the google messages app.
Basically the toolbar has a solid color and when the user scrolls it becomes transparent with a shadow at the bottom.
I managed to get a shadow effect but I can't get the transparent effect.
This is what I'm trying to achieve:
This is my XML AppBarLayout with toolbar:
<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>
Upvotes: 4
Views: 1805
Reputation: 787
Solution
I managed to get what I wanted! I thought it was easier to get it, however, i write my solution in case it is useful and if someone wants to improve it!
First, google app messages way to do it.
When the user does not scroll, toolbar elevation is 0.
When the user scrolls, toolbar elevation is changed and the entire toolbar and status bar (notice status bar) are transparent!
Let's create a CoordinatorLayout with inside a ToolBar, NestedScrollView and a LinearLayout:
<?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>
Now, inside your class OnCreate method
// 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);
Since we have notches ( :-( ), we have to calculate status bar height programatically. By default status bar height is 24dp. Unfortunately not all notch phones use 24dp. How to calculate status bar height programatically
Now we need to handle toolbar elevation whether the user moves along the page or not. Inside your class OnCreate method
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
}
});
Almost done! This is a crucial part! Again inside your class OnCreate method
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 and Configuration.UI_MODE_NIGHT_NO: are a way to handle dark and light theme. Since we are going to put all the entire content of the page on the status bar we won't have control anymore of status bar icons colors (obtainable via styles) and so we need to detect if a light or dark theme is enabled for programatically set status bar icons colors!
Upvotes: 2
Reputation: 239
I think you have to make your appbar lay on a piece of view. Try something like that:
<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>
Upvotes: 1