Skip to content

Commit

Permalink
[Shape] Added Material endorsed shapes.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 663370897
  • Loading branch information
pekingme authored and imhappi committed Aug 16, 2024
1 parent f3aacd7 commit 21ba18a
Show file tree
Hide file tree
Showing 4 changed files with 974 additions and 0 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ ext {
vectorDrawable : '1.1.0',
viewpager2 : '1.0.0',
dynamicanimation : '1.0.0',
graphicsShapes : '1.0.0-rc01',
]

errorproneVersion = '2.15.0'
Expand Down Expand Up @@ -123,6 +124,8 @@ def compatibility(name) {
return "androidx.resourceinspection:resourceinspection-processor:${androidXVersions.resourceInspectionProcessor}"
case "viewpager2":
return "androidx.viewpager2:viewpager2:${androidXVersions.viewpager2}"
case "graphicsShapes":
return "androidx.graphics:graphics-shapes:${androidXVersions.graphicsShapes}"
case "experimental":
return "androidx.annotation:annotation-experimental:${androidXVersions.experimental}"
default:
Expand Down
2 changes: 2 additions & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dependencies {
api compatibility("transition")
api compatibility("vectordrawable")
api compatibility("viewpager2")
api compatibility("graphicsShapes")

annotationProcessor compatibility("resourceInspectionProcessor")

Expand Down Expand Up @@ -66,6 +67,7 @@ def srcDirs = [
'com/google/android/material/floatingactionbutton',
'com/google/android/material/imageview',
'com/google/android/material/internal',
'com/google/android/material/loadingindicator',
'com/google/android/material/materialswitch',
'com/google/android/material/math',
'com/google/android/material/menu',
Expand Down
133 changes: 133 additions & 0 deletions lib/java/com/google/android/material/shape/MaterialShapeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,19 @@

package com.google.android.material.shape;

import static java.lang.Math.min;

import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.PathShape;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.graphics.shapes.RoundedPolygon;
import androidx.graphics.shapes.Shapes_androidKt;
import com.google.android.material.internal.ViewUtils;

/** Utility methods for {@link MaterialShapeDrawable} and related classes. */
Expand Down Expand Up @@ -84,4 +94,127 @@ public static void setParentAbsoluteElevation(
materialShapeDrawable.setParentAbsoluteElevation(ViewUtils.getParentAbsoluteElevation(view));
}
}

/**
* Returns a {@link ShapeDrawable} with the shape's path.
*
* <p>The shape is always assumed to fit in (0, 0) to (1, 1) square.
*
* @param shape A {@link RoundedPolygon} object to be used in the drawable.
* @hide
*/
@NonNull
@RestrictTo(Scope.LIBRARY_GROUP)
public static ShapeDrawable createShapeDrawable(@NonNull RoundedPolygon shape) {
PathShape pathShape = new PathShape(Shapes_androidKt.toPath(shape), 1, 1);
return new ShapeDrawable(pathShape);
}

/**
* Creates a new {@link RoundedPolygon}, moving and resizing this one, so it's completely inside
* the destination bounds.
*
* <p>If {@code radial} is true, the shape will be scaled to fit in the biggest circle centered in
* the destination bounds. This is useful when the shape is animated to rotate around its center.
* Otherwise, the shape will be scaled to fit in the destination bounds. With either option, the
* shape's original center will be aligned with the destination bounds center.
*
* @param shape The original {@link RoundedPolygon}.
* @param radial Whether to transform the shape to fit in the biggest circle centered in the
* destination bounds.
* @param dstBounds The destination bounds to fit.
* @return A new {@link RoundedPolygon} that fits in the destination bounds.
* @hide
*/
@NonNull
@RestrictTo(Scope.LIBRARY_GROUP)
public static RoundedPolygon normalize(
@NonNull RoundedPolygon shape, boolean radial, @NonNull RectF dstBounds) {
float[] srcBoundsArray = new float[4];
if (radial) {
// This calculates the axis-aligned bounds of the shape and returns that rectangle. It
// determines the max dimension of the shape (by calculating the distance from its center to
// the start and midpoint of each curve) and returns a square which can be used to hold the
// object in any rotation.
shape.calculateMaxBounds(srcBoundsArray);
} else {
// This calculates the bounds of the shape without rotating the shape.
shape.calculateBounds(srcBoundsArray);
}
RectF srcBounds =
new RectF(srcBoundsArray[0], srcBoundsArray[1], srcBoundsArray[2], srcBoundsArray[3]);
float scale =
min(dstBounds.width() / srcBounds.width(), dstBounds.height() / srcBounds.height());
// Scales the shape with pivot point at its original center then moves it to align its original
// center with the destination bounds center.
Matrix transform = createScaleMatrix(scale, scale);
transform.preTranslate(-srcBounds.centerX(), -srcBounds.centerY());
transform.postTranslate(dstBounds.centerX(), dstBounds.centerY());
return Shapes_androidKt.transformed(shape, transform);
}

/**
* Creates a new {@link RoundedPolygon}, moving and resizing this one, so it's completely inside
* (0, 0) - (1, 1) square.
*
* <p>If {@code radial} is true, the shape will be scaled to fit in the circle centered at (0.5,
* 0.5) with a radius of 0.5. This is useful when the shape is animated to rotate around its
* center. Otherwise, the shape will be scaled to fit in the (0, 0) - (1, 1) square. With either
* option, the shape center will be (0.5, 0.5).
*
* @param shape The original {@link RoundedPolygon}.
* @param radial Whether to transform the shape to fit in the circle centered at (0.5, 0.5) with a
* radius of 0.5.
* @return A new {@link RoundedPolygon} that fits in (0, 0) - (1, 1) square.
* @hide
*/
@NonNull
@RestrictTo(Scope.LIBRARY_GROUP)
public static RoundedPolygon normalize(@NonNull RoundedPolygon shape, boolean radial) {
return normalize(shape, radial, new RectF(0, 0, 1, 1));
}

/**
* Returns a {@link Matrix} with the input scales.
*
* @param scaleX Scale in X axis.
* @param scaleY Scale in Y axis
* @hide
*/
@NonNull
@RestrictTo(Scope.LIBRARY_GROUP)
static Matrix createScaleMatrix(float scaleX, float scaleY) {
Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY);
return matrix;
}

/**
* Returns a {@link Matrix} with the input rotation in degrees.
*
* @param degrees The rotation in degrees.
* @hide
*/
@NonNull
@RestrictTo(Scope.LIBRARY_GROUP)
static Matrix createRotationMatrix(float degrees) {
Matrix matrix = new Matrix();
matrix.setRotate(degrees);
return matrix;
}

/**
* Returns a {@link Matrix} with the input skews.
*
* @param kx The skew in X axis.
* @param ky The skew in Y axis.
* @hide
*/
@NonNull
@RestrictTo(Scope.LIBRARY_GROUP)
static Matrix createSkewMatrix(float kx, float ky) {
Matrix matrix = new Matrix();
matrix.setSkew(kx, ky);
return matrix;
}
}
Loading

0 comments on commit 21ba18a

Please sign in to comment.