mirror of
https://github.com/material-components/material-components-android.git
synced 2026-02-20 08:39:55 +08:00
212 lines
11 KiB
Java
212 lines
11 KiB
Java
/*
|
|
* Copyright 2023 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.carousel;
|
|
|
|
import com.google.android.material.test.R;
|
|
|
|
import static com.google.android.material.carousel.CarouselHelper.createCarouselWithWidth;
|
|
import static com.google.android.material.carousel.CarouselHelper.createCenterAlignedCarouselWithSize;
|
|
import static com.google.android.material.carousel.CarouselHelper.createViewWithSize;
|
|
import static com.google.android.material.carousel.CarouselStrategyHelper.getSmallSizeMin;
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
|
|
import android.view.View;
|
|
import androidx.test.core.app.ApplicationProvider;
|
|
import com.google.common.collect.Iterables;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.robolectric.RobolectricTestRunner;
|
|
|
|
/** Tests for {@link UncontainedCarouselStrategy}. */
|
|
@RunWith(RobolectricTestRunner.class)
|
|
public class UncontainedCarouselStrategyTest {
|
|
|
|
@Test
|
|
public void testLargeItem_withFullCarouselWidth() {
|
|
Carousel carousel = createCarouselWithWidth(400);
|
|
UncontainedCarouselStrategy config = setupStrategy();
|
|
View view = createViewWithSize(ApplicationProvider.getApplicationContext(), 400, 400);
|
|
|
|
KeylineState keylineState = config.onFirstChildMeasuredWithMargins(carousel, view);
|
|
float xSmallSize =
|
|
view.getResources().getDimension(R.dimen.m3_carousel_gone_size);
|
|
|
|
// A fullscreen layout should be [xSmall-large-xSmall] where the xSmall items are
|
|
// outside the bounds of the carousel container and the large item takes up the
|
|
// containers full width.
|
|
assertThat(keylineState.getKeylines()).hasSize(3);
|
|
assertThat(keylineState.getKeylines().get(0).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(2).locOffset)
|
|
.isEqualTo(carousel.getContainerWidth() + xSmallSize / 2F);
|
|
}
|
|
|
|
@Test
|
|
public void testLargeItem_largerThanFullCarouselWidth() {
|
|
Carousel carousel = createCarouselWithWidth(400);
|
|
UncontainedCarouselStrategy config = setupStrategy();
|
|
int cutOff = 10;
|
|
View view = createViewWithSize(ApplicationProvider.getApplicationContext(), 400 + cutOff, 400);
|
|
|
|
KeylineState keylineState = config.onFirstChildMeasuredWithMargins(carousel, view);
|
|
|
|
// The layout should be [xSmall-large-xSmall] where the xSmall items are
|
|
// outside the bounds of the carousel container and the large item takes up the
|
|
// containers full width.
|
|
assertThat(keylineState.getKeylines()).hasSize(3);
|
|
assertThat(keylineState.getKeylines().get(0).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).mask).isEqualTo(0F);
|
|
assertThat(Iterables.getLast(keylineState.getKeylines()).locOffset)
|
|
.isGreaterThan((float) carousel.getContainerWidth());
|
|
}
|
|
|
|
@Test
|
|
public void testRemainingSpaceWithItemSize_fitsItemWithThirdCutoff() {
|
|
Carousel carousel = createCarouselWithWidth(400);
|
|
UncontainedCarouselStrategy config = setupStrategy();
|
|
// With size 125px, 3 large items can fit with in 400px, with 25px left. 25px * 3 = 75px, which
|
|
// will be the size of the medium item since it can be a third cut off and it is less than the
|
|
// threshold percentage * large item size.
|
|
View view = createViewWithSize(ApplicationProvider.getApplicationContext(), 125, 400);
|
|
|
|
KeylineState keylineState = config.onFirstChildMeasuredWithMargins(carousel, view);
|
|
|
|
// The layout should be [xSmall-large-large-large-medium-xSmall] where medium is a size
|
|
// such that a third of it is cut off.
|
|
assertThat(keylineState.getKeylines()).hasSize(6);
|
|
assertThat(keylineState.getKeylines().get(0).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(2).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(3).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(4).locOffset)
|
|
.isLessThan((float) carousel.getContainerWidth());
|
|
assertThat(Iterables.getLast(keylineState.getKeylines()).locOffset)
|
|
.isGreaterThan((float) carousel.getContainerWidth());
|
|
}
|
|
|
|
@Test
|
|
public void testRemainingSpaceWithItemSize_fitsMediumItemWithCutoff() {
|
|
Carousel carousel = createCarouselWithWidth(400);
|
|
UncontainedCarouselStrategy config = setupStrategy();
|
|
int itemSize = 105;
|
|
// With size 105px, 3 large items can fit with in 400px, with 85px left over. 85*3 = 255 which
|
|
// is well over the size of the large item, so the medium size will be limited to whichever is
|
|
// larger between 85% of the large size, or 110% of the remainingSpace to make it at most
|
|
// 10% cut off.
|
|
View view = createViewWithSize(ApplicationProvider.getApplicationContext(), itemSize, 400);
|
|
|
|
KeylineState keylineState = config.onFirstChildMeasuredWithMargins(carousel, view);
|
|
|
|
// The layout should be [xSmall-large-large-large-medium-xSmall]
|
|
assertThat(keylineState.getKeylines()).hasSize(6);
|
|
assertThat(keylineState.getKeylines().get(0).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(2).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(3).mask).isEqualTo(0F);
|
|
// remainingSpace * 120%
|
|
assertThat(keylineState.getKeylines().get(4).maskedItemSize).isEqualTo(85*1.2F);
|
|
assertThat(Iterables.getLast(keylineState.getKeylines()).locOffset)
|
|
.isGreaterThan((float) carousel.getContainerWidth());
|
|
}
|
|
|
|
@Test
|
|
public void testCenterAligned_defaultKeylineHasTwoCutoffs() {
|
|
Carousel carousel = createCenterAlignedCarouselWithSize(400);
|
|
UncontainedCarouselStrategy config = setupStrategy();
|
|
int itemSize = 250;
|
|
// With this item size, we have 400 - 250 = 150 remaining space which means 75 on each side
|
|
// of one focal item.
|
|
View view = createViewWithSize(ApplicationProvider.getApplicationContext(), itemSize, 400);
|
|
|
|
KeylineState keylineState = config.onFirstChildMeasuredWithMargins(carousel, view);
|
|
|
|
// The layout should be [xSmall-medium-large-medium-xSmall]
|
|
assertThat(keylineState.getKeylines()).hasSize(5);
|
|
assertThat(keylineState.getKeylines().get(0).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).cutoff)
|
|
.isEqualTo(150F); // 75*2 since 2/3 should be cut off
|
|
assertThat(keylineState.getKeylines().get(2).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(3).cutoff)
|
|
.isEqualTo(150F); // 75*2 since 2/3 should be cut off
|
|
assertThat(keylineState.getKeylines().get(4).locOffset)
|
|
.isGreaterThan((float) carousel.getContainerWidth());
|
|
}
|
|
|
|
@Test
|
|
public void testCenterAligned_cutoffMinSize() {
|
|
Carousel carousel = createCenterAlignedCarouselWithSize(400);
|
|
UncontainedCarouselStrategy config = setupStrategy();
|
|
int itemSize = 200;
|
|
// 2 items fit perfectly in the width so there is no remaining space. Medium items should still
|
|
// be the minimum item mask size.
|
|
View view = createViewWithSize(ApplicationProvider.getApplicationContext(), itemSize, 400);
|
|
|
|
KeylineState keylineState = config.onFirstChildMeasuredWithMargins(carousel, view);
|
|
|
|
float minSmallSize = getSmallSizeMin(ApplicationProvider.getApplicationContext());
|
|
|
|
// The layout should be [xSmall-medium-large-large-medium-xSmall]
|
|
assertThat(keylineState.getKeylines()).hasSize(6);
|
|
assertThat(keylineState.getKeylines().get(0).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).cutoff)
|
|
.isEqualTo(keylineState.getKeylines().get(1).maskedItemSize);
|
|
assertThat(keylineState.getKeylines().get(1).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).maskedItemSize).isEqualTo(minSmallSize);
|
|
assertThat(keylineState.getKeylines().get(2).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(3).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(4).cutoff)
|
|
.isEqualTo(keylineState.getKeylines().get(1).maskedItemSize);
|
|
assertThat(keylineState.getKeylines().get(4).locOffset)
|
|
.isGreaterThan((float) carousel.getContainerWidth());
|
|
assertThat(keylineState.getKeylines().get(4).maskedItemSize).isEqualTo(minSmallSize);
|
|
assertThat(keylineState.getKeylines().get(5).locOffset)
|
|
.isGreaterThan((float) carousel.getContainerWidth());
|
|
}
|
|
|
|
@Test
|
|
public void testCenterAligned_cutoffMaxSize() {
|
|
Carousel carousel = createCenterAlignedCarouselWithSize(400);
|
|
UncontainedCarouselStrategy config = setupStrategy();
|
|
int itemSize = 140;
|
|
// 2 items fit into width of 400 with 120 remaining space; 60 on each side. Only a 1/3 should be
|
|
// showing which means an item width of 180 for the cut off items, but we do not want these
|
|
// items to be bigger than the focal item so the max item size should be the focal item size.
|
|
View view = createViewWithSize(ApplicationProvider.getApplicationContext(), itemSize, 400);
|
|
|
|
KeylineState keylineState = config.onFirstChildMeasuredWithMargins(carousel, view);
|
|
|
|
// The layout should be [xSmall-medium-large-large-medium-xSmall]
|
|
assertThat(keylineState.getKeylines()).hasSize(6);
|
|
assertThat(keylineState.getKeylines().get(0).locOffset).isLessThan(0F);
|
|
assertThat(keylineState.getKeylines().get(1).maskedItemSize).isEqualTo((float) itemSize);
|
|
// Item size should be max size: 180F, so 140 - 60 (remaining space) = 80
|
|
assertThat(keylineState.getKeylines().get(1).cutoff).isEqualTo(80F);
|
|
assertThat(keylineState.getKeylines().get(2).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(3).mask).isEqualTo(0F);
|
|
assertThat(keylineState.getKeylines().get(4).maskedItemSize).isEqualTo((float) itemSize);
|
|
// Item size should be max size: 180F, so 140 - 60 (remaining space) = 80
|
|
assertThat(keylineState.getKeylines().get(4).cutoff).isEqualTo(80F);
|
|
assertThat(keylineState.getKeylines().get(5).locOffset)
|
|
.isGreaterThan((float) carousel.getContainerWidth());
|
|
}
|
|
|
|
private UncontainedCarouselStrategy setupStrategy() {
|
|
UncontainedCarouselStrategy strategy = new UncontainedCarouselStrategy();
|
|
strategy.initialize(ApplicationProvider.getApplicationContext());
|
|
return strategy;
|
|
}
|
|
}
|