mirror of
https://github.com/material-components/material-components-android.git
synced 2026-02-20 08:39:55 +08:00
199 lines
7.8 KiB
Java
199 lines
7.8 KiB
Java
/*
|
|
* Copyright (C) 2022 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
|
|
*
|
|
* http://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.motion;
|
|
|
|
import com.google.android.material.test.R;
|
|
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
import static org.junit.Assert.assertThrows;
|
|
|
|
import android.animation.TimeInterpolator;
|
|
import android.content.Context;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import android.view.animation.AccelerateInterpolator;
|
|
import android.view.animation.AnimationUtils;
|
|
import android.view.animation.Interpolator;
|
|
import android.view.animation.LinearInterpolator;
|
|
import android.view.animation.PathInterpolator;
|
|
import androidx.core.content.res.ResourcesCompat;
|
|
import androidx.dynamicanimation.animation.SpringForce;
|
|
import androidx.test.core.app.ApplicationProvider;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.rules.ExpectedException;
|
|
import org.junit.runner.RunWith;
|
|
import org.robolectric.Robolectric;
|
|
import org.robolectric.RobolectricTestRunner;
|
|
import org.robolectric.android.controller.ActivityController;
|
|
import org.robolectric.annotation.Config;
|
|
import org.robolectric.annotation.internal.DoNotInstrument;
|
|
import org.robolectric.shadow.api.Shadow;
|
|
|
|
@RunWith(RobolectricTestRunner.class)
|
|
@Config(sdk = Config.OLDEST_SDK)
|
|
@DoNotInstrument
|
|
public class MotionUtilsTest {
|
|
|
|
private ActivityController<AppCompatActivity> activityController;
|
|
|
|
@Rule public final ExpectedException thrown = ExpectedException.none();
|
|
|
|
@Test
|
|
public void testResolvesThemeSpring() {
|
|
createActivityAndSetTheme(R.style.Theme_Material3_DayNight);
|
|
Context context = activityController.get().getApplicationContext();
|
|
float expectedStiffness = ResourcesCompat.getFloat(
|
|
context.getResources(), R.dimen.m3_sys_motion_standard_spring_fast_spatial_stiffness);
|
|
float expectedDampingRatio = ResourcesCompat.getFloat(
|
|
context.getResources(), R.dimen.m3_sys_motion_standard_spring_fast_spatial_damping);
|
|
SpringForce spring = MotionUtils.resolveThemeSpringForce(context,
|
|
R.attr.motionSpringFastSpatial, R.style.Motion_Material3_Spring_Standard_Fast_Spatial);
|
|
|
|
assertThat(spring.getStiffness()).isEqualTo(expectedStiffness);
|
|
assertThat(spring.getDampingRatio()).isEqualTo(expectedDampingRatio);
|
|
}
|
|
|
|
@Test
|
|
public void testAbsentThemeSpring_shouldResolveDefault() {
|
|
createActivityAndSetTheme(R.style.Theme_AppCompat_DayNight);
|
|
Context context = activityController.get().getApplicationContext();
|
|
|
|
SpringForce spring = MotionUtils.resolveThemeSpringForce(context,
|
|
R.attr.motionSpringFastSpatial, R.style.Motion_MyApp_Spring_Custom_Default);
|
|
|
|
assertThat(spring.getStiffness()).isEqualTo(1450f);
|
|
assertThat(spring.getDampingRatio()).isEqualTo(0.5f);
|
|
}
|
|
|
|
@Test
|
|
public void testPartialSpring_shouldThrow() {
|
|
createActivityAndSetTheme(R.style.Theme_Material3_DayNight_PartialSpring);
|
|
Context context = activityController.get().getApplicationContext();
|
|
|
|
IllegalArgumentException thrown = assertThrows(
|
|
IllegalArgumentException.class,
|
|
() -> MotionUtils.resolveThemeSpringForce(context, R.attr.motionSpringFastSpatial,
|
|
R.style.Motion_Material3_Spring_Standard_Fast_Spatial)
|
|
);
|
|
assertThat(thrown).hasMessageThat().contains("must have a damping");
|
|
}
|
|
|
|
@Test
|
|
public void testResolvesThemeInterpolator() {
|
|
assertThemeInterpolatorIsInstanceOf(
|
|
R.style.Theme_Material3_DayNight,
|
|
R.attr.motionEasingStandardInterpolator,
|
|
isAnimationUtilsShadowed() ? LinearInterpolator.class : PathInterpolator.class);
|
|
}
|
|
|
|
@Test
|
|
public void testCustomInterpolator_resolvesThemeInterpolator() {
|
|
assertThemeInterpolatorIsInstanceOf(
|
|
R.style.Theme_Material3_DayNight_CustomInterpolator,
|
|
R.attr.motionEasingStandardInterpolator,
|
|
isAnimationUtilsShadowed() ? LinearInterpolator.class : PathInterpolator.class);
|
|
}
|
|
|
|
@Test
|
|
public void testCustomAnimInterpolator_resolvesThemeInterpolator() {
|
|
assertThemeInterpolatorIsInstanceOf(
|
|
R.style.Theme_Material3_DayNight_CustomAnimInterpolator,
|
|
R.attr.motionEasingStandardInterpolator,
|
|
isAnimationUtilsShadowed() ? LinearInterpolator.class : AccelerateInterpolator.class);
|
|
}
|
|
|
|
@Test
|
|
public void testResolvesLegacyInterpolator() {
|
|
assertThemeInterpolatorIsInstanceOf(
|
|
R.style.Theme_Material3_DayNight, R.attr.motionEasingStandard, PathInterpolator.class);
|
|
}
|
|
|
|
@Test
|
|
public void testMaterialComponentsTheme_resolveUnavailableInterpolatorReturnsDefault() {
|
|
createActivityAndSetTheme(R.style.Theme_MaterialComponents_DayNight);
|
|
|
|
DefaultDummyInterpolator defaultInterpolator = new DefaultDummyInterpolator();
|
|
TimeInterpolator standardInterpolator =
|
|
MotionUtils.resolveThemeInterpolator(
|
|
activityController.get().getApplicationContext(),
|
|
R.attr.motionEasingStandardInterpolator,
|
|
defaultInterpolator);
|
|
assertThat(standardInterpolator).isEqualTo(defaultInterpolator);
|
|
}
|
|
|
|
@Test
|
|
public void testMaterialComponentsTheme_resolvesLegacyInterpolator() {
|
|
assertThemeInterpolatorIsInstanceOf(
|
|
R.style.Theme_MaterialComponents_DayNight,
|
|
R.attr.motionEasingStandard,
|
|
PathInterpolator.class);
|
|
}
|
|
|
|
@Test
|
|
public void testMaterialComponentsThemeIncorrectLegacyAttrType_shouldThrowException() {
|
|
createActivityAndSetTheme(
|
|
R.style.Theme_MaterialComponents_DayNight_IncorrectLegacyEasingAttrType);
|
|
|
|
// ThrowingRunnable used by assertThrows is not available until gradle 4.13
|
|
thrown.expect(IllegalArgumentException.class);
|
|
MotionUtils.resolveThemeInterpolator(
|
|
activityController.get().getApplicationContext(),
|
|
R.attr.motionEasingStandard,
|
|
new DefaultDummyInterpolator());
|
|
}
|
|
|
|
@Test
|
|
public void testMaterialComponentsThemeIncorrectLegacyFormatting_shouldThrowException() {
|
|
createActivityAndSetTheme(
|
|
R.style.Theme_MaterialComponents_DayNight_IncorrectLegacyEasingFormat);
|
|
|
|
// ThrowingRunnable used by assertThrows is not available until gradle 4.13
|
|
thrown.expect(IllegalArgumentException.class);
|
|
MotionUtils.resolveThemeInterpolator(
|
|
activityController.get().getApplicationContext(),
|
|
R.attr.motionEasingStandard,
|
|
new DefaultDummyInterpolator());
|
|
}
|
|
|
|
private boolean isAnimationUtilsShadowed() {
|
|
return Shadow.extract(new AnimationUtils()) != null;
|
|
}
|
|
|
|
private void createActivityAndSetTheme(int themeId) {
|
|
ApplicationProvider.getApplicationContext().setTheme(themeId);
|
|
activityController = Robolectric.buildActivity(AppCompatActivity.class).create();
|
|
}
|
|
|
|
private void assertThemeInterpolatorIsInstanceOf(int theme, int attrId, Class<?> expectedClass) {
|
|
createActivityAndSetTheme(theme);
|
|
DefaultDummyInterpolator defaultInterpolator = new DefaultDummyInterpolator();
|
|
TimeInterpolator themeInterpolator =
|
|
MotionUtils.resolveThemeInterpolator(
|
|
activityController.get().getApplicationContext(), attrId, defaultInterpolator);
|
|
assertThat(themeInterpolator).isNotEqualTo(defaultInterpolator);
|
|
// Robolectric's shadow of Android's AnimationUtils always returns a LinearInterpolator.
|
|
assertThat(themeInterpolator).isInstanceOf(expectedClass);
|
|
}
|
|
|
|
private static class DefaultDummyInterpolator implements Interpolator {
|
|
@Override
|
|
public float getInterpolation(float input) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|