1 package com.android.customization.widget;
2 
3 import android.graphics.Canvas;
4 import android.graphics.ColorFilter;
5 import android.graphics.Matrix;
6 import android.graphics.Paint;
7 import android.graphics.Path;
8 import android.graphics.PixelFormat;
9 import android.graphics.Rect;
10 import android.graphics.drawable.Drawable;
11 
12 import androidx.core.graphics.PathParser;
13 
14 /**
15  * Drawable that draws a grid rows x cols of icon shapes adjusting their size to fit within its
16  * bounds.
17  */
18 public class GridTileDrawable extends Drawable {
19 
20     // Path is expected configuration in following dimension: [100 x 100]))
21     private static final float PATH_SIZE = 100f;
22     private static final float SPACE_BETWEEN_ICONS = 6f;
23     private final int mCols;
24     private final int mRows;
25     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
26     private final Path mShapePath;
27     private final Path mTransformedPath;
28     private final Matrix mScaleMatrix;
29     private float mCellSize = -1f;
30 
GridTileDrawable(int cols, int rows, String path)31     public GridTileDrawable(int cols, int rows, String path) {
32         mCols = cols;
33         mRows = rows;
34 
35         mShapePath = PathParser.createPathFromPathData(path);
36         mTransformedPath = new Path(mShapePath);
37         mScaleMatrix = new Matrix();
38     }
39 
40     @Override
onBoundsChange(Rect bounds)41     protected void onBoundsChange(Rect bounds) {
42         super.onBoundsChange(bounds);
43         int longestSide = Math.max(mRows, mCols);
44         mCellSize = (float) bounds.width() / longestSide;
45 
46         float scaleFactor = (mCellSize - 2 * SPACE_BETWEEN_ICONS) / PATH_SIZE;
47         mScaleMatrix.setScale(scaleFactor, scaleFactor);
48         mShapePath.transform(mScaleMatrix, mTransformedPath);
49     }
50 
51     @Override
draw(Canvas canvas)52     public void draw(Canvas canvas) {
53         double size = getBounds().width();
54 
55         for (int r = 0; r < mRows; r++) {
56             for (int c = 0; c < mCols; c++) {
57                 int saveCount = canvas.save();
58                 float x = (float) ((r * size / mRows) + SPACE_BETWEEN_ICONS);
59                 float y = (float) ((c * size / mCols) + SPACE_BETWEEN_ICONS);
60                 canvas.translate(x, y);
61                 canvas.drawPath(mTransformedPath, mPaint);
62                 canvas.restoreToCount(saveCount);
63             }
64         }
65     }
66 
67     @Override
setAlpha(int alpha)68     public void setAlpha(int alpha) {
69         mPaint.setAlpha(alpha);
70     }
71 
72     @Override
setColorFilter(ColorFilter colorFilter)73     public void setColorFilter(ColorFilter colorFilter) {
74         mPaint.setColorFilter(colorFilter);
75     }
76 
77     @Override
getOpacity()78     public int getOpacity() {
79         return PixelFormat.TRANSLUCENT;
80     }
81 }
82