Ответ 1
Я не знаю, является ли это именно то, как это делает приложение Calendar, но оно достаточно близко для меня.
Предостережения
- Метод использует метод
ViewAnimationUtils.createCircularReveal
, введенный в Lollipop. - Для этого требуется знание высоты строки состояния и панели действий панели инструментов. Вы по-прежнему можете использовать
?attr/actionBarSize
для своей панели действий и динамически получать, но для простоты здесь я предположил56dp
для высоты панели действий и24dp
для высоты строки состояния.
Общая идея
Общая идея состоит в том, чтобы настроить панель действий и строку состояния прозрачной. Это переместит вашу панель действий под панелью состояния, поэтому вам нужно будет отрегулировать размер и дополнение панели действий для компенсации. Затем вы используете вид за ним и ViewAnimationUtils.createCircularReveal
, чтобы открыть новый цвет фона. Вам нужно еще один вид, чтобы показать старый цвет фона, поскольку средний вид показывает новый.
Анимация
Для анимации требуется:
- Прозрачная панель инструментов панель действий, которая охватывает пространство обычной панели действий и панели состояния. В этом случае жестко запрограммированная высота равна 56dp (панель действий) + 24dp (строка состояния) = 80dp. Вам также нужно установить верхнее дополнение на 24dp, чтобы содержимое нашего веб-сайта не отображалось в строке состояния.
- Среднее представление (я назову это показать представление) того же размера (высота 80dp), но только за панель действия. Это будет представление, на которое действует
ViewAnimationUtils.createCircularReveal
. - Вид снизу (я назову это показать фоном), который будет иметь тот же размер, что и просмотр, но за ним. В этом представлении отображается старый цвет фона, в то время как раскрывающийся вид показывает новый цвет поверх него.
Код
Вот ключевые фрагменты кода, который я использовал. См. Пример проекта https://github.com/shaun-blake-experiments/example-toolbar-animation.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<View
android:id="@+id/revealBackground"
android:layout_width="match_parent"
android:layout_height="80dp"
android:paddingTop="24dp"
android:background="@color/primary"
android:elevation="4dp">
</View>
<View
android:id="@+id/reveal"
android:layout_width="match_parent"
android:layout_height="80dp"
android:paddingTop="24dp"
android:background="@color/primary"
android:elevation="4dp">
</View>
<Toolbar
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="80dp"
android:paddingTop="24dp"
android:background="@android:color/transparent"
android:elevation="4dp"
android:theme="@style/TranslucentActionBar">
</Toolbar>
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Invert Toolbar Colors"
android:textOn="Invert Toolbar Colors On"
android:textOff="Invert Toolbar Colors Off"
android:id="@+id/toggleButton"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
styles.xml
<resources>
<style name="AppTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="TranslucentActionBar" parent="@android:style/Widget.Material.ActionBar">
<item name="android:textColorPrimary">@color/primary_text_dark_background</item>
</style>
</resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#2196F3</color>
<color name="primary_dark">#1976D2</color>
<color name="primary_light">#BBDEFB</color>
<color name="accent">#009688</color>
<color name="primary_text">#DD000000</color>
<color name="primary_text_dark_background">#FFFFFF</color>
<color name="secondary_text">#89000000</color>
<color name="icons">#FFFFFF</color>
<color name="divider">#30000000</color>
</resources>
MainActivity.java
package com.example.android.toolbaranimation;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.widget.ToggleButton;
import android.widget.Toolbar;
public class MainActivity extends Activity {
private View mRevealView;
private View mRevealBackgroundView;
private Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.appbar);
mToolbar.setTitle(getString(R.string.app_name));
mRevealView = findViewById(R.id.reveal);
mRevealBackgroundView = findViewById(R.id.revealBackground);
ToggleButton toggleButton = (ToggleButton) findViewById(R.id.toggleButton);
toggleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean on = ((ToggleButton) v).isChecked();
if (on) {
animateAppAndStatusBar(R.color.primary, R.color.accent);
} else {
animateAppAndStatusBar(R.color.accent, R.color.primary);
}
}
});
setActionBar(mToolbar);
}
private void animateAppAndStatusBar(int fromColor, final int toColor) {
Animator animator = ViewAnimationUtils.createCircularReveal(
mRevealView,
mToolbar.getWidth() / 2,
mToolbar.getHeight() / 2, 0,
mToolbar.getWidth() / 2);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mRevealView.setBackgroundColor(getResources().getColor(toColor));
}
});
mRevealBackgroundView.setBackgroundColor(getResources().getColor(fromColor));
animator.setStartDelay(200);
animator.setDuration(125);
animator.start();
mRevealView.setVisibility(View.VISIBLE);
}
}
Примечания
- Соблюдайте свойство
android:elevation
на панели инструментов, раскрывайте и показывайте фоновые представления. Если высота на панели инструментов меньше, остальные будут закрывать кнопки и текст.