cketcham 0547d2a06b Uncouple CornerSize from CornerTreatment
This allows for more easily updating the CornerSize independently from the CornerTreatment and makes it possible to create different types of CornerSizes such as percentage based corners. However, this means corner sizes can be different depending on the bounds of the shape, so the bounds need to be provided. MaterialShapeDrawable has bounds and the ShapeAppearanceModel, so there are new convenience methods there which return the current corner size for the current bounds of the drawable.

PiperOrigin-RevId: 272908508
2019-10-04 15:23:16 -04:00

813 lines
27 KiB
Java

/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.material.shape;
import com.google.android.material.R;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import androidx.annotation.AttrRes;
import androidx.annotation.Dimension;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.annotation.StyleRes;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
/**
* This class models the edges and corners of a shape, which are used by {@link
* MaterialShapeDrawable} to generate and render the shape for a view's background.
*/
public class ShapeAppearanceModel {
/** Builder to create instances of {@link ShapeAppearanceModel}s. */
public static final class Builder {
@NonNull
private CornerTreatment topLeftCorner = MaterialShapeUtils.createDefaultCornerTreatment();
@NonNull
private CornerTreatment topRightCorner = MaterialShapeUtils.createDefaultCornerTreatment();
@NonNull
private CornerTreatment bottomRightCorner = MaterialShapeUtils.createDefaultCornerTreatment();
@NonNull
private CornerTreatment bottomLeftCorner = MaterialShapeUtils.createDefaultCornerTreatment();
@NonNull private CornerSize topLeftCornerSize = new AbsoluteCornerSize(0);
@NonNull private CornerSize topRightCornerSize = new AbsoluteCornerSize(0);
@NonNull private CornerSize bottomRightCornerSize = new AbsoluteCornerSize(0);
@NonNull private CornerSize bottomLeftCornerSize = new AbsoluteCornerSize(0);
@NonNull private EdgeTreatment topEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
@NonNull private EdgeTreatment rightEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
@NonNull private EdgeTreatment bottomEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
@NonNull private EdgeTreatment leftEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
public Builder() {}
public Builder(@NonNull ShapeAppearanceModel other) {
topLeftCorner = other.topLeftCorner;
topRightCorner = other.topRightCorner;
bottomRightCorner = other.bottomRightCorner;
bottomLeftCorner = other.bottomLeftCorner;
topLeftCornerSize = other.topLeftCornerSize;
topRightCornerSize = other.topRightCornerSize;
bottomRightCornerSize = other.bottomRightCornerSize;
bottomLeftCornerSize = other.bottomLeftCornerSize;
topEdge = other.topEdge;
rightEdge = other.rightEdge;
bottomEdge = other.bottomEdge;
leftEdge = other.leftEdge;
}
/**
* Sets all corner treatments to {@link CornerTreatment}s generated from a {@code cornerFamily}
* and {@code cornerSize}.
*
* @param cornerFamily The family to be used to create the {@link CornerTreatment}s for all four
* corners. May be one of {@link CornerFamily#ROUNDED} or {@link CornerFamily#CUT}.
* @param cornerSize The size to be used to create the {@link CornerTreatment}s for all four
* corners.
*/
@NonNull
public Builder setAllCorners(@CornerFamily int cornerFamily, @Dimension float cornerSize) {
return setAllCorners(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setCornerRadius(cornerSize);
}
/**
* Sets all corner treatments.
*
* @param cornerTreatment the corner treatment to use for all four corners.
*/
@NonNull
public Builder setAllCorners(@NonNull CornerTreatment cornerTreatment) {
return setTopLeftCorner(cornerTreatment)
.setTopRightCorner(cornerTreatment)
.setBottomRightCorner(cornerTreatment)
.setBottomLeftCorner(cornerTreatment);
}
/**
* Sets all corner sizes.
*
* @param cornerSize the corner size to use for all four corners.
*/
@NonNull
public Builder setAllCornerSizes(@NonNull CornerSize cornerSize) {
return setTopLeftCornerSize(cornerSize)
.setTopRightCornerSize(cornerSize)
.setBottomRightCornerSize(cornerSize)
.setBottomLeftCornerSize(cornerSize);
}
/** Sets the corner size of all four corner treatments to {@code cornerRadius}. */
@NonNull
public Builder setCornerRadius(@Dimension float cornerRadius) {
return setTopLeftCornerSize(cornerRadius)
.setTopRightCornerSize(cornerRadius)
.setBottomRightCornerSize(cornerRadius)
.setBottomLeftCornerSize(cornerRadius);
}
/** Sets the top left corner size for the current corner. */
@NonNull
public Builder setTopLeftCornerSize(@Dimension float cornerSize) {
topLeftCornerSize = new AbsoluteCornerSize(cornerSize);
return this;
}
/** Sets the top left corner size for the current corner. */
@NonNull
public Builder setTopLeftCornerSize(@NonNull CornerSize cornerSize) {
topLeftCornerSize = cornerSize;
return this;
}
/** Sets the top right corner size for the current corner. */
@NonNull
public Builder setTopRightCornerSize(@Dimension float cornerSize) {
topRightCornerSize = new AbsoluteCornerSize(cornerSize);
return this;
}
/** Sets the top right corner size for the current corner. */
@NonNull
public Builder setTopRightCornerSize(@NonNull CornerSize cornerSize) {
topRightCornerSize = cornerSize;
return this;
}
/** Sets the bottom right corner size for the current corner. */
@NonNull
public Builder setBottomRightCornerSize(@Dimension float cornerSize) {
bottomRightCornerSize = new AbsoluteCornerSize(cornerSize);
return this;
}
/** Sets the bottom right corner size for the current corner. */
@NonNull
public Builder setBottomRightCornerSize(@NonNull CornerSize cornerSize) {
bottomRightCornerSize = cornerSize;
return this;
}
/** Sets the bottom left corner size for the current corner. */
@NonNull
public Builder setBottomLeftCornerSize(@Dimension float cornerSize) {
bottomLeftCornerSize = new AbsoluteCornerSize(cornerSize);
return this;
}
/** Sets the bottom left corner size for the current corner. */
@NonNull
public Builder setBottomLeftCornerSize(@NonNull CornerSize cornerSize) {
bottomLeftCornerSize = cornerSize;
return this;
}
/**
* Sets the corner treatment for the top left corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the size to use for the corner
*/
@NonNull
public Builder setTopLeftCorner(@CornerFamily int cornerFamily, @Dimension float cornerSize) {
return setTopLeftCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setTopLeftCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the top left corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the {@link CornerSize} to use for the corner
*/
@NonNull
public Builder setTopLeftCorner(
@CornerFamily int cornerFamily, @NonNull CornerSize cornerSize) {
return setTopLeftCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setTopLeftCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the top left corner.
*
* @param topLeftCorner the desired treatment.
*/
@NonNull
public Builder setTopLeftCorner(@NonNull CornerTreatment topLeftCorner) {
this.topLeftCorner = topLeftCorner;
// For backwards compatibility, set the size from the treatment if it exists
float size = compatCornerTreatmentSize(topLeftCorner);
if (size != -1) {
setTopLeftCornerSize(size);
}
return this;
}
/**
* Sets the corner treatment for the top right corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the size to use for the corner
*/
@NonNull
public Builder setTopRightCorner(@CornerFamily int cornerFamily, @Dimension float cornerSize) {
return setTopRightCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setTopRightCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the top right corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the {@link CornerSize} to use for the corner
*/
@NonNull
public Builder setTopRightCorner(
@CornerFamily int cornerFamily, @NonNull CornerSize cornerSize) {
return setTopRightCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setTopRightCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the top right corner.
*
* @param topRightCorner the desired treatment.
*/
@NonNull
public Builder setTopRightCorner(@NonNull CornerTreatment topRightCorner) {
this.topRightCorner = topRightCorner;
// For backwards compatibility, set the size from the treatment if it exists
float size = compatCornerTreatmentSize(topRightCorner);
if (size != -1) {
setTopRightCornerSize(size);
}
return this;
}
/**
* Sets the corner treatment for the bottom right corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the size to use for the corner
*/
@NonNull
public Builder setBottomRightCorner(
@CornerFamily int cornerFamily, @Dimension float cornerSize) {
return setBottomRightCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setBottomRightCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the bottom right corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the {@link CornerSize} to use for the corner
*/
@NonNull
public Builder setBottomRightCorner(
@CornerFamily int cornerFamily, @NonNull CornerSize cornerSize) {
return setBottomRightCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setBottomRightCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the bottom right corner.
*
* @param bottomRightCorner the desired treatment.
*/
@NonNull
public Builder setBottomRightCorner(@NonNull CornerTreatment bottomRightCorner) {
this.bottomRightCorner = bottomRightCorner;
// For backwards compatibility, set the size from the treatment if it exists
float size = compatCornerTreatmentSize(bottomRightCorner);
if (size != -1) {
setBottomRightCornerSize(size);
}
return this;
}
/**
* Sets the corner treatment for the bottom left corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the size to use for the corner
*/
@NonNull
public Builder setBottomLeftCorner(
@CornerFamily int cornerFamily, @Dimension float cornerSize) {
return setBottomLeftCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setBottomLeftCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the bottom left corner.
*
* @param cornerFamily the family to use to create the corner treatment
* @param cornerSize the {@link CornerSize} to use for the corner
*/
@NonNull
public Builder setBottomLeftCorner(
@CornerFamily int cornerFamily, @NonNull CornerSize cornerSize) {
return setBottomLeftCorner(MaterialShapeUtils.createCornerTreatment(cornerFamily))
.setBottomLeftCornerSize(cornerSize);
}
/**
* Sets the corner treatment for the bottom left corner.
*
* @param bottomLeftCorner the desired treatment.
*/
@NonNull
public Builder setBottomLeftCorner(@NonNull CornerTreatment bottomLeftCorner) {
this.bottomLeftCorner = bottomLeftCorner;
// For backwards compatibility, set the size from the treatment if it exists
float size = compatCornerTreatmentSize(bottomLeftCorner);
if (size != -1) {
setBottomLeftCornerSize(size);
}
return this;
}
/**
* Sets all edge treatments.
*
* @param edgeTreatment the edge treatment to use for all four edges.
*/
@NonNull
public Builder setAllEdges(@NonNull EdgeTreatment edgeTreatment) {
return setLeftEdge(edgeTreatment)
.setTopEdge(edgeTreatment)
.setRightEdge(edgeTreatment)
.setBottomEdge(edgeTreatment);
}
/**
* Sets the edge treatment for the left edge.
*
* @param leftEdge the desired treatment.
*/
@NonNull
public Builder setLeftEdge(@NonNull EdgeTreatment leftEdge) {
this.leftEdge = leftEdge;
return this;
}
/**
* Sets the edge treatment for the top edge.
*
* @param topEdge the desired treatment.
*/
@NonNull
public Builder setTopEdge(@NonNull EdgeTreatment topEdge) {
this.topEdge = topEdge;
return this;
}
/**
* Sets the edge treatment for the right edge.
*
* @param rightEdge the desired treatment.
*/
@NonNull
public Builder setRightEdge(@NonNull EdgeTreatment rightEdge) {
this.rightEdge = rightEdge;
return this;
}
/**
* Sets the edge treatment for the bottom edge.
*
* @param bottomEdge the desired treatment.
*/
@NonNull
public Builder setBottomEdge(@NonNull EdgeTreatment bottomEdge) {
this.bottomEdge = bottomEdge;
return this;
}
/** Adjusts all the corners by the offset. */
@NonNull
public Builder adjustCorners(@Dimension float offset) {
return setTopLeftCornerSize(new AdjustedCornerSize(offset, topLeftCornerSize))
.setTopRightCornerSize(new AdjustedCornerSize(offset, topRightCornerSize))
.setBottomRightCornerSize(new AdjustedCornerSize(offset, bottomRightCornerSize))
.setBottomLeftCornerSize(new AdjustedCornerSize(offset, bottomLeftCornerSize));
}
/** Pulls the corner size from specific CornerTreatments for backwards compatibility */
private static float compatCornerTreatmentSize(CornerTreatment treatment) {
if (treatment instanceof RoundedCornerTreatment) {
return ((RoundedCornerTreatment) treatment).radius;
} else if (treatment instanceof CutCornerTreatment) {
return ((CutCornerTreatment) treatment).size;
}
return -1;
}
/** Builds an instance of a {@link ShapeAppearanceModel} */
@NonNull
public ShapeAppearanceModel build() {
return new ShapeAppearanceModel(this);
}
}
@NonNull
public static Builder builder() {
return new ShapeAppearanceModel.Builder();
}
@NonNull
public static Builder builder(
@NonNull Context context,
AttributeSet attrs,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes) {
return builder(context, attrs, defStyleAttr, defStyleRes, 0);
}
@NonNull
public static Builder builder(
@NonNull Context context,
AttributeSet attrs,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes,
int defaultCornerSize) {
return builder(
context, attrs, defStyleAttr, defStyleRes, new AbsoluteCornerSize(defaultCornerSize));
}
@NonNull
public static Builder builder(
@NonNull Context context,
AttributeSet attrs,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes,
@NonNull CornerSize defaultCornerSize) {
TypedArray a =
context.obtainStyledAttributes(attrs, R.styleable.MaterialShape, defStyleAttr, defStyleRes);
int shapeAppearanceResId = a.getResourceId(R.styleable.MaterialShape_shapeAppearance, 0);
int shapeAppearanceOverlayResId =
a.getResourceId(R.styleable.MaterialShape_shapeAppearanceOverlay, 0);
a.recycle();
return builder(context, shapeAppearanceResId, shapeAppearanceOverlayResId, defaultCornerSize);
}
@NonNull
public static Builder builder(
Context context,
@StyleRes int shapeAppearanceResId,
@StyleRes int shapeAppearanceOverlayResId) {
return builder(context, shapeAppearanceResId, shapeAppearanceOverlayResId, 0);
}
@NonNull
private static Builder builder(
Context context,
@StyleRes int shapeAppearanceResId,
@StyleRes int shapeAppearanceOverlayResId,
int defaultCornerSize) {
return builder(
context,
shapeAppearanceResId,
shapeAppearanceOverlayResId,
new AbsoluteCornerSize(defaultCornerSize));
}
@NonNull
private static Builder builder(
Context context,
@StyleRes int shapeAppearanceResId,
@StyleRes int shapeAppearanceOverlayResId,
@NonNull CornerSize defaultCornerSize) {
// The attributes in shapeAppearanceOverlay should be applied on top of shapeAppearance.
if (shapeAppearanceOverlayResId != 0) {
context = new ContextThemeWrapper(context, shapeAppearanceResId);
shapeAppearanceResId = shapeAppearanceOverlayResId;
}
TypedArray a =
context.obtainStyledAttributes(shapeAppearanceResId, R.styleable.ShapeAppearance);
try {
int cornerFamily = a.getInt(R.styleable.ShapeAppearance_cornerFamily, CornerFamily.ROUNDED);
int cornerFamilyTopLeft =
a.getInt(R.styleable.ShapeAppearance_cornerFamilyTopLeft, cornerFamily);
int cornerFamilyTopRight =
a.getInt(R.styleable.ShapeAppearance_cornerFamilyTopRight, cornerFamily);
int cornerFamilyBottomRight =
a.getInt(R.styleable.ShapeAppearance_cornerFamilyBottomRight, cornerFamily);
int cornerFamilyBottomLeft =
a.getInt(R.styleable.ShapeAppearance_cornerFamilyBottomLeft, cornerFamily);
CornerSize cornerSize =
getCornerSize(a, R.styleable.ShapeAppearance_cornerSize, defaultCornerSize);
CornerSize cornerSizeTopLeft =
getCornerSize(a, R.styleable.ShapeAppearance_cornerSizeTopLeft, cornerSize);
CornerSize cornerSizeTopRight =
getCornerSize(a, R.styleable.ShapeAppearance_cornerSizeTopRight, cornerSize);
CornerSize cornerSizeBottomRight =
getCornerSize(a, R.styleable.ShapeAppearance_cornerSizeBottomRight, cornerSize);
CornerSize cornerSizeBottomLeft =
getCornerSize(a, R.styleable.ShapeAppearance_cornerSizeBottomLeft, cornerSize);
return new Builder()
.setTopLeftCorner(cornerFamilyTopLeft, cornerSizeTopLeft)
.setTopRightCorner(cornerFamilyTopRight, cornerSizeTopRight)
.setBottomRightCorner(cornerFamilyBottomRight, cornerSizeBottomRight)
.setBottomLeftCorner(cornerFamilyBottomLeft, cornerSizeBottomLeft);
} finally {
a.recycle();
}
}
@NonNull
private static CornerSize getCornerSize(
TypedArray a, int index, @NonNull CornerSize defaultValue) {
TypedValue value = a.peekValue(index);
if (value == null) {
return defaultValue;
}
if (value.type == TypedValue.TYPE_DIMENSION) {
// Eventually we might want to change this to call getDimension() since corner sizes support
// floats.
return new AbsoluteCornerSize(
TypedValue.complexToDimensionPixelSize(value.data, a.getResources().getDisplayMetrics()));
} else {
return defaultValue;
}
}
// Constant corner radius value to indicate that shape should use 50% height corner radii
public static final Integer PILL = -1;
CornerTreatment topLeftCorner;
CornerTreatment topRightCorner;
CornerTreatment bottomRightCorner;
CornerTreatment bottomLeftCorner;
CornerSize topLeftCornerSize;
CornerSize topRightCornerSize;
CornerSize bottomRightCornerSize;
CornerSize bottomLeftCornerSize;
EdgeTreatment topEdge;
EdgeTreatment rightEdge;
EdgeTreatment bottomEdge;
EdgeTreatment leftEdge;
private ShapeAppearanceModel(@NonNull ShapeAppearanceModel.Builder builder) {
topLeftCorner = builder.topLeftCorner;
topRightCorner = builder.topRightCorner;
bottomRightCorner = builder.bottomRightCorner;
bottomLeftCorner = builder.bottomLeftCorner;
topLeftCornerSize = builder.topLeftCornerSize;
topRightCornerSize = builder.topRightCornerSize;
bottomRightCornerSize = builder.bottomRightCornerSize;
bottomLeftCornerSize = builder.bottomLeftCornerSize;
topEdge = builder.topEdge;
rightEdge = builder.rightEdge;
bottomEdge = builder.bottomEdge;
leftEdge = builder.leftEdge;
}
/** Constructs a default path generator with default edge and corner treatments. */
public ShapeAppearanceModel() {
topLeftCorner = MaterialShapeUtils.createDefaultCornerTreatment();
topRightCorner = MaterialShapeUtils.createDefaultCornerTreatment();
bottomRightCorner = MaterialShapeUtils.createDefaultCornerTreatment();
bottomLeftCorner = MaterialShapeUtils.createDefaultCornerTreatment();
topLeftCornerSize = new AbsoluteCornerSize(0);
topRightCornerSize = new AbsoluteCornerSize(0);
bottomRightCornerSize = new AbsoluteCornerSize(0);
bottomLeftCornerSize = new AbsoluteCornerSize(0);
topEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
rightEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
bottomEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
leftEdge = MaterialShapeUtils.createDefaultEdgeTreatment();
}
/**
* Gets the corner treatment for the top left corner.
*
* @return the corner treatment for the top left corner.
*/
@NonNull
public CornerTreatment getTopLeftCorner() {
return topLeftCorner;
}
/**
* Gets the corner treatment for the top right corner.
*
* @return the corner treatment for the top right corner.
*/
@NonNull
public CornerTreatment getTopRightCorner() {
return topRightCorner;
}
/**
* Gets the corner treatment for the bottom right corner.
*
* @return the corner treatment for the bottom right corner.
*/
@NonNull
public CornerTreatment getBottomRightCorner() {
return bottomRightCorner;
}
/**
* Gets the corner treatment for the bottom left corner.
*
* @return the corner treatment for the bottom left corner.
*/
@NonNull
public CornerTreatment getBottomLeftCorner() {
return bottomLeftCorner;
}
/**
* Gets the corner size for the top left corner.
*
* @return the corner size for the top left corner.
*/
@NonNull
public CornerSize getTopLeftCornerSize() {
return topLeftCornerSize;
}
/**
* Gets the corner size for the top right corner.
*
* @return the corner size for the top right corner.
*/
@NonNull
public CornerSize getTopRightCornerSize() {
return topRightCornerSize;
}
/**
* Gets the corner size for the bottom right corner.
*
* @return the corner size for the bottom right corner.
*/
@NonNull
public CornerSize getBottomRightCornerSize() {
return bottomRightCornerSize;
}
/**
* Gets the corner size for the bottom left corner.
*
* @return the corner size for the bottom left corner.
*/
@NonNull
public CornerSize getBottomLeftCornerSize() {
return bottomLeftCornerSize;
}
/**
* Gets the edge treatment for the left edge.
*
* @return the edge treatment for the left edge.
*/
@NonNull
public EdgeTreatment getLeftEdge() {
return leftEdge;
}
/**
* Gets the edge treatment for the top edge.
*
* @return the edge treatment for the top edge.
*/
@NonNull
public EdgeTreatment getTopEdge() {
return topEdge;
}
/**
* Gets the edge treatment for the right edge.
*
* @return the edge treatment for the right edge.
*/
@NonNull
public EdgeTreatment getRightEdge() {
return rightEdge;
}
/**
* Gets the edge treatment for the bottom edge.
*
* @return the edge treatment for the bottom edge.
*/
@NonNull
public EdgeTreatment getBottomEdge() {
return bottomEdge;
}
/** Checks if all four corners of this ShapeAppearanceModel are of size {@link #PILL}. */
public boolean isUsingPillCorner() {
return isCornerPill(getTopRightCornerSize())
&& isCornerPill(getTopLeftCornerSize())
&& isCornerPill(getBottomLeftCornerSize())
&& isCornerPill(getBottomRightCornerSize());
}
private boolean isCornerPill(CornerSize cornerSize) {
return ((AbsoluteCornerSize) cornerSize).getCornerSize() == PILL;
}
/** Returns a builder with the edges and corners from this {@link ShapeAppearanceModel} */
@NonNull
public Builder toBuilder() {
return new Builder(this);
}
/**
* Returns a copy of this {@link ShapeAppearanceModel} with the same edges and corners, but with
* the corner radius for all corners updated.
*/
@NonNull
public ShapeAppearanceModel withCornerRadius(float cornerRadius) {
return toBuilder().setCornerRadius(cornerRadius).build();
}
@NonNull
public ShapeAppearanceModel withCornerSize(@NonNull CornerSize cornerSize) {
return toBuilder().setAllCornerSizes(cornerSize).build();
}
/**
* Returns a copy of this {@link ShapeAppearanceModel} with the same edges and corners, but with
* the corner radius for all corners offset by an adjustment.
*/
@NonNull
public ShapeAppearanceModel withAdjustedCorners(float offset) {
return toBuilder().adjustCorners(offset).build();
}
/**
* Checks Corner and Edge treatments to see if we can use {@link Canvas#drawRoundRect(RectF,float,
* float, Paint)} "} to draw this model.
*
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public boolean isRoundRect(@NonNull RectF bounds) {
boolean hasDefaultEdges =
leftEdge.getClass().equals(EdgeTreatment.class)
&& rightEdge.getClass().equals(EdgeTreatment.class)
&& topEdge.getClass().equals(EdgeTreatment.class)
&& bottomEdge.getClass().equals(EdgeTreatment.class);
float cornerSize = topLeftCornerSize.getCornerSize(bounds);
boolean cornersHaveSameSize =
topRightCornerSize.getCornerSize(bounds) == cornerSize
&& bottomLeftCornerSize.getCornerSize(bounds) == cornerSize
&& bottomRightCornerSize.getCornerSize(bounds) == cornerSize;
boolean hasRoundedCorners =
topRightCorner instanceof RoundedCornerTreatment
&& topLeftCorner instanceof RoundedCornerTreatment
&& bottomRightCorner instanceof RoundedCornerTreatment
&& bottomLeftCorner instanceof RoundedCornerTreatment;
return hasDefaultEdges && cornersHaveSameSize && hasRoundedCorners;
}
}