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