mirror of
https://github.com/material-components/material-components-android.git
synced 2026-01-16 18:01:42 +08:00
192 lines
6.2 KiB
Java
192 lines
6.2 KiB
Java
/*
|
|
* Copyright 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.google.android.material.transition;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.AnimatorListenerAdapter;
|
|
import android.animation.ObjectAnimator;
|
|
import android.animation.PropertyValuesHolder;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
|
|
/**
|
|
* A class that configures and is able to provide an {@link Animator} that scales a view.
|
|
*
|
|
* <p>{@code ScaleProvider}'s constructor optionally takes a {@code growing} parameter. By default,
|
|
* this is set to true and will increase the size of the target both when appearing and
|
|
* disappearing. This is useful when pairing two animating targets, one appearing and one
|
|
* disappearing, that should both be either growing or shrinking to create a visual relationship.
|
|
*/
|
|
public final class ScaleProvider implements VisibilityAnimatorProvider {
|
|
|
|
private float outgoingStartScale = 1f;
|
|
private float outgoingEndScale = 1.1f;
|
|
private float incomingStartScale = 0.8f;
|
|
private float incomingEndScale = 1f;
|
|
|
|
private boolean growing;
|
|
private boolean scaleOnDisappear = true;
|
|
|
|
public ScaleProvider() {
|
|
this(true);
|
|
}
|
|
|
|
public ScaleProvider(boolean growing) {
|
|
this.growing = growing;
|
|
}
|
|
|
|
/** Whether or not this animation's target will grow or shrink in size. */
|
|
public boolean isGrowing() {
|
|
return growing;
|
|
}
|
|
|
|
/** Set whether or not this animation's target will grow or shrink in size. */
|
|
public void setGrowing(boolean growing) {
|
|
this.growing = growing;
|
|
}
|
|
|
|
/**
|
|
* Whether or not a scale animation will be run on this animation's target when disappearing.
|
|
*
|
|
* @see #setScaleOnDisappear(boolean)
|
|
*/
|
|
public boolean isScaleOnDisappear() {
|
|
return scaleOnDisappear;
|
|
}
|
|
|
|
/**
|
|
* Set whether or not a scale animation will be run on this animation's target when disappearing.
|
|
*
|
|
* <p>This is useful when using a single {@code ScaleProvider} that runs on multiple targets and
|
|
* only appearing targets should be animated.
|
|
*/
|
|
public void setScaleOnDisappear(boolean scaleOnDisappear) {
|
|
this.scaleOnDisappear = scaleOnDisappear;
|
|
}
|
|
|
|
/**
|
|
* The scale x and scale y value which an appearing and shrinking target will scale to and a
|
|
* disappearing and growing target will scale from.
|
|
*/
|
|
public float getOutgoingStartScale() {
|
|
return outgoingStartScale;
|
|
}
|
|
|
|
/**
|
|
* Set the scale x and scale y value which an appearing and shrinking target should scale to and a
|
|
* disappearing and growing target should scale from.
|
|
*/
|
|
public void setOutgoingStartScale(float outgoingStartScale) {
|
|
this.outgoingStartScale = outgoingStartScale;
|
|
}
|
|
|
|
/**
|
|
* The scale x and scale y value which an appearing and shrinking target will scale from and a
|
|
* disappearing and growing target will scale to.
|
|
*/
|
|
public float getOutgoingEndScale() {
|
|
return outgoingEndScale;
|
|
}
|
|
|
|
/**
|
|
* Set the scale x and scale y value which an appearing and shrinking target should scale from and
|
|
* a disappearing and growing target should scale to.
|
|
*/
|
|
public void setOutgoingEndScale(float outgoingEndScale) {
|
|
this.outgoingEndScale = outgoingEndScale;
|
|
}
|
|
|
|
/**
|
|
* The scale x and scale y value which an appearing and growing target will scale from and a
|
|
* disappearing and shrinking target will scale to.
|
|
*/
|
|
public float getIncomingStartScale() {
|
|
return incomingStartScale;
|
|
}
|
|
|
|
/**
|
|
* Set the scale x and scale y value which an appearing and growing target should scale from and a
|
|
* disappearing and shrinking target should scale to.
|
|
*/
|
|
public void setIncomingStartScale(float incomingStartScale) {
|
|
this.incomingStartScale = incomingStartScale;
|
|
}
|
|
|
|
/**
|
|
* The scale x and scale y value which an appearing and growing target will scale to and a
|
|
* disappearing and shrinking target will scale from.
|
|
*/
|
|
public float getIncomingEndScale() {
|
|
return incomingEndScale;
|
|
}
|
|
|
|
/**
|
|
* Set the scale x and scale y value which an appearing and growing target should scale to and a
|
|
* disappearing and shrinking target should scale from.
|
|
*/
|
|
public void setIncomingEndScale(float incomingEndScale) {
|
|
this.incomingEndScale = incomingEndScale;
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public Animator createAppear(@NonNull ViewGroup sceneRoot, @NonNull View view) {
|
|
if (growing) {
|
|
return createScaleAnimator(view, incomingStartScale, incomingEndScale);
|
|
} else {
|
|
return createScaleAnimator(view, outgoingEndScale, outgoingStartScale);
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public Animator createDisappear(@NonNull ViewGroup sceneRoot, @NonNull View view) {
|
|
if (!scaleOnDisappear) {
|
|
return null;
|
|
}
|
|
|
|
if (growing) {
|
|
return createScaleAnimator(view, outgoingStartScale, outgoingEndScale);
|
|
} else {
|
|
return createScaleAnimator(view, incomingEndScale, incomingStartScale);
|
|
}
|
|
}
|
|
|
|
private static Animator createScaleAnimator(final View view, float startScale, float endScale) {
|
|
final float originalScaleX = view.getScaleX();
|
|
final float originalScaleY = view.getScaleY();
|
|
ObjectAnimator animator =
|
|
ObjectAnimator.ofPropertyValuesHolder(
|
|
view,
|
|
PropertyValuesHolder.ofFloat(
|
|
View.SCALE_X, originalScaleX * startScale, originalScaleX * endScale),
|
|
PropertyValuesHolder.ofFloat(
|
|
View.SCALE_Y, originalScaleY * startScale, originalScaleY * endScale));
|
|
animator.addListener(
|
|
new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
view.setScaleX(originalScaleX);
|
|
view.setScaleY(originalScaleY);
|
|
}
|
|
});
|
|
return animator;
|
|
}
|
|
}
|