1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.wallpaper.picker.individual;
17 
18 import android.content.Context;
19 import android.graphics.Canvas;
20 import android.graphics.Matrix;
21 import android.graphics.Path;
22 import android.util.AttributeSet;
23 import android.widget.ImageView;
24 
25 import androidx.core.graphics.PathParser;
26 
27 import com.android.wallpaper.R;
28 
29 /**
30  * A view where the image can be optionally clipped to have a custom border, by default circular.
31  */
32 public class CustomShapeImageView extends ImageView {
33     private boolean mClipped;
34 
35     private boolean mPathSet;
36     private Path mPath;
37 
CustomShapeImageView(Context context)38     public CustomShapeImageView(Context context) {
39         super(context);
40     }
41 
CustomShapeImageView(Context context, AttributeSet attrs)42     public CustomShapeImageView(Context context, AttributeSet attrs) {
43         super(context, attrs);
44     }
45 
CustomShapeImageView(Context context, AttributeSet attrs, int defStyleAttr)46     public CustomShapeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
47         super(context, attrs, defStyleAttr);
48     }
49 
50     /**
51      * Returns whether the image is clipped with a circular border.
52      */
getClipped()53     public boolean getClipped() {
54         return mClipped;
55     }
56 
57     /**
58      * Modifies how the image is clipped. When called with true, the image
59      * is clipped with a circular border; with false, the default border.
60      *
61      * @param clippedValue Whether the image is clipped with a circular
62      *                     border.
63      */
setClipped(boolean clippedValue)64     public void setClipped(boolean clippedValue) {
65         mClipped = clippedValue;
66         invalidate();
67         requestLayout();
68     }
69 
70     /**
71      * Sets the border of the thumbnail.
72      *
73      * @param clippingPathResource The resource ID of the path string of the desired
74      *                             border.
75      */
setClippingPath(int clippingPathResource)76     public void setClippingPath(int clippingPathResource) {
77         String string = getResources().getString(clippingPathResource);
78         mPath = PathParser.createPathFromPathData(string);
79         mPathSet = true;
80     }
81 
82     @Override
onDraw(Canvas canvas)83     protected void onDraw(Canvas canvas) {
84         if (mClipped) {
85             if (!mPathSet) {
86                 setClippingPath(R.string.circular_border);
87             }
88             float scale = (float) (getHeight() / 100.0);
89             Matrix matrix = new Matrix();
90             matrix.postScale(scale, scale);
91             Path scaledPath = new Path(mPath);
92             scaledPath.transform(matrix);
93             canvas.clipPath(scaledPath);
94         }
95 
96         super.onDraw(canvas);
97     }
98 }
99 
100