ADD week 5
This commit is contained in:
@ -0,0 +1,131 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import androidx.core.math.MathUtils;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
final class Arrangement {
|
||||
private static final float MEDIUM_ITEM_FLEX_PERCENTAGE = 0.1f;
|
||||
final float cost;
|
||||
final int largeCount;
|
||||
float largeSize;
|
||||
int mediumCount;
|
||||
float mediumSize;
|
||||
final int priority;
|
||||
int smallCount;
|
||||
float smallSize;
|
||||
|
||||
private float calculateLargeSize(float f, int i, float f2, int i2, int i3) {
|
||||
if (i <= 0) {
|
||||
f2 = 0.0f;
|
||||
}
|
||||
float f3 = i2 / 2.0f;
|
||||
return (f - ((i + f3) * f2)) / (i3 + f3);
|
||||
}
|
||||
|
||||
private float getSpace() {
|
||||
return (this.largeSize * this.largeCount) + (this.mediumSize * this.mediumCount) + (this.smallSize * this.smallCount);
|
||||
}
|
||||
|
||||
private boolean isValid() {
|
||||
int i = this.largeCount;
|
||||
if (i <= 0 || this.smallCount <= 0 || this.mediumCount <= 0) {
|
||||
return i <= 0 || this.smallCount <= 0 || this.largeSize > this.smallSize;
|
||||
}
|
||||
float f = this.largeSize;
|
||||
float f2 = this.mediumSize;
|
||||
return f > f2 && f2 > this.smallSize;
|
||||
}
|
||||
|
||||
int getItemCount() {
|
||||
return this.smallCount + this.mediumCount + this.largeCount;
|
||||
}
|
||||
|
||||
Arrangement(int i, float f, float f2, float f3, int i2, float f4, int i3, float f5, int i4, float f6) {
|
||||
this.priority = i;
|
||||
this.smallSize = MathUtils.clamp(f, f2, f3);
|
||||
this.smallCount = i2;
|
||||
this.mediumSize = f4;
|
||||
this.mediumCount = i3;
|
||||
this.largeSize = f5;
|
||||
this.largeCount = i4;
|
||||
fit(f6, f2, f3, f5);
|
||||
this.cost = cost(f5);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Arrangement [priority=" + this.priority + ", smallCount=" + this.smallCount + ", smallSize=" + this.smallSize + ", mediumCount=" + this.mediumCount + ", mediumSize=" + this.mediumSize + ", largeCount=" + this.largeCount + ", largeSize=" + this.largeSize + ", cost=" + this.cost + "]";
|
||||
}
|
||||
|
||||
private void fit(float f, float f2, float f3, float f4) {
|
||||
float space = f - getSpace();
|
||||
int i = this.smallCount;
|
||||
if (i > 0 && space > 0.0f) {
|
||||
float f5 = this.smallSize;
|
||||
this.smallSize = f5 + Math.min(space / i, f3 - f5);
|
||||
} else if (i > 0 && space < 0.0f) {
|
||||
float f6 = this.smallSize;
|
||||
this.smallSize = f6 + Math.max(space / i, f2 - f6);
|
||||
}
|
||||
int i2 = this.smallCount;
|
||||
float f7 = i2 > 0 ? this.smallSize : 0.0f;
|
||||
this.smallSize = f7;
|
||||
float calculateLargeSize = calculateLargeSize(f, i2, f7, this.mediumCount, this.largeCount);
|
||||
this.largeSize = calculateLargeSize;
|
||||
float f8 = (this.smallSize + calculateLargeSize) / 2.0f;
|
||||
this.mediumSize = f8;
|
||||
int i3 = this.mediumCount;
|
||||
if (i3 <= 0 || calculateLargeSize == f4) {
|
||||
return;
|
||||
}
|
||||
float f9 = (f4 - calculateLargeSize) * this.largeCount;
|
||||
float min = Math.min(Math.abs(f9), f8 * 0.1f * i3);
|
||||
if (f9 > 0.0f) {
|
||||
this.mediumSize -= min / this.mediumCount;
|
||||
this.largeSize += min / this.largeCount;
|
||||
} else {
|
||||
this.mediumSize += min / this.mediumCount;
|
||||
this.largeSize -= min / this.largeCount;
|
||||
}
|
||||
}
|
||||
|
||||
private float cost(float f) {
|
||||
if (isValid()) {
|
||||
return Math.abs(f - this.largeSize) * this.priority;
|
||||
}
|
||||
return Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
static Arrangement findLowestCostArrangement(float f, float f2, float f3, float f4, int[] iArr, float f5, int[] iArr2, float f6, int[] iArr3) {
|
||||
Arrangement arrangement = null;
|
||||
int i = 1;
|
||||
for (int i2 : iArr3) {
|
||||
int length = iArr2.length;
|
||||
int i3 = 0;
|
||||
while (i3 < length) {
|
||||
int i4 = iArr2[i3];
|
||||
int length2 = iArr.length;
|
||||
int i5 = 0;
|
||||
while (i5 < length2) {
|
||||
int i6 = i5;
|
||||
int i7 = length2;
|
||||
int i8 = i3;
|
||||
int i9 = length;
|
||||
Arrangement arrangement2 = new Arrangement(i, f2, f3, f4, iArr[i5], f5, i4, f6, i2, f);
|
||||
if (arrangement == null || arrangement2.cost < arrangement.cost) {
|
||||
if (arrangement2.cost == 0.0f) {
|
||||
return arrangement2;
|
||||
}
|
||||
arrangement = arrangement2;
|
||||
}
|
||||
i++;
|
||||
i5 = i6 + 1;
|
||||
length2 = i7;
|
||||
i3 = i8;
|
||||
length = i9;
|
||||
}
|
||||
i3++;
|
||||
}
|
||||
}
|
||||
return arrangement;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
interface Carousel {
|
||||
int getCarouselAlignment();
|
||||
|
||||
int getContainerHeight();
|
||||
|
||||
int getContainerWidth();
|
||||
|
||||
int getItemCount();
|
||||
|
||||
boolean isHorizontal();
|
||||
}
|
@ -0,0 +1,965 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.math.MathUtils;
|
||||
import androidx.core.util.Preconditions;
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.R;
|
||||
import com.google.android.material.animation.AnimationUtils;
|
||||
import com.google.android.material.carousel.KeylineState;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class CarouselLayoutManager extends RecyclerView.LayoutManager implements Carousel, RecyclerView.SmoothScroller.ScrollVectorProvider {
|
||||
public static final int ALIGNMENT_CENTER = 1;
|
||||
public static final int ALIGNMENT_START = 0;
|
||||
public static final int HORIZONTAL = 0;
|
||||
private static final String TAG = "CarouselLayoutManager";
|
||||
public static final int VERTICAL = 1;
|
||||
private int carouselAlignment;
|
||||
private CarouselStrategy carouselStrategy;
|
||||
private int currentEstimatedPosition;
|
||||
private int currentFillStartPosition;
|
||||
private KeylineState currentKeylineState;
|
||||
private final DebugItemDecoration debugItemDecoration;
|
||||
private boolean isDebuggingEnabled;
|
||||
private KeylineStateList keylineStateList;
|
||||
private Map<Integer, KeylineState> keylineStatePositionMap;
|
||||
private int lastItemCount;
|
||||
int maxScroll;
|
||||
int minScroll;
|
||||
private CarouselOrientationHelper orientationHelper;
|
||||
private final View.OnLayoutChangeListener recyclerViewSizeChangeListener;
|
||||
int scrollOffset;
|
||||
|
||||
private static int calculateShouldScrollBy(int i, int i2, int i3, int i4) {
|
||||
int i5 = i2 + i;
|
||||
return i5 < i3 ? i3 - i2 : i5 > i4 ? i4 - i2 : i;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int computeHorizontalScrollOffset(RecyclerView.State state) {
|
||||
return this.scrollOffset;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int computeHorizontalScrollRange(RecyclerView.State state) {
|
||||
return this.maxScroll - this.minScroll;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int computeVerticalScrollOffset(RecyclerView.State state) {
|
||||
return this.scrollOffset;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int computeVerticalScrollRange(RecyclerView.State state) {
|
||||
return this.maxScroll - this.minScroll;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Carousel
|
||||
public int getCarouselAlignment() {
|
||||
return this.carouselAlignment;
|
||||
}
|
||||
|
||||
/* renamed from: lambda$new$0$com-google-android-material-carousel-CarouselLayoutManager, reason: not valid java name */
|
||||
/* synthetic */ void m195x2ff337cb(View view, int i, int i2, int i3, int i4, int i5, int i6, int i7, int i8) {
|
||||
if (i == i5 && i2 == i6 && i3 == i7 && i4 == i8) {
|
||||
return;
|
||||
}
|
||||
view.post(new Runnable() { // from class: com.google.android.material.carousel.CarouselLayoutManager$$ExternalSyntheticLambda0
|
||||
@Override // java.lang.Runnable
|
||||
public final void run() {
|
||||
CarouselLayoutManager.this.refreshKeylineState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static final class ChildCalculations {
|
||||
final float center;
|
||||
final View child;
|
||||
final float offsetCenter;
|
||||
final KeylineRange range;
|
||||
|
||||
ChildCalculations(View view, float f, float f2, KeylineRange keylineRange) {
|
||||
this.child = view;
|
||||
this.center = f;
|
||||
this.offsetCenter = f2;
|
||||
this.range = keylineRange;
|
||||
}
|
||||
}
|
||||
|
||||
public CarouselLayoutManager() {
|
||||
this(new MultiBrowseCarouselStrategy());
|
||||
}
|
||||
|
||||
public CarouselLayoutManager(CarouselStrategy carouselStrategy) {
|
||||
this(carouselStrategy, 0);
|
||||
}
|
||||
|
||||
public CarouselLayoutManager(CarouselStrategy carouselStrategy, int i) {
|
||||
this.isDebuggingEnabled = false;
|
||||
this.debugItemDecoration = new DebugItemDecoration();
|
||||
this.currentFillStartPosition = 0;
|
||||
this.recyclerViewSizeChangeListener = new View.OnLayoutChangeListener() { // from class: com.google.android.material.carousel.CarouselLayoutManager$$ExternalSyntheticLambda1
|
||||
@Override // android.view.View.OnLayoutChangeListener
|
||||
public final void onLayoutChange(View view, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9) {
|
||||
CarouselLayoutManager.this.m195x2ff337cb(view, i2, i3, i4, i5, i6, i7, i8, i9);
|
||||
}
|
||||
};
|
||||
this.currentEstimatedPosition = -1;
|
||||
this.carouselAlignment = 0;
|
||||
setCarouselStrategy(carouselStrategy);
|
||||
setOrientation(i);
|
||||
}
|
||||
|
||||
public CarouselLayoutManager(Context context, AttributeSet attributeSet, int i, int i2) {
|
||||
this.isDebuggingEnabled = false;
|
||||
this.debugItemDecoration = new DebugItemDecoration();
|
||||
this.currentFillStartPosition = 0;
|
||||
this.recyclerViewSizeChangeListener = new View.OnLayoutChangeListener() { // from class: com.google.android.material.carousel.CarouselLayoutManager$$ExternalSyntheticLambda1
|
||||
@Override // android.view.View.OnLayoutChangeListener
|
||||
public final void onLayoutChange(View view, int i22, int i3, int i4, int i5, int i6, int i7, int i8, int i9) {
|
||||
CarouselLayoutManager.this.m195x2ff337cb(view, i22, i3, i4, i5, i6, i7, i8, i9);
|
||||
}
|
||||
};
|
||||
this.currentEstimatedPosition = -1;
|
||||
this.carouselAlignment = 0;
|
||||
setCarouselStrategy(new MultiBrowseCarouselStrategy());
|
||||
setCarouselAttributes(context, attributeSet);
|
||||
}
|
||||
|
||||
private void setCarouselAttributes(Context context, AttributeSet attributeSet) {
|
||||
if (attributeSet != null) {
|
||||
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, R.styleable.Carousel);
|
||||
setCarouselAlignment(obtainStyledAttributes.getInt(R.styleable.Carousel_carousel_alignment, 0));
|
||||
setOrientation(obtainStyledAttributes.getInt(R.styleable.RecyclerView_android_orientation, 0));
|
||||
obtainStyledAttributes.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCarouselAlignment(int i) {
|
||||
this.carouselAlignment = i;
|
||||
refreshKeylineState();
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
|
||||
return new RecyclerView.LayoutParams(-2, -2);
|
||||
}
|
||||
|
||||
public void setCarouselStrategy(CarouselStrategy carouselStrategy) {
|
||||
this.carouselStrategy = carouselStrategy;
|
||||
refreshKeylineState();
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void onAttachedToWindow(RecyclerView recyclerView) {
|
||||
super.onAttachedToWindow(recyclerView);
|
||||
refreshKeylineState();
|
||||
recyclerView.addOnLayoutChangeListener(this.recyclerViewSizeChangeListener);
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void onDetachedFromWindow(RecyclerView recyclerView, RecyclerView.Recycler recycler) {
|
||||
super.onDetachedFromWindow(recyclerView, recycler);
|
||||
recyclerView.removeOnLayoutChangeListener(this.recyclerViewSizeChangeListener);
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
if (state.getItemCount() <= 0 || getContainerSize() <= 0.0f) {
|
||||
removeAndRecycleAllViews(recycler);
|
||||
this.currentFillStartPosition = 0;
|
||||
return;
|
||||
}
|
||||
boolean isLayoutRtl = isLayoutRtl();
|
||||
boolean z = this.keylineStateList == null;
|
||||
if (z) {
|
||||
recalculateKeylineStateList(recycler);
|
||||
}
|
||||
int calculateStartScroll = calculateStartScroll(this.keylineStateList);
|
||||
int calculateEndScroll = calculateEndScroll(state, this.keylineStateList);
|
||||
this.minScroll = isLayoutRtl ? calculateEndScroll : calculateStartScroll;
|
||||
if (isLayoutRtl) {
|
||||
calculateEndScroll = calculateStartScroll;
|
||||
}
|
||||
this.maxScroll = calculateEndScroll;
|
||||
if (z) {
|
||||
this.scrollOffset = calculateStartScroll;
|
||||
this.keylineStatePositionMap = this.keylineStateList.getKeylineStateForPositionMap(getItemCount(), this.minScroll, this.maxScroll, isLayoutRtl());
|
||||
int i = this.currentEstimatedPosition;
|
||||
if (i != -1) {
|
||||
this.scrollOffset = getScrollOffsetForPosition(i, getKeylineStateForPosition(i));
|
||||
}
|
||||
}
|
||||
int i2 = this.scrollOffset;
|
||||
this.scrollOffset = i2 + calculateShouldScrollBy(0, i2, this.minScroll, this.maxScroll);
|
||||
this.currentFillStartPosition = MathUtils.clamp(this.currentFillStartPosition, 0, state.getItemCount());
|
||||
updateCurrentKeylineStateForScrollOffset(this.keylineStateList);
|
||||
detachAndScrapAttachedViews(recycler);
|
||||
fill(recycler, state);
|
||||
this.lastItemCount = getItemCount();
|
||||
}
|
||||
|
||||
private void recalculateKeylineStateList(RecyclerView.Recycler recycler) {
|
||||
View viewForPosition = recycler.getViewForPosition(0);
|
||||
measureChildWithMargins(viewForPosition, 0, 0);
|
||||
KeylineState onFirstChildMeasuredWithMargins = this.carouselStrategy.onFirstChildMeasuredWithMargins(this, viewForPosition);
|
||||
if (isLayoutRtl()) {
|
||||
onFirstChildMeasuredWithMargins = KeylineState.reverse(onFirstChildMeasuredWithMargins, getContainerSize());
|
||||
}
|
||||
this.keylineStateList = KeylineStateList.from(this, onFirstChildMeasuredWithMargins);
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public void refreshKeylineState() {
|
||||
this.keylineStateList = null;
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
private void fill(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
removeAndRecycleOutOfBoundsViews(recycler);
|
||||
if (getChildCount() == 0) {
|
||||
addViewsStart(recycler, this.currentFillStartPosition - 1);
|
||||
addViewsEnd(recycler, state, this.currentFillStartPosition);
|
||||
} else {
|
||||
int position = getPosition(getChildAt(0));
|
||||
int position2 = getPosition(getChildAt(getChildCount() - 1));
|
||||
addViewsStart(recycler, position - 1);
|
||||
addViewsEnd(recycler, state, position2 + 1);
|
||||
}
|
||||
validateChildOrderIfDebugging();
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void onLayoutCompleted(RecyclerView.State state) {
|
||||
super.onLayoutCompleted(state);
|
||||
if (getChildCount() == 0) {
|
||||
this.currentFillStartPosition = 0;
|
||||
} else {
|
||||
this.currentFillStartPosition = getPosition(getChildAt(0));
|
||||
}
|
||||
validateChildOrderIfDebugging();
|
||||
}
|
||||
|
||||
private void addViewsStart(RecyclerView.Recycler recycler, int i) {
|
||||
float calculateChildStartForFill = calculateChildStartForFill(i);
|
||||
while (i >= 0) {
|
||||
ChildCalculations makeChildCalculations = makeChildCalculations(recycler, calculateChildStartForFill, i);
|
||||
if (isLocOffsetOutOfFillBoundsStart(makeChildCalculations.offsetCenter, makeChildCalculations.range)) {
|
||||
return;
|
||||
}
|
||||
calculateChildStartForFill = addStart(calculateChildStartForFill, this.currentKeylineState.getItemSize());
|
||||
if (!isLocOffsetOutOfFillBoundsEnd(makeChildCalculations.offsetCenter, makeChildCalculations.range)) {
|
||||
addAndLayoutView(makeChildCalculations.child, 0, makeChildCalculations);
|
||||
}
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
private void addViewAtPosition(RecyclerView.Recycler recycler, int i, int i2) {
|
||||
if (i < 0 || i >= getItemCount()) {
|
||||
return;
|
||||
}
|
||||
ChildCalculations makeChildCalculations = makeChildCalculations(recycler, calculateChildStartForFill(i), i);
|
||||
addAndLayoutView(makeChildCalculations.child, i2, makeChildCalculations);
|
||||
}
|
||||
|
||||
private void addViewsEnd(RecyclerView.Recycler recycler, RecyclerView.State state, int i) {
|
||||
float calculateChildStartForFill = calculateChildStartForFill(i);
|
||||
while (i < state.getItemCount()) {
|
||||
ChildCalculations makeChildCalculations = makeChildCalculations(recycler, calculateChildStartForFill, i);
|
||||
if (isLocOffsetOutOfFillBoundsEnd(makeChildCalculations.offsetCenter, makeChildCalculations.range)) {
|
||||
return;
|
||||
}
|
||||
calculateChildStartForFill = addEnd(calculateChildStartForFill, this.currentKeylineState.getItemSize());
|
||||
if (!isLocOffsetOutOfFillBoundsStart(makeChildCalculations.offsetCenter, makeChildCalculations.range)) {
|
||||
addAndLayoutView(makeChildCalculations.child, -1, makeChildCalculations);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private void logChildrenIfDebugging() {
|
||||
if (this.isDebuggingEnabled && Log.isLoggable(TAG, 3)) {
|
||||
Log.d(TAG, "internal representation of views on the screen");
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View childAt = getChildAt(i);
|
||||
Log.d(TAG, "item position " + getPosition(childAt) + ", center:" + getDecoratedCenterWithMargins(childAt) + ", child index:" + i);
|
||||
}
|
||||
Log.d(TAG, "==============");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateChildOrderIfDebugging() {
|
||||
if (!this.isDebuggingEnabled || getChildCount() < 1) {
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
while (i < getChildCount() - 1) {
|
||||
int position = getPosition(getChildAt(i));
|
||||
int i2 = i + 1;
|
||||
int position2 = getPosition(getChildAt(i2));
|
||||
if (position > position2) {
|
||||
logChildrenIfDebugging();
|
||||
throw new IllegalStateException("Detected invalid child order. Child at index [" + i + "] had adapter position [" + position + "] and child at index [" + i2 + "] had adapter position [" + position2 + "].");
|
||||
}
|
||||
i = i2;
|
||||
}
|
||||
}
|
||||
|
||||
private ChildCalculations makeChildCalculations(RecyclerView.Recycler recycler, float f, int i) {
|
||||
View viewForPosition = recycler.getViewForPosition(i);
|
||||
measureChildWithMargins(viewForPosition, 0, 0);
|
||||
float addEnd = addEnd(f, this.currentKeylineState.getItemSize() / 2.0f);
|
||||
KeylineRange surroundingKeylineRange = getSurroundingKeylineRange(this.currentKeylineState.getKeylines(), addEnd, false);
|
||||
return new ChildCalculations(viewForPosition, addEnd, calculateChildOffsetCenterForLocation(viewForPosition, addEnd, surroundingKeylineRange), surroundingKeylineRange);
|
||||
}
|
||||
|
||||
private void addAndLayoutView(View view, int i, ChildCalculations childCalculations) {
|
||||
float itemSize = this.currentKeylineState.getItemSize() / 2.0f;
|
||||
addView(view, i);
|
||||
this.orientationHelper.layoutDecoratedWithMargins(view, (int) (childCalculations.offsetCenter - itemSize), (int) (childCalculations.offsetCenter + itemSize));
|
||||
updateChildMaskForLocation(view, childCalculations.center, childCalculations.range);
|
||||
}
|
||||
|
||||
private boolean isLocOffsetOutOfFillBoundsStart(float f, KeylineRange keylineRange) {
|
||||
float addEnd = addEnd(f, getMaskedItemSizeForLocOffset(f, keylineRange) / 2.0f);
|
||||
if (isLayoutRtl()) {
|
||||
if (addEnd > getContainerSize()) {
|
||||
return true;
|
||||
}
|
||||
} else if (addEnd < 0.0f) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Carousel
|
||||
public boolean isHorizontal() {
|
||||
return this.orientationHelper.orientation == 0;
|
||||
}
|
||||
|
||||
private boolean isLocOffsetOutOfFillBoundsEnd(float f, KeylineRange keylineRange) {
|
||||
float addStart = addStart(f, getMaskedItemSizeForLocOffset(f, keylineRange) / 2.0f);
|
||||
if (isLayoutRtl()) {
|
||||
if (addStart < 0.0f) {
|
||||
return true;
|
||||
}
|
||||
} else if (addStart > getContainerSize()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void getDecoratedBoundsWithMargins(View view, Rect rect) {
|
||||
super.getDecoratedBoundsWithMargins(view, rect);
|
||||
float centerY = rect.centerY();
|
||||
if (isHorizontal()) {
|
||||
centerY = rect.centerX();
|
||||
}
|
||||
float maskedItemSizeForLocOffset = getMaskedItemSizeForLocOffset(centerY, getSurroundingKeylineRange(this.currentKeylineState.getKeylines(), centerY, true));
|
||||
float width = isHorizontal() ? (rect.width() - maskedItemSizeForLocOffset) / 2.0f : 0.0f;
|
||||
float height = isHorizontal() ? 0.0f : (rect.height() - maskedItemSizeForLocOffset) / 2.0f;
|
||||
rect.set((int) (rect.left + width), (int) (rect.top + height), (int) (rect.right - width), (int) (rect.bottom - height));
|
||||
}
|
||||
|
||||
private float getDecoratedCenterWithMargins(View view) {
|
||||
int centerY;
|
||||
Rect rect = new Rect();
|
||||
super.getDecoratedBoundsWithMargins(view, rect);
|
||||
if (isHorizontal()) {
|
||||
centerY = rect.centerX();
|
||||
} else {
|
||||
centerY = rect.centerY();
|
||||
}
|
||||
return centerY;
|
||||
}
|
||||
|
||||
private void removeAndRecycleOutOfBoundsViews(RecyclerView.Recycler recycler) {
|
||||
while (getChildCount() > 0) {
|
||||
View childAt = getChildAt(0);
|
||||
float decoratedCenterWithMargins = getDecoratedCenterWithMargins(childAt);
|
||||
if (!isLocOffsetOutOfFillBoundsStart(decoratedCenterWithMargins, getSurroundingKeylineRange(this.currentKeylineState.getKeylines(), decoratedCenterWithMargins, true))) {
|
||||
break;
|
||||
} else {
|
||||
removeAndRecycleView(childAt, recycler);
|
||||
}
|
||||
}
|
||||
while (getChildCount() - 1 >= 0) {
|
||||
View childAt2 = getChildAt(getChildCount() - 1);
|
||||
float decoratedCenterWithMargins2 = getDecoratedCenterWithMargins(childAt2);
|
||||
if (!isLocOffsetOutOfFillBoundsEnd(decoratedCenterWithMargins2, getSurroundingKeylineRange(this.currentKeylineState.getKeylines(), decoratedCenterWithMargins2, true))) {
|
||||
return;
|
||||
} else {
|
||||
removeAndRecycleView(childAt2, recycler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static KeylineRange getSurroundingKeylineRange(List<KeylineState.Keyline> list, float f, boolean z) {
|
||||
float f2 = Float.MAX_VALUE;
|
||||
float f3 = Float.MAX_VALUE;
|
||||
float f4 = Float.MAX_VALUE;
|
||||
float f5 = -3.4028235E38f;
|
||||
int i = -1;
|
||||
int i2 = -1;
|
||||
int i3 = -1;
|
||||
int i4 = -1;
|
||||
for (int i5 = 0; i5 < list.size(); i5++) {
|
||||
KeylineState.Keyline keyline = list.get(i5);
|
||||
float f6 = z ? keyline.locOffset : keyline.loc;
|
||||
float abs = Math.abs(f6 - f);
|
||||
if (f6 <= f && abs <= f2) {
|
||||
i = i5;
|
||||
f2 = abs;
|
||||
}
|
||||
if (f6 > f && abs <= f3) {
|
||||
i3 = i5;
|
||||
f3 = abs;
|
||||
}
|
||||
if (f6 <= f4) {
|
||||
i2 = i5;
|
||||
f4 = f6;
|
||||
}
|
||||
if (f6 > f5) {
|
||||
i4 = i5;
|
||||
f5 = f6;
|
||||
}
|
||||
}
|
||||
if (i == -1) {
|
||||
i = i2;
|
||||
}
|
||||
if (i3 == -1) {
|
||||
i3 = i4;
|
||||
}
|
||||
return new KeylineRange(list.get(i), list.get(i3));
|
||||
}
|
||||
|
||||
private void updateCurrentKeylineStateForScrollOffset(KeylineStateList keylineStateList) {
|
||||
int i = this.maxScroll;
|
||||
int i2 = this.minScroll;
|
||||
if (i <= i2) {
|
||||
this.currentKeylineState = isLayoutRtl() ? keylineStateList.getEndState() : keylineStateList.getStartState();
|
||||
} else {
|
||||
this.currentKeylineState = keylineStateList.getShiftedState(this.scrollOffset, i2, i);
|
||||
}
|
||||
this.debugItemDecoration.setKeylines(this.currentKeylineState.getKeylines());
|
||||
}
|
||||
|
||||
private int calculateStartScroll(KeylineStateList keylineStateList) {
|
||||
boolean isLayoutRtl = isLayoutRtl();
|
||||
KeylineState endState = isLayoutRtl ? keylineStateList.getEndState() : keylineStateList.getStartState();
|
||||
return (int) (((getPaddingStart() * (isLayoutRtl ? 1 : -1)) + getParentStart()) - addStart((isLayoutRtl ? endState.getLastFocalKeyline() : endState.getFirstFocalKeyline()).loc, endState.getItemSize() / 2.0f));
|
||||
}
|
||||
|
||||
private int calculateEndScroll(RecyclerView.State state, KeylineStateList keylineStateList) {
|
||||
boolean isLayoutRtl = isLayoutRtl();
|
||||
KeylineState startState = isLayoutRtl ? keylineStateList.getStartState() : keylineStateList.getEndState();
|
||||
KeylineState.Keyline firstFocalKeyline = isLayoutRtl ? startState.getFirstFocalKeyline() : startState.getLastFocalKeyline();
|
||||
int itemCount = (int) ((((((state.getItemCount() - 1) * startState.getItemSize()) + getPaddingEnd()) * (isLayoutRtl ? -1.0f : 1.0f)) - (firstFocalKeyline.loc - getParentStart())) + (getParentEnd() - firstFocalKeyline.loc));
|
||||
return isLayoutRtl ? Math.min(0, itemCount) : Math.max(0, itemCount);
|
||||
}
|
||||
|
||||
private float calculateChildStartForFill(int i) {
|
||||
return addEnd(getParentStart() - this.scrollOffset, this.currentKeylineState.getItemSize() * i);
|
||||
}
|
||||
|
||||
private float calculateChildOffsetCenterForLocation(View view, float f, KeylineRange keylineRange) {
|
||||
float lerp = AnimationUtils.lerp(keylineRange.leftOrTop.locOffset, keylineRange.rightOrBottom.locOffset, keylineRange.leftOrTop.loc, keylineRange.rightOrBottom.loc, f);
|
||||
if (keylineRange.rightOrBottom != this.currentKeylineState.getFirstKeyline() && keylineRange.leftOrTop != this.currentKeylineState.getLastKeyline()) {
|
||||
return lerp;
|
||||
}
|
||||
return lerp + ((f - keylineRange.rightOrBottom.loc) * ((1.0f - keylineRange.rightOrBottom.mask) + (this.orientationHelper.getMaskMargins((RecyclerView.LayoutParams) view.getLayoutParams()) / this.currentKeylineState.getItemSize())));
|
||||
}
|
||||
|
||||
private float getMaskedItemSizeForLocOffset(float f, KeylineRange keylineRange) {
|
||||
return AnimationUtils.lerp(keylineRange.leftOrTop.maskedItemSize, keylineRange.rightOrBottom.maskedItemSize, keylineRange.leftOrTop.locOffset, keylineRange.rightOrBottom.locOffset, f);
|
||||
}
|
||||
|
||||
/* JADX WARN: Multi-variable type inference failed */
|
||||
private void updateChildMaskForLocation(View view, float f, KeylineRange keylineRange) {
|
||||
if (view instanceof Maskable) {
|
||||
float lerp = AnimationUtils.lerp(keylineRange.leftOrTop.mask, keylineRange.rightOrBottom.mask, keylineRange.leftOrTop.loc, keylineRange.rightOrBottom.loc, f);
|
||||
float height = view.getHeight();
|
||||
float width = view.getWidth();
|
||||
RectF maskRect = this.orientationHelper.getMaskRect(height, width, AnimationUtils.lerp(0.0f, height / 2.0f, 0.0f, 1.0f, lerp), AnimationUtils.lerp(0.0f, width / 2.0f, 0.0f, 1.0f, lerp));
|
||||
float calculateChildOffsetCenterForLocation = calculateChildOffsetCenterForLocation(view, f, keylineRange);
|
||||
RectF rectF = new RectF(calculateChildOffsetCenterForLocation - (maskRect.width() / 2.0f), calculateChildOffsetCenterForLocation - (maskRect.height() / 2.0f), calculateChildOffsetCenterForLocation + (maskRect.width() / 2.0f), (maskRect.height() / 2.0f) + calculateChildOffsetCenterForLocation);
|
||||
RectF rectF2 = new RectF(getParentLeft(), getParentTop(), getParentRight(), getParentBottom());
|
||||
if (this.carouselStrategy.isContained()) {
|
||||
this.orientationHelper.containMaskWithinBounds(maskRect, rectF, rectF2);
|
||||
}
|
||||
this.orientationHelper.moveMaskOnEdgeOutsideBounds(maskRect, rectF, rectF2);
|
||||
((Maskable) view).setMaskRectF(maskRect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void measureChildWithMargins(View view, int i, int i2) {
|
||||
float f;
|
||||
float f2;
|
||||
if (!(view instanceof Maskable)) {
|
||||
throw new IllegalStateException("All children of a RecyclerView using CarouselLayoutManager must use MaskableFrameLayout as their root ViewGroup.");
|
||||
}
|
||||
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
|
||||
Rect rect = new Rect();
|
||||
calculateItemDecorationsForChild(view, rect);
|
||||
int i3 = i + rect.left + rect.right;
|
||||
int i4 = i2 + rect.top + rect.bottom;
|
||||
if (this.keylineStateList != null && this.orientationHelper.orientation == 0) {
|
||||
f = this.keylineStateList.getDefaultState().getItemSize();
|
||||
} else {
|
||||
f = layoutParams.width;
|
||||
}
|
||||
if (this.keylineStateList != null && this.orientationHelper.orientation == 1) {
|
||||
f2 = this.keylineStateList.getDefaultState().getItemSize();
|
||||
} else {
|
||||
f2 = layoutParams.height;
|
||||
}
|
||||
view.measure(getChildMeasureSpec(getWidth(), getWidthMode(), getPaddingLeft() + getPaddingRight() + layoutParams.leftMargin + layoutParams.rightMargin + i3, (int) f, canScrollHorizontally()), getChildMeasureSpec(getHeight(), getHeightMode(), getPaddingTop() + getPaddingBottom() + layoutParams.topMargin + layoutParams.bottomMargin + i4, (int) f2, canScrollVertically()));
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public int getParentLeft() {
|
||||
return this.orientationHelper.getParentLeft();
|
||||
}
|
||||
|
||||
private int getParentStart() {
|
||||
return this.orientationHelper.getParentStart();
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public int getParentRight() {
|
||||
return this.orientationHelper.getParentRight();
|
||||
}
|
||||
|
||||
private int getParentEnd() {
|
||||
return this.orientationHelper.getParentEnd();
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public int getParentTop() {
|
||||
return this.orientationHelper.getParentTop();
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public int getParentBottom() {
|
||||
return this.orientationHelper.getParentBottom();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Carousel
|
||||
public int getContainerWidth() {
|
||||
return getWidth();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Carousel
|
||||
public int getContainerHeight() {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
private int getContainerSize() {
|
||||
if (isHorizontal()) {
|
||||
return getContainerWidth();
|
||||
}
|
||||
return getContainerHeight();
|
||||
}
|
||||
|
||||
boolean isLayoutRtl() {
|
||||
return isHorizontal() && getLayoutDirection() == 1;
|
||||
}
|
||||
|
||||
private float addStart(float f, float f2) {
|
||||
return isLayoutRtl() ? f + f2 : f - f2;
|
||||
}
|
||||
|
||||
private float addEnd(float f, float f2) {
|
||||
return isLayoutRtl() ? f - f2 : f + f2;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void onInitializeAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
|
||||
super.onInitializeAccessibilityEvent(accessibilityEvent);
|
||||
if (getChildCount() > 0) {
|
||||
accessibilityEvent.setFromIndex(getPosition(getChildAt(0)));
|
||||
accessibilityEvent.setToIndex(getPosition(getChildAt(getChildCount() - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
private int getScrollOffsetForPosition(int i, KeylineState keylineState) {
|
||||
if (isLayoutRtl()) {
|
||||
return (int) (((getContainerSize() - keylineState.getLastFocalKeyline().loc) - (i * keylineState.getItemSize())) - (keylineState.getItemSize() / 2.0f));
|
||||
}
|
||||
return (int) (((i * keylineState.getItemSize()) - keylineState.getFirstFocalKeyline().loc) + (keylineState.getItemSize() / 2.0f));
|
||||
}
|
||||
|
||||
private int getSmallestScrollOffsetToFocalKeyline(int i, KeylineState keylineState) {
|
||||
int i2;
|
||||
int i3 = Integer.MAX_VALUE;
|
||||
for (KeylineState.Keyline keyline : keylineState.getFocalKeylines()) {
|
||||
float itemSize = (i * keylineState.getItemSize()) + (keylineState.getItemSize() / 2.0f);
|
||||
if (isLayoutRtl()) {
|
||||
i2 = (int) ((getContainerSize() - keyline.loc) - itemSize);
|
||||
} else {
|
||||
i2 = (int) (itemSize - keyline.loc);
|
||||
}
|
||||
int i4 = i2 - this.scrollOffset;
|
||||
if (Math.abs(i3) > Math.abs(i4)) {
|
||||
i3 = i4;
|
||||
}
|
||||
}
|
||||
return i3;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.SmoothScroller.ScrollVectorProvider
|
||||
public PointF computeScrollVectorForPosition(int i) {
|
||||
if (this.keylineStateList == null) {
|
||||
return null;
|
||||
}
|
||||
int offsetToScrollToPosition = getOffsetToScrollToPosition(i, getKeylineStateForPosition(i));
|
||||
if (isHorizontal()) {
|
||||
return new PointF(offsetToScrollToPosition, 0.0f);
|
||||
}
|
||||
return new PointF(0.0f, offsetToScrollToPosition);
|
||||
}
|
||||
|
||||
int getOffsetToScrollToPosition(int i, KeylineState keylineState) {
|
||||
return getScrollOffsetForPosition(i, keylineState) - this.scrollOffset;
|
||||
}
|
||||
|
||||
int getOffsetToScrollToPositionForSnap(int i, boolean z) {
|
||||
int offsetToScrollToPosition = getOffsetToScrollToPosition(i, this.keylineStateList.getShiftedState(this.scrollOffset, this.minScroll, this.maxScroll, true));
|
||||
int offsetToScrollToPosition2 = this.keylineStatePositionMap != null ? getOffsetToScrollToPosition(i, getKeylineStateForPosition(i)) : offsetToScrollToPosition;
|
||||
return (!z || Math.abs(offsetToScrollToPosition2) >= Math.abs(offsetToScrollToPosition)) ? offsetToScrollToPosition : offsetToScrollToPosition2;
|
||||
}
|
||||
|
||||
private KeylineState getKeylineStateForPosition(int i) {
|
||||
KeylineState keylineState;
|
||||
Map<Integer, KeylineState> map = this.keylineStatePositionMap;
|
||||
return (map == null || (keylineState = map.get(Integer.valueOf(MathUtils.clamp(i, 0, Math.max(0, getItemCount() + (-1)))))) == null) ? this.keylineStateList.getDefaultState() : keylineState;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void scrollToPosition(int i) {
|
||||
this.currentEstimatedPosition = i;
|
||||
if (this.keylineStateList == null) {
|
||||
return;
|
||||
}
|
||||
this.scrollOffset = getScrollOffsetForPosition(i, getKeylineStateForPosition(i));
|
||||
this.currentFillStartPosition = MathUtils.clamp(i, 0, Math.max(0, getItemCount() - 1));
|
||||
updateCurrentKeylineStateForScrollOffset(this.keylineStateList);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int i) {
|
||||
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) { // from class: com.google.android.material.carousel.CarouselLayoutManager.1
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.SmoothScroller
|
||||
public PointF computeScrollVectorForPosition(int i2) {
|
||||
return CarouselLayoutManager.this.computeScrollVectorForPosition(i2);
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.LinearSmoothScroller
|
||||
public int calculateDxToMakeVisible(View view, int i2) {
|
||||
if (CarouselLayoutManager.this.keylineStateList == null || !CarouselLayoutManager.this.isHorizontal()) {
|
||||
return 0;
|
||||
}
|
||||
CarouselLayoutManager carouselLayoutManager = CarouselLayoutManager.this;
|
||||
return carouselLayoutManager.calculateScrollDeltaToMakePositionVisible(carouselLayoutManager.getPosition(view));
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.LinearSmoothScroller
|
||||
public int calculateDyToMakeVisible(View view, int i2) {
|
||||
if (CarouselLayoutManager.this.keylineStateList == null || CarouselLayoutManager.this.isHorizontal()) {
|
||||
return 0;
|
||||
}
|
||||
CarouselLayoutManager carouselLayoutManager = CarouselLayoutManager.this;
|
||||
return carouselLayoutManager.calculateScrollDeltaToMakePositionVisible(carouselLayoutManager.getPosition(view));
|
||||
}
|
||||
};
|
||||
linearSmoothScroller.setTargetPosition(i);
|
||||
startSmoothScroll(linearSmoothScroller);
|
||||
}
|
||||
|
||||
int calculateScrollDeltaToMakePositionVisible(int i) {
|
||||
return (int) (this.scrollOffset - getScrollOffsetForPosition(i, getKeylineStateForPosition(i)));
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public boolean canScrollHorizontally() {
|
||||
return isHorizontal();
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int scrollHorizontallyBy(int i, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
if (canScrollHorizontally()) {
|
||||
return scrollBy(i, recycler, state);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public boolean canScrollVertically() {
|
||||
return !isHorizontal();
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int scrollVerticallyBy(int i, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
if (canScrollVertically()) {
|
||||
return scrollBy(i, recycler, state);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static class LayoutDirection {
|
||||
private static final int INVALID_LAYOUT = Integer.MIN_VALUE;
|
||||
private static final int LAYOUT_END = 1;
|
||||
private static final int LAYOUT_START = -1;
|
||||
|
||||
private LayoutDirection() {
|
||||
}
|
||||
}
|
||||
|
||||
private int convertFocusDirectionToLayoutDirection(int i) {
|
||||
int orientation = getOrientation();
|
||||
if (i == 1) {
|
||||
return -1;
|
||||
}
|
||||
if (i == 2) {
|
||||
return 1;
|
||||
}
|
||||
if (i == 17) {
|
||||
if (orientation == 0) {
|
||||
return isLayoutRtl() ? 1 : -1;
|
||||
}
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
if (i == 33) {
|
||||
return orientation == 1 ? -1 : Integer.MIN_VALUE;
|
||||
}
|
||||
if (i == 66) {
|
||||
if (orientation == 0) {
|
||||
return isLayoutRtl() ? -1 : 1;
|
||||
}
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
if (i == 130) {
|
||||
return orientation == 1 ? 1 : Integer.MIN_VALUE;
|
||||
}
|
||||
Log.d(TAG, "Unknown focus request:" + i);
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public View onFocusSearchFailed(View view, int i, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
int convertFocusDirectionToLayoutDirection;
|
||||
if (getChildCount() == 0 || (convertFocusDirectionToLayoutDirection = convertFocusDirectionToLayoutDirection(i)) == Integer.MIN_VALUE) {
|
||||
return null;
|
||||
}
|
||||
if (convertFocusDirectionToLayoutDirection == -1) {
|
||||
if (getPosition(view) == 0) {
|
||||
return null;
|
||||
}
|
||||
addViewAtPosition(recycler, getPosition(getChildAt(0)) - 1, 0);
|
||||
return getChildClosestToStart();
|
||||
}
|
||||
if (getPosition(view) == getItemCount() - 1) {
|
||||
return null;
|
||||
}
|
||||
addViewAtPosition(recycler, getPosition(getChildAt(getChildCount() - 1)) + 1, -1);
|
||||
return getChildClosestToEnd();
|
||||
}
|
||||
|
||||
private View getChildClosestToStart() {
|
||||
return getChildAt(isLayoutRtl() ? getChildCount() - 1 : 0);
|
||||
}
|
||||
|
||||
private View getChildClosestToEnd() {
|
||||
return getChildAt(isLayoutRtl() ? 0 : getChildCount() - 1);
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public boolean requestChildRectangleOnScreen(RecyclerView recyclerView, View view, Rect rect, boolean z, boolean z2) {
|
||||
int smallestScrollOffsetToFocalKeyline;
|
||||
if (this.keylineStateList == null || (smallestScrollOffsetToFocalKeyline = getSmallestScrollOffsetToFocalKeyline(getPosition(view), getKeylineStateForPosition(getPosition(view)))) == 0) {
|
||||
return false;
|
||||
}
|
||||
scrollBy(recyclerView, getSmallestScrollOffsetToFocalKeyline(getPosition(view), this.keylineStateList.getShiftedState(this.scrollOffset + calculateShouldScrollBy(smallestScrollOffsetToFocalKeyline, this.scrollOffset, this.minScroll, this.maxScroll), this.minScroll, this.maxScroll)));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void scrollBy(RecyclerView recyclerView, int i) {
|
||||
if (isHorizontal()) {
|
||||
recyclerView.scrollBy(i, 0);
|
||||
} else {
|
||||
recyclerView.scrollBy(0, i);
|
||||
}
|
||||
}
|
||||
|
||||
private int scrollBy(int i, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
float f;
|
||||
if (getChildCount() == 0 || i == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (this.keylineStateList == null) {
|
||||
recalculateKeylineStateList(recycler);
|
||||
}
|
||||
int calculateShouldScrollBy = calculateShouldScrollBy(i, this.scrollOffset, this.minScroll, this.maxScroll);
|
||||
this.scrollOffset += calculateShouldScrollBy;
|
||||
updateCurrentKeylineStateForScrollOffset(this.keylineStateList);
|
||||
float itemSize = this.currentKeylineState.getItemSize() / 2.0f;
|
||||
float calculateChildStartForFill = calculateChildStartForFill(getPosition(getChildAt(0)));
|
||||
Rect rect = new Rect();
|
||||
if (isLayoutRtl()) {
|
||||
f = this.currentKeylineState.getLastFocalKeyline().locOffset;
|
||||
} else {
|
||||
f = this.currentKeylineState.getFirstFocalKeyline().locOffset;
|
||||
}
|
||||
float f2 = Float.MAX_VALUE;
|
||||
for (int i2 = 0; i2 < getChildCount(); i2++) {
|
||||
View childAt = getChildAt(i2);
|
||||
float abs = Math.abs(f - offsetChild(childAt, calculateChildStartForFill, itemSize, rect));
|
||||
if (childAt != null && abs < f2) {
|
||||
this.currentEstimatedPosition = getPosition(childAt);
|
||||
f2 = abs;
|
||||
}
|
||||
calculateChildStartForFill = addEnd(calculateChildStartForFill, this.currentKeylineState.getItemSize());
|
||||
}
|
||||
fill(recycler, state);
|
||||
return calculateShouldScrollBy;
|
||||
}
|
||||
|
||||
private float offsetChild(View view, float f, float f2, Rect rect) {
|
||||
float addEnd = addEnd(f, f2);
|
||||
KeylineRange surroundingKeylineRange = getSurroundingKeylineRange(this.currentKeylineState.getKeylines(), addEnd, false);
|
||||
float calculateChildOffsetCenterForLocation = calculateChildOffsetCenterForLocation(view, addEnd, surroundingKeylineRange);
|
||||
super.getDecoratedBoundsWithMargins(view, rect);
|
||||
updateChildMaskForLocation(view, addEnd, surroundingKeylineRange);
|
||||
this.orientationHelper.offsetChild(view, rect, f2, calculateChildOffsetCenterForLocation);
|
||||
return calculateChildOffsetCenterForLocation;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int computeHorizontalScrollExtent(RecyclerView.State state) {
|
||||
if (getChildCount() == 0 || this.keylineStateList == null || getItemCount() <= 1) {
|
||||
return 0;
|
||||
}
|
||||
return (int) (getWidth() * (this.keylineStateList.getDefaultState().getItemSize() / computeHorizontalScrollRange(state)));
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public int computeVerticalScrollExtent(RecyclerView.State state) {
|
||||
if (getChildCount() == 0 || this.keylineStateList == null || getItemCount() <= 1) {
|
||||
return 0;
|
||||
}
|
||||
return (int) (getHeight() * (this.keylineStateList.getDefaultState().getItemSize() / computeVerticalScrollRange(state)));
|
||||
}
|
||||
|
||||
public int getOrientation() {
|
||||
return this.orientationHelper.orientation;
|
||||
}
|
||||
|
||||
public void setOrientation(int i) {
|
||||
if (i != 0 && i != 1) {
|
||||
throw new IllegalArgumentException("invalid orientation:" + i);
|
||||
}
|
||||
assertNotInLayoutOrScroll(null);
|
||||
CarouselOrientationHelper carouselOrientationHelper = this.orientationHelper;
|
||||
if (carouselOrientationHelper == null || i != carouselOrientationHelper.orientation) {
|
||||
this.orientationHelper = CarouselOrientationHelper.createOrientationHelper(this, i);
|
||||
refreshKeylineState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void onItemsAdded(RecyclerView recyclerView, int i, int i2) {
|
||||
super.onItemsAdded(recyclerView, i, i2);
|
||||
updateItemCount();
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
public void onItemsRemoved(RecyclerView recyclerView, int i, int i2) {
|
||||
super.onItemsRemoved(recyclerView, i, i2);
|
||||
updateItemCount();
|
||||
}
|
||||
|
||||
private void updateItemCount() {
|
||||
int itemCount = getItemCount();
|
||||
int i = this.lastItemCount;
|
||||
if (itemCount == i || this.keylineStateList == null) {
|
||||
return;
|
||||
}
|
||||
if (this.carouselStrategy.shouldRefreshKeylineState(this, i)) {
|
||||
refreshKeylineState();
|
||||
}
|
||||
this.lastItemCount = itemCount;
|
||||
}
|
||||
|
||||
public void setDebuggingEnabled(RecyclerView recyclerView, boolean z) {
|
||||
this.isDebuggingEnabled = z;
|
||||
recyclerView.removeItemDecoration(this.debugItemDecoration);
|
||||
if (z) {
|
||||
recyclerView.addItemDecoration(this.debugItemDecoration);
|
||||
}
|
||||
recyclerView.invalidateItemDecorations();
|
||||
}
|
||||
|
||||
private static class KeylineRange {
|
||||
final KeylineState.Keyline leftOrTop;
|
||||
final KeylineState.Keyline rightOrBottom;
|
||||
|
||||
KeylineRange(KeylineState.Keyline keyline, KeylineState.Keyline keyline2) {
|
||||
Preconditions.checkArgument(keyline.loc <= keyline2.loc);
|
||||
this.leftOrTop = keyline;
|
||||
this.rightOrBottom = keyline2;
|
||||
}
|
||||
}
|
||||
|
||||
private static class DebugItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private List<KeylineState.Keyline> keylines;
|
||||
private final Paint linePaint;
|
||||
|
||||
DebugItemDecoration() {
|
||||
Paint paint = new Paint();
|
||||
this.linePaint = paint;
|
||||
this.keylines = Collections.unmodifiableList(new ArrayList());
|
||||
paint.setStrokeWidth(5.0f);
|
||||
paint.setColor(-65281);
|
||||
}
|
||||
|
||||
void setKeylines(List<KeylineState.Keyline> list) {
|
||||
this.keylines = Collections.unmodifiableList(list);
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.RecyclerView.ItemDecoration
|
||||
public void onDrawOver(Canvas canvas, RecyclerView recyclerView, RecyclerView.State state) {
|
||||
super.onDrawOver(canvas, recyclerView, state);
|
||||
this.linePaint.setStrokeWidth(recyclerView.getResources().getDimension(R.dimen.m3_carousel_debug_keyline_width));
|
||||
for (KeylineState.Keyline keyline : this.keylines) {
|
||||
this.linePaint.setColor(ColorUtils.blendARGB(-65281, -16776961, keyline.mask));
|
||||
if (((CarouselLayoutManager) recyclerView.getLayoutManager()).isHorizontal()) {
|
||||
canvas.drawLine(keyline.locOffset, ((CarouselLayoutManager) recyclerView.getLayoutManager()).getParentTop(), keyline.locOffset, ((CarouselLayoutManager) recyclerView.getLayoutManager()).getParentBottom(), this.linePaint);
|
||||
} else {
|
||||
canvas.drawLine(((CarouselLayoutManager) recyclerView.getLayoutManager()).getParentLeft(), keyline.locOffset, ((CarouselLayoutManager) recyclerView.getLayoutManager()).getParentRight(), keyline.locOffset, this.linePaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,211 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.view.View;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
abstract class CarouselOrientationHelper {
|
||||
final int orientation;
|
||||
|
||||
abstract void containMaskWithinBounds(RectF rectF, RectF rectF2, RectF rectF3);
|
||||
|
||||
abstract float getMaskMargins(RecyclerView.LayoutParams layoutParams);
|
||||
|
||||
abstract RectF getMaskRect(float f, float f2, float f3, float f4);
|
||||
|
||||
abstract int getParentBottom();
|
||||
|
||||
abstract int getParentEnd();
|
||||
|
||||
abstract int getParentLeft();
|
||||
|
||||
abstract int getParentRight();
|
||||
|
||||
abstract int getParentStart();
|
||||
|
||||
abstract int getParentTop();
|
||||
|
||||
abstract void layoutDecoratedWithMargins(View view, int i, int i2);
|
||||
|
||||
abstract void moveMaskOnEdgeOutsideBounds(RectF rectF, RectF rectF2, RectF rectF3);
|
||||
|
||||
abstract void offsetChild(View view, Rect rect, float f, float f2);
|
||||
|
||||
private CarouselOrientationHelper(int i) {
|
||||
this.orientation = i;
|
||||
}
|
||||
|
||||
static CarouselOrientationHelper createOrientationHelper(CarouselLayoutManager carouselLayoutManager, int i) {
|
||||
if (i == 0) {
|
||||
return createHorizontalHelper(carouselLayoutManager);
|
||||
}
|
||||
if (i == 1) {
|
||||
return createVerticalHelper(carouselLayoutManager);
|
||||
}
|
||||
throw new IllegalArgumentException("invalid orientation");
|
||||
}
|
||||
|
||||
private static CarouselOrientationHelper createVerticalHelper(final CarouselLayoutManager carouselLayoutManager) {
|
||||
return new CarouselOrientationHelper(1) { // from class: com.google.android.material.carousel.CarouselOrientationHelper.1
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentTop() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentLeft() {
|
||||
return carouselLayoutManager.getPaddingLeft();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentStart() {
|
||||
return getParentTop();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentRight() {
|
||||
return carouselLayoutManager.getWidth() - carouselLayoutManager.getPaddingRight();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentEnd() {
|
||||
return getParentBottom();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentBottom() {
|
||||
return carouselLayoutManager.getHeight();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void layoutDecoratedWithMargins(View view, int i, int i2) {
|
||||
carouselLayoutManager.layoutDecoratedWithMargins(view, getParentLeft(), i, getParentRight(), i2);
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public float getMaskMargins(RecyclerView.LayoutParams layoutParams) {
|
||||
return layoutParams.topMargin + layoutParams.bottomMargin;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public RectF getMaskRect(float f, float f2, float f3, float f4) {
|
||||
return new RectF(0.0f, f3, f2, f - f3);
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void containMaskWithinBounds(RectF rectF, RectF rectF2, RectF rectF3) {
|
||||
if (rectF2.top < rectF3.top && rectF2.bottom > rectF3.top) {
|
||||
float f = rectF3.top - rectF2.top;
|
||||
rectF.top += f;
|
||||
rectF3.top += f;
|
||||
}
|
||||
if (rectF2.bottom <= rectF3.bottom || rectF2.top >= rectF3.bottom) {
|
||||
return;
|
||||
}
|
||||
float f2 = rectF2.bottom - rectF3.bottom;
|
||||
rectF.bottom = Math.max(rectF.bottom - f2, rectF.top);
|
||||
rectF2.bottom = Math.max(rectF2.bottom - f2, rectF2.top);
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void moveMaskOnEdgeOutsideBounds(RectF rectF, RectF rectF2, RectF rectF3) {
|
||||
if (rectF2.bottom <= rectF3.top) {
|
||||
rectF.bottom = ((float) Math.floor(rectF.bottom)) - 1.0f;
|
||||
rectF.top = Math.min(rectF.top, rectF.bottom);
|
||||
}
|
||||
if (rectF2.top >= rectF3.bottom) {
|
||||
rectF.top = ((float) Math.ceil(rectF.top)) + 1.0f;
|
||||
rectF.bottom = Math.max(rectF.top, rectF.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void offsetChild(View view, Rect rect, float f, float f2) {
|
||||
view.offsetTopAndBottom((int) (f2 - (rect.top + f)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static CarouselOrientationHelper createHorizontalHelper(final CarouselLayoutManager carouselLayoutManager) {
|
||||
return new CarouselOrientationHelper(0) { // from class: com.google.android.material.carousel.CarouselOrientationHelper.2
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentLeft() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentStart() {
|
||||
return carouselLayoutManager.isLayoutRtl() ? getParentRight() : getParentLeft();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentRight() {
|
||||
return carouselLayoutManager.getWidth();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentEnd() {
|
||||
return carouselLayoutManager.isLayoutRtl() ? getParentLeft() : getParentRight();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentTop() {
|
||||
return carouselLayoutManager.getPaddingTop();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
int getParentBottom() {
|
||||
return carouselLayoutManager.getHeight() - carouselLayoutManager.getPaddingBottom();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void layoutDecoratedWithMargins(View view, int i, int i2) {
|
||||
carouselLayoutManager.layoutDecoratedWithMargins(view, i, getParentTop(), i2, getParentBottom());
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public float getMaskMargins(RecyclerView.LayoutParams layoutParams) {
|
||||
return layoutParams.rightMargin + layoutParams.leftMargin;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public RectF getMaskRect(float f, float f2, float f3, float f4) {
|
||||
return new RectF(f4, 0.0f, f2 - f4, f);
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void containMaskWithinBounds(RectF rectF, RectF rectF2, RectF rectF3) {
|
||||
if (rectF2.left < rectF3.left && rectF2.right > rectF3.left) {
|
||||
float f = rectF3.left - rectF2.left;
|
||||
rectF.left += f;
|
||||
rectF2.left += f;
|
||||
}
|
||||
if (rectF2.right <= rectF3.right || rectF2.left >= rectF3.right) {
|
||||
return;
|
||||
}
|
||||
float f2 = rectF2.right - rectF3.right;
|
||||
rectF.right = Math.max(rectF.right - f2, rectF.left);
|
||||
rectF2.right = Math.max(rectF2.right - f2, rectF2.left);
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void moveMaskOnEdgeOutsideBounds(RectF rectF, RectF rectF2, RectF rectF3) {
|
||||
if (rectF2.right <= rectF3.left) {
|
||||
rectF.right = ((float) Math.floor(rectF.right)) - 1.0f;
|
||||
rectF.left = Math.min(rectF.left, rectF.right);
|
||||
}
|
||||
if (rectF2.left >= rectF3.right) {
|
||||
rectF.left = ((float) Math.ceil(rectF.left)) + 1.0f;
|
||||
rectF.right = Math.max(rectF.left, rectF.right);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselOrientationHelper
|
||||
public void offsetChild(View view, Rect rect, float f, float f2) {
|
||||
view.offsetLeftAndRight((int) (f2 - (rect.left + f)));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.SnapHelper;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class CarouselSnapHelper extends SnapHelper {
|
||||
private static final float HORIZONTAL_SNAP_SPEED = 100.0f;
|
||||
private static final float VERTICAL_SNAP_SPEED = 50.0f;
|
||||
private final boolean disableFling;
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
public CarouselSnapHelper() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public CarouselSnapHelper(boolean z) {
|
||||
this.disableFling = z;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.SnapHelper
|
||||
public void attachToRecyclerView(RecyclerView recyclerView) {
|
||||
super.attachToRecyclerView(recyclerView);
|
||||
this.recyclerView = recyclerView;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.SnapHelper
|
||||
public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View view) {
|
||||
return calculateDistanceToSnap(layoutManager, view, false);
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public int[] calculateDistanceToSnap(RecyclerView.LayoutManager layoutManager, View view, boolean z) {
|
||||
if (!(layoutManager instanceof CarouselLayoutManager)) {
|
||||
return new int[]{0, 0};
|
||||
}
|
||||
int distanceToFirstFocalKeyline = distanceToFirstFocalKeyline(view, (CarouselLayoutManager) layoutManager, z);
|
||||
return layoutManager.canScrollHorizontally() ? new int[]{distanceToFirstFocalKeyline, 0} : layoutManager.canScrollVertically() ? new int[]{0, distanceToFirstFocalKeyline} : new int[]{0, 0};
|
||||
}
|
||||
|
||||
private int distanceToFirstFocalKeyline(View view, CarouselLayoutManager carouselLayoutManager, boolean z) {
|
||||
return carouselLayoutManager.getOffsetToScrollToPositionForSnap(carouselLayoutManager.getPosition(view), z);
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.SnapHelper
|
||||
public View findSnapView(RecyclerView.LayoutManager layoutManager) {
|
||||
return findViewNearestFirstKeyline(layoutManager);
|
||||
}
|
||||
|
||||
private View findViewNearestFirstKeyline(RecyclerView.LayoutManager layoutManager) {
|
||||
int childCount = layoutManager.getChildCount();
|
||||
View view = null;
|
||||
if (childCount != 0 && (layoutManager instanceof CarouselLayoutManager)) {
|
||||
CarouselLayoutManager carouselLayoutManager = (CarouselLayoutManager) layoutManager;
|
||||
int i = Integer.MAX_VALUE;
|
||||
for (int i2 = 0; i2 < childCount; i2++) {
|
||||
View childAt = layoutManager.getChildAt(i2);
|
||||
int abs = Math.abs(carouselLayoutManager.getOffsetToScrollToPositionForSnap(layoutManager.getPosition(childAt), false));
|
||||
if (abs < i) {
|
||||
view = childAt;
|
||||
i = abs;
|
||||
}
|
||||
}
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.SnapHelper
|
||||
public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int i, int i2) {
|
||||
int itemCount;
|
||||
if (!this.disableFling || (itemCount = layoutManager.getItemCount()) == 0) {
|
||||
return -1;
|
||||
}
|
||||
int childCount = layoutManager.getChildCount();
|
||||
View view = null;
|
||||
View view2 = null;
|
||||
int i3 = Integer.MIN_VALUE;
|
||||
int i4 = Integer.MAX_VALUE;
|
||||
for (int i5 = 0; i5 < childCount; i5++) {
|
||||
View childAt = layoutManager.getChildAt(i5);
|
||||
if (childAt != null) {
|
||||
int distanceToFirstFocalKeyline = distanceToFirstFocalKeyline(childAt, (CarouselLayoutManager) layoutManager, false);
|
||||
if (distanceToFirstFocalKeyline <= 0 && distanceToFirstFocalKeyline > i3) {
|
||||
view2 = childAt;
|
||||
i3 = distanceToFirstFocalKeyline;
|
||||
}
|
||||
if (distanceToFirstFocalKeyline >= 0 && distanceToFirstFocalKeyline < i4) {
|
||||
view = childAt;
|
||||
i4 = distanceToFirstFocalKeyline;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean isForwardFling = isForwardFling(layoutManager, i, i2);
|
||||
if (isForwardFling && view != null) {
|
||||
return layoutManager.getPosition(view);
|
||||
}
|
||||
if (!isForwardFling && view2 != null) {
|
||||
return layoutManager.getPosition(view2);
|
||||
}
|
||||
if (isForwardFling) {
|
||||
view = view2;
|
||||
}
|
||||
if (view == null) {
|
||||
return -1;
|
||||
}
|
||||
int position = layoutManager.getPosition(view) + (isReverseLayout(layoutManager) == isForwardFling ? -1 : 1);
|
||||
if (position < 0 || position >= itemCount) {
|
||||
return -1;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
private boolean isForwardFling(RecyclerView.LayoutManager layoutManager, int i, int i2) {
|
||||
return layoutManager.canScrollHorizontally() ? i > 0 : i2 > 0;
|
||||
}
|
||||
|
||||
/* JADX WARN: Multi-variable type inference failed */
|
||||
private boolean isReverseLayout(RecyclerView.LayoutManager layoutManager) {
|
||||
PointF computeScrollVectorForPosition;
|
||||
int itemCount = layoutManager.getItemCount();
|
||||
if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider) || (computeScrollVectorForPosition = ((RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager).computeScrollVectorForPosition(itemCount - 1)) == null) {
|
||||
return false;
|
||||
}
|
||||
return computeScrollVectorForPosition.x < 0.0f || computeScrollVectorForPosition.y < 0.0f;
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.SnapHelper
|
||||
protected RecyclerView.SmoothScroller createScroller(final RecyclerView.LayoutManager layoutManager) {
|
||||
if (layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider) {
|
||||
return new LinearSmoothScroller(this.recyclerView.getContext()) { // from class: com.google.android.material.carousel.CarouselSnapHelper.1
|
||||
@Override // androidx.recyclerview.widget.LinearSmoothScroller, androidx.recyclerview.widget.RecyclerView.SmoothScroller
|
||||
protected void onTargetFound(View view, RecyclerView.State state, RecyclerView.SmoothScroller.Action action) {
|
||||
if (CarouselSnapHelper.this.recyclerView != null) {
|
||||
CarouselSnapHelper carouselSnapHelper = CarouselSnapHelper.this;
|
||||
int[] calculateDistanceToSnap = carouselSnapHelper.calculateDistanceToSnap(carouselSnapHelper.recyclerView.getLayoutManager(), view, true);
|
||||
int i = calculateDistanceToSnap[0];
|
||||
int i2 = calculateDistanceToSnap[1];
|
||||
int calculateTimeForDeceleration = calculateTimeForDeceleration(Math.max(Math.abs(i), Math.abs(i2)));
|
||||
if (calculateTimeForDeceleration > 0) {
|
||||
action.update(i, i2, calculateTimeForDeceleration, this.mDecelerateInterpolator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // androidx.recyclerview.widget.LinearSmoothScroller
|
||||
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
|
||||
float f;
|
||||
float f2;
|
||||
if (layoutManager.canScrollVertically()) {
|
||||
f = displayMetrics.densityDpi;
|
||||
f2 = 50.0f;
|
||||
} else {
|
||||
f = displayMetrics.densityDpi;
|
||||
f2 = CarouselSnapHelper.HORIZONTAL_SNAP_SPEED;
|
||||
}
|
||||
return f2 / f;
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public abstract class CarouselStrategy {
|
||||
static float getChildMaskPercentage(float f, float f2, float f3) {
|
||||
return 1.0f - ((f - f3) / (f2 - f3));
|
||||
}
|
||||
|
||||
boolean isContained() {
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract KeylineState onFirstChildMeasuredWithMargins(Carousel carousel, View view);
|
||||
|
||||
boolean shouldRefreshKeylineState(Carousel carousel, int i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static int[] doubleCounts(int[] iArr) {
|
||||
int length = iArr.length;
|
||||
int[] iArr2 = new int[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
iArr2[i] = iArr[i] * 2;
|
||||
}
|
||||
return iArr2;
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.content.Context;
|
||||
import com.google.android.material.R;
|
||||
import com.google.android.material.carousel.KeylineState;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
final class CarouselStrategyHelper {
|
||||
static float addStart(float f, float f2, int i) {
|
||||
return i > 0 ? f + (f2 / 2.0f) : f;
|
||||
}
|
||||
|
||||
static float updateCurPosition(float f, float f2, float f3, int i) {
|
||||
return i > 0 ? f2 + (f3 / 2.0f) : f;
|
||||
}
|
||||
|
||||
private CarouselStrategyHelper() {
|
||||
}
|
||||
|
||||
static float getExtraSmallSize(Context context) {
|
||||
return context.getResources().getDimension(R.dimen.m3_carousel_gone_size);
|
||||
}
|
||||
|
||||
static float getSmallSizeMin(Context context) {
|
||||
return context.getResources().getDimension(R.dimen.m3_carousel_small_item_size_min);
|
||||
}
|
||||
|
||||
static float getSmallSizeMax(Context context) {
|
||||
return context.getResources().getDimension(R.dimen.m3_carousel_small_item_size_max);
|
||||
}
|
||||
|
||||
static KeylineState createKeylineState(Context context, float f, float f2, Arrangement arrangement, int i) {
|
||||
if (i == 1) {
|
||||
return createCenterAlignedKeylineState(context, f, f2, arrangement);
|
||||
}
|
||||
return createLeftAlignedKeylineState(context, f, f2, arrangement);
|
||||
}
|
||||
|
||||
static KeylineState createLeftAlignedKeylineState(Context context, float f, float f2, Arrangement arrangement) {
|
||||
float min = Math.min(getExtraSmallSize(context) + f, arrangement.largeSize);
|
||||
float f3 = min / 2.0f;
|
||||
float f4 = 0.0f - f3;
|
||||
float addStart = addStart(0.0f, arrangement.largeSize, arrangement.largeCount);
|
||||
float updateCurPosition = updateCurPosition(0.0f, addEnd(addStart, arrangement.largeSize, arrangement.largeCount), arrangement.largeSize, arrangement.largeCount);
|
||||
float addStart2 = addStart(updateCurPosition, arrangement.mediumSize, arrangement.mediumCount);
|
||||
float addStart3 = addStart(updateCurPosition(updateCurPosition, addStart2, arrangement.mediumSize, arrangement.mediumCount), arrangement.smallSize, arrangement.smallCount);
|
||||
float f5 = f3 + f2;
|
||||
float childMaskPercentage = CarouselStrategy.getChildMaskPercentage(min, arrangement.largeSize, f);
|
||||
float childMaskPercentage2 = CarouselStrategy.getChildMaskPercentage(arrangement.smallSize, arrangement.largeSize, f);
|
||||
float childMaskPercentage3 = CarouselStrategy.getChildMaskPercentage(arrangement.mediumSize, arrangement.largeSize, f);
|
||||
KeylineState.Builder addKeylineRange = new KeylineState.Builder(arrangement.largeSize, f2).addAnchorKeyline(f4, childMaskPercentage, min).addKeylineRange(addStart, 0.0f, arrangement.largeSize, arrangement.largeCount, true);
|
||||
if (arrangement.mediumCount > 0) {
|
||||
addKeylineRange.addKeyline(addStart2, childMaskPercentage3, arrangement.mediumSize);
|
||||
}
|
||||
if (arrangement.smallCount > 0) {
|
||||
addKeylineRange.addKeylineRange(addStart3, childMaskPercentage2, arrangement.smallSize, arrangement.smallCount);
|
||||
}
|
||||
addKeylineRange.addAnchorKeyline(f5, childMaskPercentage, min);
|
||||
return addKeylineRange.build();
|
||||
}
|
||||
|
||||
static KeylineState createCenterAlignedKeylineState(Context context, float f, float f2, Arrangement arrangement) {
|
||||
float f3;
|
||||
float min = Math.min(getExtraSmallSize(context) + f, arrangement.largeSize);
|
||||
float f4 = min / 2.0f;
|
||||
float f5 = 0.0f - f4;
|
||||
float addStart = addStart(0.0f, arrangement.smallSize, arrangement.smallCount);
|
||||
float updateCurPosition = updateCurPosition(0.0f, addEnd(addStart, arrangement.smallSize, (int) Math.floor(arrangement.smallCount / 2.0f)), arrangement.smallSize, arrangement.smallCount);
|
||||
float addStart2 = addStart(updateCurPosition, arrangement.mediumSize, arrangement.mediumCount);
|
||||
float updateCurPosition2 = updateCurPosition(updateCurPosition, addEnd(addStart2, arrangement.mediumSize, (int) Math.floor(arrangement.mediumCount / 2.0f)), arrangement.mediumSize, arrangement.mediumCount);
|
||||
float addStart3 = addStart(updateCurPosition2, arrangement.largeSize, arrangement.largeCount);
|
||||
float updateCurPosition3 = updateCurPosition(updateCurPosition2, addEnd(addStart3, arrangement.largeSize, arrangement.largeCount), arrangement.largeSize, arrangement.largeCount);
|
||||
float addStart4 = addStart(updateCurPosition3, arrangement.mediumSize, arrangement.mediumCount);
|
||||
float addStart5 = addStart(updateCurPosition(updateCurPosition3, addEnd(addStart4, arrangement.mediumSize, (int) Math.ceil(arrangement.mediumCount / 2.0f)), arrangement.mediumSize, arrangement.mediumCount), arrangement.smallSize, arrangement.smallCount);
|
||||
float f6 = f4 + f2;
|
||||
float childMaskPercentage = CarouselStrategy.getChildMaskPercentage(min, arrangement.largeSize, f);
|
||||
float childMaskPercentage2 = CarouselStrategy.getChildMaskPercentage(arrangement.smallSize, arrangement.largeSize, f);
|
||||
float childMaskPercentage3 = CarouselStrategy.getChildMaskPercentage(arrangement.mediumSize, arrangement.largeSize, f);
|
||||
KeylineState.Builder addAnchorKeyline = new KeylineState.Builder(arrangement.largeSize, f2).addAnchorKeyline(f5, childMaskPercentage, min);
|
||||
if (arrangement.smallCount > 0) {
|
||||
f3 = f6;
|
||||
addAnchorKeyline.addKeylineRange(addStart, childMaskPercentage2, arrangement.smallSize, (int) Math.floor(arrangement.smallCount / 2.0f));
|
||||
} else {
|
||||
f3 = f6;
|
||||
}
|
||||
if (arrangement.mediumCount > 0) {
|
||||
addAnchorKeyline.addKeylineRange(addStart2, childMaskPercentage3, arrangement.mediumSize, (int) Math.floor(arrangement.mediumCount / 2.0f));
|
||||
}
|
||||
addAnchorKeyline.addKeylineRange(addStart3, 0.0f, arrangement.largeSize, arrangement.largeCount, true);
|
||||
if (arrangement.mediumCount > 0) {
|
||||
addAnchorKeyline.addKeylineRange(addStart4, childMaskPercentage3, arrangement.mediumSize, (int) Math.ceil(arrangement.mediumCount / 2.0f));
|
||||
}
|
||||
if (arrangement.smallCount > 0) {
|
||||
addAnchorKeyline.addKeylineRange(addStart5, childMaskPercentage2, arrangement.smallSize, (int) Math.ceil(arrangement.smallCount / 2.0f));
|
||||
}
|
||||
addAnchorKeyline.addAnchorKeyline(f3, childMaskPercentage, min);
|
||||
return addAnchorKeyline.build();
|
||||
}
|
||||
|
||||
static int maxValue(int[] iArr) {
|
||||
int i = Integer.MIN_VALUE;
|
||||
for (int i2 : iArr) {
|
||||
if (i2 > i) {
|
||||
i = i2;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static float addEnd(float f, float f2, int i) {
|
||||
return f + (Math.max(0, i - 1) * f2);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class FullScreenCarouselStrategy extends CarouselStrategy {
|
||||
@Override // com.google.android.material.carousel.CarouselStrategy
|
||||
KeylineState onFirstChildMeasuredWithMargins(Carousel carousel, View view) {
|
||||
float containerHeight;
|
||||
int i;
|
||||
int i2;
|
||||
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
|
||||
if (carousel.isHorizontal()) {
|
||||
containerHeight = carousel.getContainerWidth();
|
||||
i = layoutParams.leftMargin;
|
||||
i2 = layoutParams.rightMargin;
|
||||
} else {
|
||||
containerHeight = carousel.getContainerHeight();
|
||||
i = layoutParams.topMargin;
|
||||
i2 = layoutParams.bottomMargin;
|
||||
}
|
||||
float f = i + i2;
|
||||
return CarouselStrategyHelper.createLeftAlignedKeylineState(view.getContext(), f, containerHeight, new Arrangement(0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0, Math.min(containerHeight + f, containerHeight), 1, containerHeight));
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.core.math.MathUtils;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class HeroCarouselStrategy extends CarouselStrategy {
|
||||
private int keylineCount = 0;
|
||||
private static final int[] SMALL_COUNTS = {1};
|
||||
private static final int[] MEDIUM_COUNTS = {0, 1};
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselStrategy
|
||||
KeylineState onFirstChildMeasuredWithMargins(Carousel carousel, View view) {
|
||||
int i;
|
||||
int containerHeight = carousel.getContainerHeight();
|
||||
if (carousel.isHorizontal()) {
|
||||
containerHeight = carousel.getContainerWidth();
|
||||
}
|
||||
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
|
||||
float f = layoutParams.topMargin + layoutParams.bottomMargin;
|
||||
float measuredWidth = view.getMeasuredWidth() * 2;
|
||||
if (carousel.isHorizontal()) {
|
||||
f = layoutParams.leftMargin + layoutParams.rightMargin;
|
||||
measuredWidth = view.getMeasuredHeight() * 2;
|
||||
}
|
||||
float smallSizeMin = CarouselStrategyHelper.getSmallSizeMin(view.getContext()) + f;
|
||||
float smallSizeMax = CarouselStrategyHelper.getSmallSizeMax(view.getContext()) + f;
|
||||
float f2 = containerHeight;
|
||||
float min = Math.min(measuredWidth + f, f2);
|
||||
float clamp = MathUtils.clamp((measuredWidth / 3.0f) + f, CarouselStrategyHelper.getSmallSizeMin(view.getContext()) + f, CarouselStrategyHelper.getSmallSizeMax(view.getContext()) + f);
|
||||
float f3 = (min + clamp) / 2.0f;
|
||||
int[] iArr = f2 < 2.0f * smallSizeMin ? new int[]{0} : SMALL_COUNTS;
|
||||
int max = (int) Math.max(1.0d, Math.floor((f2 - (CarouselStrategyHelper.maxValue(r4) * smallSizeMax)) / min));
|
||||
int ceil = (((int) Math.ceil(f2 / min)) - max) + 1;
|
||||
int[] iArr2 = new int[ceil];
|
||||
for (int i2 = 0; i2 < ceil; i2++) {
|
||||
iArr2[i2] = max + i2;
|
||||
}
|
||||
int i3 = carousel.getCarouselAlignment() == 1 ? 1 : 0;
|
||||
Arrangement findLowestCostArrangement = Arrangement.findLowestCostArrangement(f2, clamp, smallSizeMin, smallSizeMax, i3 != 0 ? doubleCounts(iArr) : iArr, f3, i3 != 0 ? doubleCounts(MEDIUM_COUNTS) : MEDIUM_COUNTS, min, iArr2);
|
||||
this.keylineCount = findLowestCostArrangement.getItemCount();
|
||||
if (findLowestCostArrangement.getItemCount() > carousel.getItemCount()) {
|
||||
findLowestCostArrangement = Arrangement.findLowestCostArrangement(f2, clamp, smallSizeMin, smallSizeMax, iArr, f3, MEDIUM_COUNTS, min, iArr2);
|
||||
i = 0;
|
||||
} else {
|
||||
i = i3;
|
||||
}
|
||||
return CarouselStrategyHelper.createKeylineState(view.getContext(), f, f2, findLowestCostArrangement, i);
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselStrategy
|
||||
boolean shouldRefreshKeylineState(Carousel carousel, int i) {
|
||||
if (carousel.getCarouselAlignment() == 1) {
|
||||
if (i < this.keylineCount && carousel.getItemCount() >= this.keylineCount) {
|
||||
return true;
|
||||
}
|
||||
if (i >= this.keylineCount && carousel.getItemCount() < this.keylineCount) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import com.google.android.material.animation.AnimationUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
final class KeylineState {
|
||||
private final int firstFocalKeylineIndex;
|
||||
private final float itemSize;
|
||||
private final List<Keyline> keylines;
|
||||
private final int lastFocalKeylineIndex;
|
||||
|
||||
int getFirstFocalKeylineIndex() {
|
||||
return this.firstFocalKeylineIndex;
|
||||
}
|
||||
|
||||
float getItemSize() {
|
||||
return this.itemSize;
|
||||
}
|
||||
|
||||
List<Keyline> getKeylines() {
|
||||
return this.keylines;
|
||||
}
|
||||
|
||||
int getLastFocalKeylineIndex() {
|
||||
return this.lastFocalKeylineIndex;
|
||||
}
|
||||
|
||||
private KeylineState(float f, List<Keyline> list, int i, int i2) {
|
||||
this.itemSize = f;
|
||||
this.keylines = Collections.unmodifiableList(list);
|
||||
this.firstFocalKeylineIndex = i;
|
||||
this.lastFocalKeylineIndex = i2;
|
||||
}
|
||||
|
||||
Keyline getFirstFocalKeyline() {
|
||||
return this.keylines.get(this.firstFocalKeylineIndex);
|
||||
}
|
||||
|
||||
Keyline getLastFocalKeyline() {
|
||||
return this.keylines.get(this.lastFocalKeylineIndex);
|
||||
}
|
||||
|
||||
List<Keyline> getFocalKeylines() {
|
||||
return this.keylines.subList(this.firstFocalKeylineIndex, this.lastFocalKeylineIndex + 1);
|
||||
}
|
||||
|
||||
Keyline getFirstKeyline() {
|
||||
return this.keylines.get(0);
|
||||
}
|
||||
|
||||
Keyline getLastKeyline() {
|
||||
return this.keylines.get(r0.size() - 1);
|
||||
}
|
||||
|
||||
Keyline getFirstNonAnchorKeyline() {
|
||||
for (int i = 0; i < this.keylines.size(); i++) {
|
||||
Keyline keyline = this.keylines.get(i);
|
||||
if (!keyline.isAnchor) {
|
||||
return keyline;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Keyline getLastNonAnchorKeyline() {
|
||||
for (int size = this.keylines.size() - 1; size >= 0; size--) {
|
||||
Keyline keyline = this.keylines.get(size);
|
||||
if (!keyline.isAnchor) {
|
||||
return keyline;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static KeylineState lerp(KeylineState keylineState, KeylineState keylineState2, float f) {
|
||||
if (keylineState.getItemSize() != keylineState2.getItemSize()) {
|
||||
throw new IllegalArgumentException("Keylines being linearly interpolated must have the same item size.");
|
||||
}
|
||||
List<Keyline> keylines = keylineState.getKeylines();
|
||||
List<Keyline> keylines2 = keylineState2.getKeylines();
|
||||
if (keylines.size() != keylines2.size()) {
|
||||
throw new IllegalArgumentException("Keylines being linearly interpolated must have the same number of keylines.");
|
||||
}
|
||||
ArrayList arrayList = new ArrayList();
|
||||
for (int i = 0; i < keylineState.getKeylines().size(); i++) {
|
||||
arrayList.add(Keyline.lerp(keylines.get(i), keylines2.get(i), f));
|
||||
}
|
||||
return new KeylineState(keylineState.getItemSize(), arrayList, AnimationUtils.lerp(keylineState.getFirstFocalKeylineIndex(), keylineState2.getFirstFocalKeylineIndex(), f), AnimationUtils.lerp(keylineState.getLastFocalKeylineIndex(), keylineState2.getLastFocalKeylineIndex(), f));
|
||||
}
|
||||
|
||||
static KeylineState reverse(KeylineState keylineState, float f) {
|
||||
Builder builder = new Builder(keylineState.getItemSize(), f);
|
||||
float f2 = (f - keylineState.getLastKeyline().locOffset) - (keylineState.getLastKeyline().maskedItemSize / 2.0f);
|
||||
int size = keylineState.getKeylines().size() - 1;
|
||||
while (size >= 0) {
|
||||
Keyline keyline = keylineState.getKeylines().get(size);
|
||||
builder.addKeyline(f2 + (keyline.maskedItemSize / 2.0f), keyline.mask, keyline.maskedItemSize, size >= keylineState.getFirstFocalKeylineIndex() && size <= keylineState.getLastFocalKeylineIndex(), keyline.isAnchor);
|
||||
f2 += keyline.maskedItemSize;
|
||||
size--;
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static final class Builder {
|
||||
private static final int NO_INDEX = -1;
|
||||
private static final float UNKNOWN_LOC = Float.MIN_VALUE;
|
||||
private final float availableSpace;
|
||||
private final float itemSize;
|
||||
private Keyline tmpFirstFocalKeyline;
|
||||
private Keyline tmpLastFocalKeyline;
|
||||
private final List<Keyline> tmpKeylines = new ArrayList();
|
||||
private int firstFocalKeylineIndex = -1;
|
||||
private int lastFocalKeylineIndex = -1;
|
||||
private float lastKeylineMaskedSize = 0.0f;
|
||||
private int latestAnchorKeylineIndex = -1;
|
||||
|
||||
private static float calculateKeylineLocationForItemPosition(float f, float f2, int i, int i2) {
|
||||
return (f - (i * f2)) + (i2 * f2);
|
||||
}
|
||||
|
||||
Builder(float f, float f2) {
|
||||
this.itemSize = f;
|
||||
this.availableSpace = f2;
|
||||
}
|
||||
|
||||
Builder addKeyline(float f, float f2, float f3, boolean z) {
|
||||
return addKeyline(f, f2, f3, z, false);
|
||||
}
|
||||
|
||||
Builder addKeyline(float f, float f2, float f3) {
|
||||
return addKeyline(f, f2, f3, false);
|
||||
}
|
||||
|
||||
Builder addKeyline(float f, float f2, float f3, boolean z, boolean z2, float f4) {
|
||||
if (f3 <= 0.0f) {
|
||||
return this;
|
||||
}
|
||||
if (z2) {
|
||||
if (z) {
|
||||
throw new IllegalArgumentException("Anchor keylines cannot be focal.");
|
||||
}
|
||||
int i = this.latestAnchorKeylineIndex;
|
||||
if (i != -1 && i != 0) {
|
||||
throw new IllegalArgumentException("Anchor keylines must be either the first or last keyline.");
|
||||
}
|
||||
this.latestAnchorKeylineIndex = this.tmpKeylines.size();
|
||||
}
|
||||
Keyline keyline = new Keyline(Float.MIN_VALUE, f, f2, f3, z2, f4);
|
||||
if (z) {
|
||||
if (this.tmpFirstFocalKeyline == null) {
|
||||
this.tmpFirstFocalKeyline = keyline;
|
||||
this.firstFocalKeylineIndex = this.tmpKeylines.size();
|
||||
}
|
||||
if (this.lastFocalKeylineIndex != -1 && this.tmpKeylines.size() - this.lastFocalKeylineIndex > 1) {
|
||||
throw new IllegalArgumentException("Keylines marked as focal must be placed next to each other. There cannot be non-focal keylines between focal keylines.");
|
||||
}
|
||||
if (f3 != this.tmpFirstFocalKeyline.maskedItemSize) {
|
||||
throw new IllegalArgumentException("Keylines that are marked as focal must all have the same masked item size.");
|
||||
}
|
||||
this.tmpLastFocalKeyline = keyline;
|
||||
this.lastFocalKeylineIndex = this.tmpKeylines.size();
|
||||
} else {
|
||||
if (this.tmpFirstFocalKeyline == null && keyline.maskedItemSize < this.lastKeylineMaskedSize) {
|
||||
throw new IllegalArgumentException("Keylines before the first focal keyline must be ordered by incrementing masked item size.");
|
||||
}
|
||||
if (this.tmpLastFocalKeyline != null && keyline.maskedItemSize > this.lastKeylineMaskedSize) {
|
||||
throw new IllegalArgumentException("Keylines after the last focal keyline must be ordered by decreasing masked item size.");
|
||||
}
|
||||
}
|
||||
this.lastKeylineMaskedSize = keyline.maskedItemSize;
|
||||
this.tmpKeylines.add(keyline);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder addKeyline(float f, float f2, float f3, boolean z, boolean z2) {
|
||||
float f4;
|
||||
float abs;
|
||||
float f5 = f3 / 2.0f;
|
||||
float f6 = f - f5;
|
||||
float f7 = f5 + f;
|
||||
float f8 = this.availableSpace;
|
||||
if (f7 > f8) {
|
||||
abs = Math.abs(f7 - Math.max(f7 - f3, f8));
|
||||
} else if (f6 < 0.0f) {
|
||||
abs = Math.abs(f6 - Math.min(f6 + f3, 0.0f));
|
||||
} else {
|
||||
f4 = 0.0f;
|
||||
return addKeyline(f, f2, f3, z, z2, f4);
|
||||
}
|
||||
f4 = abs;
|
||||
return addKeyline(f, f2, f3, z, z2, f4);
|
||||
}
|
||||
|
||||
Builder addAnchorKeyline(float f, float f2, float f3) {
|
||||
return addKeyline(f, f2, f3, false, true);
|
||||
}
|
||||
|
||||
Builder addKeylineRange(float f, float f2, float f3, int i) {
|
||||
return addKeylineRange(f, f2, f3, i, false);
|
||||
}
|
||||
|
||||
Builder addKeylineRange(float f, float f2, float f3, int i, boolean z) {
|
||||
if (i > 0 && f3 > 0.0f) {
|
||||
for (int i2 = 0; i2 < i; i2++) {
|
||||
addKeyline((i2 * f3) + f, f2, f3, z);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
KeylineState build() {
|
||||
if (this.tmpFirstFocalKeyline == null) {
|
||||
throw new IllegalStateException("There must be a keyline marked as focal.");
|
||||
}
|
||||
ArrayList arrayList = new ArrayList();
|
||||
for (int i = 0; i < this.tmpKeylines.size(); i++) {
|
||||
Keyline keyline = this.tmpKeylines.get(i);
|
||||
arrayList.add(new Keyline(calculateKeylineLocationForItemPosition(this.tmpFirstFocalKeyline.locOffset, this.itemSize, this.firstFocalKeylineIndex, i), keyline.locOffset, keyline.mask, keyline.maskedItemSize, keyline.isAnchor, keyline.cutoff));
|
||||
}
|
||||
return new KeylineState(this.itemSize, arrayList, this.firstFocalKeylineIndex, this.lastFocalKeylineIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static final class Keyline {
|
||||
final float cutoff;
|
||||
final boolean isAnchor;
|
||||
final float loc;
|
||||
final float locOffset;
|
||||
final float mask;
|
||||
final float maskedItemSize;
|
||||
|
||||
Keyline(float f, float f2, float f3, float f4) {
|
||||
this(f, f2, f3, f4, false, 0.0f);
|
||||
}
|
||||
|
||||
Keyline(float f, float f2, float f3, float f4, boolean z, float f5) {
|
||||
this.loc = f;
|
||||
this.locOffset = f2;
|
||||
this.mask = f3;
|
||||
this.maskedItemSize = f4;
|
||||
this.isAnchor = z;
|
||||
this.cutoff = f5;
|
||||
}
|
||||
|
||||
static Keyline lerp(Keyline keyline, Keyline keyline2, float f) {
|
||||
return new Keyline(AnimationUtils.lerp(keyline.loc, keyline2.loc, f), AnimationUtils.lerp(keyline.locOffset, keyline2.locOffset, f), AnimationUtils.lerp(keyline.mask, keyline2.mask, f), AnimationUtils.lerp(keyline.maskedItemSize, keyline2.maskedItemSize, f));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,277 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import androidx.core.math.MathUtils;
|
||||
import com.google.android.material.animation.AnimationUtils;
|
||||
import com.google.android.material.carousel.KeylineState;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
class KeylineStateList {
|
||||
private static final int NO_INDEX = -1;
|
||||
private final KeylineState defaultState;
|
||||
private final float endShiftRange;
|
||||
private final List<KeylineState> endStateSteps;
|
||||
private final float[] endStateStepsInterpolationPoints;
|
||||
private final float startShiftRange;
|
||||
private final List<KeylineState> startStateSteps;
|
||||
private final float[] startStateStepsInterpolationPoints;
|
||||
|
||||
KeylineState getDefaultState() {
|
||||
return this.defaultState;
|
||||
}
|
||||
|
||||
private KeylineStateList(KeylineState keylineState, List<KeylineState> list, List<KeylineState> list2) {
|
||||
this.defaultState = keylineState;
|
||||
this.startStateSteps = Collections.unmodifiableList(list);
|
||||
this.endStateSteps = Collections.unmodifiableList(list2);
|
||||
float f = list.get(list.size() - 1).getFirstKeyline().loc - keylineState.getFirstKeyline().loc;
|
||||
this.startShiftRange = f;
|
||||
float f2 = keylineState.getLastKeyline().loc - list2.get(list2.size() - 1).getLastKeyline().loc;
|
||||
this.endShiftRange = f2;
|
||||
this.startStateStepsInterpolationPoints = getStateStepInterpolationPoints(f, list, true);
|
||||
this.endStateStepsInterpolationPoints = getStateStepInterpolationPoints(f2, list2, false);
|
||||
}
|
||||
|
||||
static KeylineStateList from(Carousel carousel, KeylineState keylineState) {
|
||||
return new KeylineStateList(keylineState, getStateStepsStart(carousel, keylineState), getStateStepsEnd(carousel, keylineState));
|
||||
}
|
||||
|
||||
KeylineState getStartState() {
|
||||
return this.startStateSteps.get(r0.size() - 1);
|
||||
}
|
||||
|
||||
KeylineState getEndState() {
|
||||
return this.endStateSteps.get(r0.size() - 1);
|
||||
}
|
||||
|
||||
public KeylineState getShiftedState(float f, float f2, float f3) {
|
||||
return getShiftedState(f, f2, f3, false);
|
||||
}
|
||||
|
||||
KeylineState getShiftedState(float f, float f2, float f3, boolean z) {
|
||||
float lerp;
|
||||
List<KeylineState> list;
|
||||
float[] fArr;
|
||||
float f4 = this.startShiftRange + f2;
|
||||
float f5 = f3 - this.endShiftRange;
|
||||
if (f < f4) {
|
||||
lerp = AnimationUtils.lerp(1.0f, 0.0f, f2, f4, f);
|
||||
list = this.startStateSteps;
|
||||
fArr = this.startStateStepsInterpolationPoints;
|
||||
} else {
|
||||
if (f <= f5) {
|
||||
return this.defaultState;
|
||||
}
|
||||
lerp = AnimationUtils.lerp(0.0f, 1.0f, f5, f3, f);
|
||||
list = this.endStateSteps;
|
||||
fArr = this.endStateStepsInterpolationPoints;
|
||||
}
|
||||
if (z) {
|
||||
return closestStateStepFromInterpolation(list, lerp, fArr);
|
||||
}
|
||||
return lerp(list, lerp, fArr);
|
||||
}
|
||||
|
||||
private static KeylineState lerp(List<KeylineState> list, float f, float[] fArr) {
|
||||
float[] stateStepsRange = getStateStepsRange(list, f, fArr);
|
||||
return KeylineState.lerp(list.get((int) stateStepsRange[1]), list.get((int) stateStepsRange[2]), stateStepsRange[0]);
|
||||
}
|
||||
|
||||
private static float[] getStateStepsRange(List<KeylineState> list, float f, float[] fArr) {
|
||||
int size = list.size();
|
||||
float f2 = fArr[0];
|
||||
int i = 1;
|
||||
while (i < size) {
|
||||
float f3 = fArr[i];
|
||||
if (f <= f3) {
|
||||
return new float[]{AnimationUtils.lerp(0.0f, 1.0f, f2, f3, f), i - 1, i};
|
||||
}
|
||||
i++;
|
||||
f2 = f3;
|
||||
}
|
||||
return new float[]{0.0f, 0.0f, 0.0f};
|
||||
}
|
||||
|
||||
private KeylineState closestStateStepFromInterpolation(List<KeylineState> list, float f, float[] fArr) {
|
||||
float[] stateStepsRange = getStateStepsRange(list, f, fArr);
|
||||
if (stateStepsRange[0] > 0.5f) {
|
||||
return list.get((int) stateStepsRange[2]);
|
||||
}
|
||||
return list.get((int) stateStepsRange[1]);
|
||||
}
|
||||
|
||||
private static float[] getStateStepInterpolationPoints(float f, List<KeylineState> list, boolean z) {
|
||||
float f2;
|
||||
int size = list.size();
|
||||
float[] fArr = new float[size];
|
||||
int i = 1;
|
||||
while (i < size) {
|
||||
int i2 = i - 1;
|
||||
KeylineState keylineState = list.get(i2);
|
||||
KeylineState keylineState2 = list.get(i);
|
||||
if (z) {
|
||||
f2 = keylineState2.getFirstKeyline().loc - keylineState.getFirstKeyline().loc;
|
||||
} else {
|
||||
f2 = keylineState.getLastKeyline().loc - keylineState2.getLastKeyline().loc;
|
||||
}
|
||||
fArr[i] = i == size + (-1) ? 1.0f : fArr[i2] + (f2 / f);
|
||||
i++;
|
||||
}
|
||||
return fArr;
|
||||
}
|
||||
|
||||
private static boolean isFirstFocalItemAtLeftOfContainer(KeylineState keylineState) {
|
||||
return keylineState.getFirstFocalKeyline().locOffset - (keylineState.getFirstFocalKeyline().maskedItemSize / 2.0f) >= 0.0f && keylineState.getFirstFocalKeyline() == keylineState.getFirstNonAnchorKeyline();
|
||||
}
|
||||
|
||||
private static boolean isLastFocalItemVisibleAtRightOfContainer(Carousel carousel, KeylineState keylineState) {
|
||||
int containerHeight = carousel.getContainerHeight();
|
||||
if (carousel.isHorizontal()) {
|
||||
containerHeight = carousel.getContainerWidth();
|
||||
}
|
||||
return keylineState.getLastFocalKeyline().locOffset + (keylineState.getLastFocalKeyline().maskedItemSize / 2.0f) <= ((float) containerHeight) && keylineState.getLastFocalKeyline() == keylineState.getLastNonAnchorKeyline();
|
||||
}
|
||||
|
||||
private static List<KeylineState> getStateStepsStart(Carousel carousel, KeylineState keylineState) {
|
||||
ArrayList arrayList = new ArrayList();
|
||||
arrayList.add(keylineState);
|
||||
int findFirstNonAnchorKeylineIndex = findFirstNonAnchorKeylineIndex(keylineState);
|
||||
if (!isFirstFocalItemAtLeftOfContainer(keylineState) && findFirstNonAnchorKeylineIndex != -1) {
|
||||
int firstFocalKeylineIndex = keylineState.getFirstFocalKeylineIndex() - findFirstNonAnchorKeylineIndex;
|
||||
float containerWidth = carousel.isHorizontal() ? carousel.getContainerWidth() : carousel.getContainerHeight();
|
||||
float f = keylineState.getFirstKeyline().locOffset - (keylineState.getFirstKeyline().maskedItemSize / 2.0f);
|
||||
float f2 = 0.0f;
|
||||
if (firstFocalKeylineIndex <= 0 && keylineState.getFirstFocalKeyline().cutoff > 0.0f) {
|
||||
arrayList.add(shiftKeylinesAndCreateKeylineState(keylineState, f + keylineState.getFirstFocalKeyline().cutoff, containerWidth));
|
||||
return arrayList;
|
||||
}
|
||||
int i = 0;
|
||||
while (i < firstFocalKeylineIndex) {
|
||||
KeylineState keylineState2 = (KeylineState) arrayList.get(arrayList.size() - 1);
|
||||
int i2 = findFirstNonAnchorKeylineIndex + i;
|
||||
int size = keylineState.getKeylines().size() - 1;
|
||||
float f3 = f2 + keylineState.getKeylines().get(i2).cutoff;
|
||||
arrayList.add(moveKeylineAndCreateKeylineState(keylineState2, findFirstNonAnchorKeylineIndex, i2 - 1 >= 0 ? findFirstIndexAfterLastFocalKeylineWithMask(keylineState2, keylineState.getKeylines().get(r3).mask) - 1 : size, f + f3, (keylineState.getFirstFocalKeylineIndex() - i) - 1, (keylineState.getLastFocalKeylineIndex() - i) - 1, containerWidth));
|
||||
i++;
|
||||
f2 = f3;
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
private static List<KeylineState> getStateStepsEnd(Carousel carousel, KeylineState keylineState) {
|
||||
ArrayList arrayList = new ArrayList();
|
||||
arrayList.add(keylineState);
|
||||
int findLastNonAnchorKeylineIndex = findLastNonAnchorKeylineIndex(keylineState);
|
||||
if (!isLastFocalItemVisibleAtRightOfContainer(carousel, keylineState) && findLastNonAnchorKeylineIndex != -1) {
|
||||
int lastFocalKeylineIndex = findLastNonAnchorKeylineIndex - keylineState.getLastFocalKeylineIndex();
|
||||
float containerWidth = carousel.isHorizontal() ? carousel.getContainerWidth() : carousel.getContainerHeight();
|
||||
float f = keylineState.getFirstKeyline().locOffset - (keylineState.getFirstKeyline().maskedItemSize / 2.0f);
|
||||
float f2 = 0.0f;
|
||||
if (lastFocalKeylineIndex <= 0 && keylineState.getLastFocalKeyline().cutoff > 0.0f) {
|
||||
arrayList.add(shiftKeylinesAndCreateKeylineState(keylineState, f - keylineState.getLastFocalKeyline().cutoff, containerWidth));
|
||||
return arrayList;
|
||||
}
|
||||
int i = 0;
|
||||
while (i < lastFocalKeylineIndex) {
|
||||
KeylineState keylineState2 = (KeylineState) arrayList.get(arrayList.size() - 1);
|
||||
int i2 = findLastNonAnchorKeylineIndex - i;
|
||||
float f3 = f2 + keylineState.getKeylines().get(i2).cutoff;
|
||||
int i3 = i2 + 1;
|
||||
arrayList.add(moveKeylineAndCreateKeylineState(keylineState2, findLastNonAnchorKeylineIndex, i3 < keylineState.getKeylines().size() ? findLastIndexBeforeFirstFocalKeylineWithMask(keylineState2, keylineState.getKeylines().get(i3).mask) + 1 : 0, f - f3, keylineState.getFirstFocalKeylineIndex() + i + 1, keylineState.getLastFocalKeylineIndex() + i + 1, containerWidth));
|
||||
i++;
|
||||
f2 = f3;
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
private static KeylineState shiftKeylinesAndCreateKeylineState(KeylineState keylineState, float f, float f2) {
|
||||
return moveKeylineAndCreateKeylineState(keylineState, 0, 0, f, keylineState.getFirstFocalKeylineIndex(), keylineState.getLastFocalKeylineIndex(), f2);
|
||||
}
|
||||
|
||||
private static KeylineState moveKeylineAndCreateKeylineState(KeylineState keylineState, int i, int i2, float f, int i3, int i4, float f2) {
|
||||
ArrayList arrayList = new ArrayList(keylineState.getKeylines());
|
||||
arrayList.add(i2, (KeylineState.Keyline) arrayList.remove(i));
|
||||
KeylineState.Builder builder = new KeylineState.Builder(keylineState.getItemSize(), f2);
|
||||
int i5 = 0;
|
||||
while (i5 < arrayList.size()) {
|
||||
KeylineState.Keyline keyline = (KeylineState.Keyline) arrayList.get(i5);
|
||||
builder.addKeyline(f + (keyline.maskedItemSize / 2.0f), keyline.mask, keyline.maskedItemSize, i5 >= i3 && i5 <= i4, keyline.isAnchor, keyline.cutoff);
|
||||
f += keyline.maskedItemSize;
|
||||
i5++;
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static int findFirstIndexAfterLastFocalKeylineWithMask(KeylineState keylineState, float f) {
|
||||
for (int lastFocalKeylineIndex = keylineState.getLastFocalKeylineIndex(); lastFocalKeylineIndex < keylineState.getKeylines().size(); lastFocalKeylineIndex++) {
|
||||
if (f == keylineState.getKeylines().get(lastFocalKeylineIndex).mask) {
|
||||
return lastFocalKeylineIndex;
|
||||
}
|
||||
}
|
||||
return keylineState.getKeylines().size() - 1;
|
||||
}
|
||||
|
||||
private static int findLastIndexBeforeFirstFocalKeylineWithMask(KeylineState keylineState, float f) {
|
||||
for (int firstFocalKeylineIndex = keylineState.getFirstFocalKeylineIndex() - 1; firstFocalKeylineIndex >= 0; firstFocalKeylineIndex--) {
|
||||
if (f == keylineState.getKeylines().get(firstFocalKeylineIndex).mask) {
|
||||
return firstFocalKeylineIndex;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int findFirstNonAnchorKeylineIndex(KeylineState keylineState) {
|
||||
for (int i = 0; i < keylineState.getKeylines().size(); i++) {
|
||||
if (!keylineState.getKeylines().get(i).isAnchor) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int findLastNonAnchorKeylineIndex(KeylineState keylineState) {
|
||||
for (int size = keylineState.getKeylines().size() - 1; size >= 0; size--) {
|
||||
if (!keylineState.getKeylines().get(size).isAnchor) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Map<Integer, KeylineState> getKeylineStateForPositionMap(int i, int i2, int i3, boolean z) {
|
||||
float itemSize = this.defaultState.getItemSize();
|
||||
HashMap hashMap = new HashMap();
|
||||
int i4 = 0;
|
||||
int i5 = 0;
|
||||
while (true) {
|
||||
if (i4 >= i) {
|
||||
break;
|
||||
}
|
||||
int i6 = z ? (i - i4) - 1 : i4;
|
||||
if (i6 * itemSize * (z ? -1 : 1) > i3 - this.endShiftRange || i4 >= i - this.endStateSteps.size()) {
|
||||
Integer valueOf = Integer.valueOf(i6);
|
||||
List<KeylineState> list = this.endStateSteps;
|
||||
hashMap.put(valueOf, list.get(MathUtils.clamp(i5, 0, list.size() - 1)));
|
||||
i5++;
|
||||
}
|
||||
i4++;
|
||||
}
|
||||
int i7 = 0;
|
||||
for (int i8 = i - 1; i8 >= 0; i8--) {
|
||||
int i9 = z ? (i - i8) - 1 : i8;
|
||||
if (i9 * itemSize * (z ? -1 : 1) < i2 + this.startShiftRange || i8 < this.startStateSteps.size()) {
|
||||
Integer valueOf2 = Integer.valueOf(i9);
|
||||
List<KeylineState> list2 = this.startStateSteps;
|
||||
hashMap.put(valueOf2, list2.get(MathUtils.clamp(i7, 0, list2.size() - 1)));
|
||||
i7++;
|
||||
}
|
||||
}
|
||||
return hashMap;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
interface Maskable {
|
||||
RectF getMaskRectF();
|
||||
|
||||
@Deprecated
|
||||
float getMaskXPercentage();
|
||||
|
||||
void setMaskRectF(RectF rectF);
|
||||
|
||||
@Deprecated
|
||||
void setMaskXPercentage(float f);
|
||||
|
||||
void setOnMaskChangedListener(OnMaskChangedListener onMaskChangedListener);
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.core.math.MathUtils;
|
||||
import com.google.android.material.animation.AnimationUtils;
|
||||
import com.google.android.material.canvas.CanvasCompat;
|
||||
import com.google.android.material.shape.AbsoluteCornerSize;
|
||||
import com.google.android.material.shape.ClampedCornerSize;
|
||||
import com.google.android.material.shape.CornerSize;
|
||||
import com.google.android.material.shape.ShapeAppearanceModel;
|
||||
import com.google.android.material.shape.Shapeable;
|
||||
import com.google.android.material.shape.ShapeableDelegate;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class MaskableFrameLayout extends FrameLayout implements Maskable, Shapeable {
|
||||
private static final int NOT_SET = -1;
|
||||
private final RectF maskRect;
|
||||
private float maskXPercentage;
|
||||
private OnMaskChangedListener onMaskChangedListener;
|
||||
private Boolean savedForceCompatClippingEnabled;
|
||||
private ShapeAppearanceModel shapeAppearanceModel;
|
||||
private final ShapeableDelegate shapeableDelegate;
|
||||
|
||||
@Override // com.google.android.material.carousel.Maskable
|
||||
public RectF getMaskRectF() {
|
||||
return this.maskRect;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Maskable
|
||||
@Deprecated
|
||||
public float getMaskXPercentage() {
|
||||
return this.maskXPercentage;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.shape.Shapeable
|
||||
public ShapeAppearanceModel getShapeAppearanceModel() {
|
||||
return this.shapeAppearanceModel;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Maskable
|
||||
public void setOnMaskChangedListener(OnMaskChangedListener onMaskChangedListener) {
|
||||
this.onMaskChangedListener = onMaskChangedListener;
|
||||
}
|
||||
|
||||
public MaskableFrameLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public MaskableFrameLayout(Context context, AttributeSet attributeSet) {
|
||||
this(context, attributeSet, 0);
|
||||
}
|
||||
|
||||
public MaskableFrameLayout(Context context, AttributeSet attributeSet, int i) {
|
||||
super(context, attributeSet, i);
|
||||
this.maskXPercentage = -1.0f;
|
||||
this.maskRect = new RectF();
|
||||
this.shapeableDelegate = ShapeableDelegate.create(this);
|
||||
this.savedForceCompatClippingEnabled = null;
|
||||
setShapeAppearanceModel(ShapeAppearanceModel.builder(context, attributeSet, i, 0, 0).build());
|
||||
}
|
||||
|
||||
@Override // android.view.View
|
||||
protected void onSizeChanged(int i, int i2, int i3, int i4) {
|
||||
super.onSizeChanged(i, i2, i3, i4);
|
||||
if (this.maskXPercentage != -1.0f) {
|
||||
updateMaskRectForMaskXPercentage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // android.view.View
|
||||
public void getFocusedRect(Rect rect) {
|
||||
rect.set((int) this.maskRect.left, (int) this.maskRect.top, (int) this.maskRect.right, (int) this.maskRect.bottom);
|
||||
}
|
||||
|
||||
@Override // android.view.ViewGroup, android.view.View
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
Boolean bool = this.savedForceCompatClippingEnabled;
|
||||
if (bool != null) {
|
||||
this.shapeableDelegate.setForceCompatClippingEnabled(this, bool.booleanValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override // android.view.ViewGroup, android.view.View
|
||||
protected void onDetachedFromWindow() {
|
||||
this.savedForceCompatClippingEnabled = Boolean.valueOf(this.shapeableDelegate.isForceCompatClippingEnabled());
|
||||
this.shapeableDelegate.setForceCompatClippingEnabled(this, true);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.shape.Shapeable
|
||||
public void setShapeAppearanceModel(ShapeAppearanceModel shapeAppearanceModel) {
|
||||
ShapeAppearanceModel withTransformedCornerSizes = shapeAppearanceModel.withTransformedCornerSizes(new ShapeAppearanceModel.CornerSizeUnaryOperator() { // from class: com.google.android.material.carousel.MaskableFrameLayout$$ExternalSyntheticLambda1
|
||||
@Override // com.google.android.material.shape.ShapeAppearanceModel.CornerSizeUnaryOperator
|
||||
public final CornerSize apply(CornerSize cornerSize) {
|
||||
return MaskableFrameLayout.lambda$setShapeAppearanceModel$0(cornerSize);
|
||||
}
|
||||
});
|
||||
this.shapeAppearanceModel = withTransformedCornerSizes;
|
||||
this.shapeableDelegate.onShapeAppearanceChanged(this, withTransformedCornerSizes);
|
||||
}
|
||||
|
||||
static /* synthetic */ CornerSize lambda$setShapeAppearanceModel$0(CornerSize cornerSize) {
|
||||
return cornerSize instanceof AbsoluteCornerSize ? ClampedCornerSize.createFromCornerSize((AbsoluteCornerSize) cornerSize) : cornerSize;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Maskable
|
||||
@Deprecated
|
||||
public void setMaskXPercentage(float f) {
|
||||
float clamp = MathUtils.clamp(f, 0.0f, 1.0f);
|
||||
if (this.maskXPercentage != clamp) {
|
||||
this.maskXPercentage = clamp;
|
||||
updateMaskRectForMaskXPercentage();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMaskRectForMaskXPercentage() {
|
||||
if (this.maskXPercentage != -1.0f) {
|
||||
float lerp = AnimationUtils.lerp(0.0f, getWidth() / 2.0f, 0.0f, 1.0f, this.maskXPercentage);
|
||||
setMaskRectF(new RectF(lerp, 0.0f, getWidth() - lerp, getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.Maskable
|
||||
public void setMaskRectF(RectF rectF) {
|
||||
this.maskRect.set(rectF);
|
||||
onMaskChanged();
|
||||
}
|
||||
|
||||
private void onMaskChanged() {
|
||||
this.shapeableDelegate.onMaskChanged(this, this.maskRect);
|
||||
OnMaskChangedListener onMaskChangedListener = this.onMaskChangedListener;
|
||||
if (onMaskChangedListener != null) {
|
||||
onMaskChangedListener.onMaskChanged(this.maskRect);
|
||||
}
|
||||
}
|
||||
|
||||
public void setForceCompatClipping(boolean z) {
|
||||
this.shapeableDelegate.setForceCompatClippingEnabled(this, z);
|
||||
}
|
||||
|
||||
@Override // android.view.View
|
||||
public boolean onTouchEvent(MotionEvent motionEvent) {
|
||||
if (!this.maskRect.isEmpty() && motionEvent.getAction() == 0) {
|
||||
if (!this.maskRect.contains(motionEvent.getX(), motionEvent.getY())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(motionEvent);
|
||||
}
|
||||
|
||||
@Override // android.view.ViewGroup, android.view.View
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
this.shapeableDelegate.maybeClip(canvas, new CanvasCompat.CanvasOperation() { // from class: com.google.android.material.carousel.MaskableFrameLayout$$ExternalSyntheticLambda0
|
||||
@Override // com.google.android.material.canvas.CanvasCompat.CanvasOperation
|
||||
public final void run(Canvas canvas2) {
|
||||
MaskableFrameLayout.this.m196x418c47c0(canvas2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* renamed from: lambda$dispatchDraw$1$com-google-android-material-carousel-MaskableFrameLayout, reason: not valid java name */
|
||||
/* synthetic */ void m196x418c47c0(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.core.math.MathUtils;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public final class MultiBrowseCarouselStrategy extends CarouselStrategy {
|
||||
private int keylineCount = 0;
|
||||
private static final int[] SMALL_COUNTS = {1};
|
||||
private static final int[] MEDIUM_COUNTS = {1, 0};
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselStrategy
|
||||
KeylineState onFirstChildMeasuredWithMargins(Carousel carousel, View view) {
|
||||
float containerHeight = carousel.getContainerHeight();
|
||||
if (carousel.isHorizontal()) {
|
||||
containerHeight = carousel.getContainerWidth();
|
||||
}
|
||||
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
|
||||
float f = layoutParams.topMargin + layoutParams.bottomMargin;
|
||||
float measuredHeight = view.getMeasuredHeight();
|
||||
if (carousel.isHorizontal()) {
|
||||
f = layoutParams.leftMargin + layoutParams.rightMargin;
|
||||
measuredHeight = view.getMeasuredWidth();
|
||||
}
|
||||
float f2 = f;
|
||||
float smallSizeMin = CarouselStrategyHelper.getSmallSizeMin(view.getContext()) + f2;
|
||||
float smallSizeMax = CarouselStrategyHelper.getSmallSizeMax(view.getContext()) + f2;
|
||||
float min = Math.min(measuredHeight + f2, containerHeight);
|
||||
float clamp = MathUtils.clamp((measuredHeight / 3.0f) + f2, CarouselStrategyHelper.getSmallSizeMin(view.getContext()) + f2, CarouselStrategyHelper.getSmallSizeMax(view.getContext()) + f2);
|
||||
float f3 = (min + clamp) / 2.0f;
|
||||
int[] iArr = SMALL_COUNTS;
|
||||
if (containerHeight < 2.0f * smallSizeMin) {
|
||||
iArr = new int[]{0};
|
||||
}
|
||||
int[] iArr2 = MEDIUM_COUNTS;
|
||||
if (carousel.getCarouselAlignment() == 1) {
|
||||
iArr = doubleCounts(iArr);
|
||||
iArr2 = doubleCounts(iArr2);
|
||||
}
|
||||
int[] iArr3 = iArr;
|
||||
int[] iArr4 = iArr2;
|
||||
int max = (int) Math.max(1.0d, Math.floor(((containerHeight - (CarouselStrategyHelper.maxValue(iArr4) * f3)) - (CarouselStrategyHelper.maxValue(iArr3) * smallSizeMax)) / min));
|
||||
int ceil = (int) Math.ceil(containerHeight / min);
|
||||
int i = (ceil - max) + 1;
|
||||
int[] iArr5 = new int[i];
|
||||
for (int i2 = 0; i2 < i; i2++) {
|
||||
iArr5[i2] = ceil - i2;
|
||||
}
|
||||
Arrangement findLowestCostArrangement = Arrangement.findLowestCostArrangement(containerHeight, clamp, smallSizeMin, smallSizeMax, iArr3, f3, iArr4, min, iArr5);
|
||||
this.keylineCount = findLowestCostArrangement.getItemCount();
|
||||
if (ensureArrangementFitsItemCount(findLowestCostArrangement, carousel.getItemCount())) {
|
||||
findLowestCostArrangement = Arrangement.findLowestCostArrangement(containerHeight, clamp, smallSizeMin, smallSizeMax, new int[]{findLowestCostArrangement.smallCount}, f3, new int[]{findLowestCostArrangement.mediumCount}, min, new int[]{findLowestCostArrangement.largeCount});
|
||||
}
|
||||
return CarouselStrategyHelper.createKeylineState(view.getContext(), f2, containerHeight, findLowestCostArrangement, carousel.getCarouselAlignment());
|
||||
}
|
||||
|
||||
boolean ensureArrangementFitsItemCount(Arrangement arrangement, int i) {
|
||||
int itemCount = arrangement.getItemCount() - i;
|
||||
boolean z = itemCount > 0 && (arrangement.smallCount > 0 || arrangement.mediumCount > 1);
|
||||
while (itemCount > 0) {
|
||||
if (arrangement.smallCount > 0) {
|
||||
arrangement.smallCount--;
|
||||
} else if (arrangement.mediumCount > 1) {
|
||||
arrangement.mediumCount--;
|
||||
}
|
||||
itemCount--;
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselStrategy
|
||||
boolean shouldRefreshKeylineState(Carousel carousel, int i) {
|
||||
return (i < this.keylineCount && carousel.getItemCount() >= this.keylineCount) || (i >= this.keylineCount && carousel.getItemCount() < this.keylineCount);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public interface OnMaskChangedListener {
|
||||
void onMaskChanged(RectF rectF);
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package com.google.android.material.carousel;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.carousel.KeylineState;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public final class UncontainedCarouselStrategy extends CarouselStrategy {
|
||||
private static final float MEDIUM_LARGE_ITEM_PERCENTAGE_THRESHOLD = 0.85f;
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselStrategy
|
||||
boolean isContained() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // com.google.android.material.carousel.CarouselStrategy
|
||||
KeylineState onFirstChildMeasuredWithMargins(Carousel carousel, View view) {
|
||||
float f;
|
||||
float containerWidth = carousel.isHorizontal() ? carousel.getContainerWidth() : carousel.getContainerHeight();
|
||||
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
|
||||
float f2 = layoutParams.topMargin + layoutParams.bottomMargin;
|
||||
float measuredHeight = view.getMeasuredHeight();
|
||||
if (carousel.isHorizontal()) {
|
||||
float f3 = layoutParams.leftMargin + layoutParams.rightMargin;
|
||||
measuredHeight = view.getMeasuredWidth();
|
||||
f = f3;
|
||||
} else {
|
||||
f = f2;
|
||||
}
|
||||
float f4 = measuredHeight + f;
|
||||
float extraSmallSize = CarouselStrategyHelper.getExtraSmallSize(view.getContext()) + f;
|
||||
float extraSmallSize2 = CarouselStrategyHelper.getExtraSmallSize(view.getContext()) + f;
|
||||
int max = Math.max(1, (int) Math.floor(containerWidth / f4));
|
||||
float f5 = containerWidth - (max * f4);
|
||||
if (carousel.getCarouselAlignment() == 1) {
|
||||
float f6 = f5 / 2.0f;
|
||||
return createCenterAlignedKeylineState(containerWidth, f, f4, max, Math.max(Math.min(3.0f * f6, f4), CarouselStrategyHelper.getSmallSizeMin(view.getContext()) + f), extraSmallSize2, f6);
|
||||
}
|
||||
return createLeftAlignedKeylineState(view.getContext(), f, containerWidth, f4, max, calculateMediumChildSize(extraSmallSize, f4, f5), f5 > 0.0f ? 1 : 0, extraSmallSize2);
|
||||
}
|
||||
|
||||
private float calculateMediumChildSize(float f, float f2, float f3) {
|
||||
float max = Math.max(1.5f * f3, f);
|
||||
float f4 = MEDIUM_LARGE_ITEM_PERCENTAGE_THRESHOLD * f2;
|
||||
if (max > f4) {
|
||||
max = Math.max(f4, f3 * 1.2f);
|
||||
}
|
||||
return Math.min(f2, max);
|
||||
}
|
||||
|
||||
private KeylineState createCenterAlignedKeylineState(float f, float f2, float f3, int i, float f4, float f5, float f6) {
|
||||
float min = Math.min(f5, f3);
|
||||
float childMaskPercentage = getChildMaskPercentage(min, f3, f2);
|
||||
float childMaskPercentage2 = getChildMaskPercentage(f4, f3, f2);
|
||||
float f7 = f4 / 2.0f;
|
||||
float f8 = (f6 + 0.0f) - f7;
|
||||
float f9 = f8 + f7;
|
||||
float f10 = min / 2.0f;
|
||||
float f11 = (i * f3) + f9;
|
||||
KeylineState.Builder addKeylineRange = new KeylineState.Builder(f3, f).addAnchorKeyline((f8 - f7) - f10, childMaskPercentage, min).addKeyline(f8, childMaskPercentage2, f4, false).addKeylineRange((f3 / 2.0f) + f9, 0.0f, f3, i, true);
|
||||
addKeylineRange.addKeyline(f7 + f11, childMaskPercentage2, f4, false);
|
||||
addKeylineRange.addAnchorKeyline(f11 + f4 + f10, childMaskPercentage, min);
|
||||
return addKeylineRange.build();
|
||||
}
|
||||
|
||||
private KeylineState createLeftAlignedKeylineState(Context context, float f, float f2, float f3, int i, float f4, int i2, float f5) {
|
||||
float min = Math.min(f5, f3);
|
||||
float max = Math.max(min, 0.5f * f4);
|
||||
float childMaskPercentage = getChildMaskPercentage(max, f3, f);
|
||||
float childMaskPercentage2 = getChildMaskPercentage(min, f3, f);
|
||||
float childMaskPercentage3 = getChildMaskPercentage(f4, f3, f);
|
||||
float f6 = (i * f3) + 0.0f;
|
||||
KeylineState.Builder addKeylineRange = new KeylineState.Builder(f3, f2).addAnchorKeyline(0.0f - (max / 2.0f), childMaskPercentage, max).addKeylineRange(f3 / 2.0f, 0.0f, f3, i, true);
|
||||
if (i2 > 0) {
|
||||
float f7 = (f4 / 2.0f) + f6;
|
||||
f6 += f4;
|
||||
addKeylineRange.addKeyline(f7, childMaskPercentage3, f4, false);
|
||||
}
|
||||
addKeylineRange.addAnchorKeyline(f6 + (CarouselStrategyHelper.getExtraSmallSize(context) / 2.0f), childMaskPercentage2, min);
|
||||
return addKeylineRange.build();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user