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 17 package android.view; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.graphics.Point; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * Represents a rounded corner of the display. 32 * <p> 33 * <img src="{@docRoot}reference/android/images/rounded_corner/rounded-corner-info.png" height="120" 34 * alt="A figure to describe what the rounded corner radius and the center point are. "/> 35 * </p> 36 * 37 * <p>Note: The rounded corner formed by the radius and the center is an approximation.</p> 38 * 39 * <p>{@link RoundedCorner} is immutable.</p> 40 */ 41 public final class RoundedCorner implements Parcelable { 42 43 /** 44 * The rounded corner is at the top-left of the screen. 45 */ 46 public static final int POSITION_TOP_LEFT = 0; 47 /** 48 * The rounded corner is at the top-right of the screen. 49 */ 50 public static final int POSITION_TOP_RIGHT = 1; 51 /** 52 * The rounded corner is at the bottom-right of the screen. 53 */ 54 public static final int POSITION_BOTTOM_RIGHT = 2; 55 /** 56 * The rounded corner is at the bottom-left of the screen. 57 */ 58 public static final int POSITION_BOTTOM_LEFT = 3; 59 60 /** 61 * @hide 62 */ 63 @IntDef(prefix = { "POSITION_" }, value = { 64 POSITION_TOP_LEFT, 65 POSITION_TOP_RIGHT, 66 POSITION_BOTTOM_RIGHT, 67 POSITION_BOTTOM_LEFT 68 }) 69 @Retention(RetentionPolicy.SOURCE) 70 public @interface Position {} 71 72 private final @Position int mPosition; 73 private final int mRadius; 74 @NonNull 75 private final Point mCenter; 76 77 /** 78 * Creates an empty {@link RoundedCorner} on the given position. 79 * @hide 80 */ 81 @VisibleForTesting RoundedCorner(@osition int position)82 public RoundedCorner(@Position int position) { 83 mPosition = position; 84 mRadius = 0; 85 mCenter = new Point(0, 0); 86 } 87 88 /** 89 * Creates a {@link RoundedCorner}. 90 * 91 * <p>Note that this is only useful for tests. For production code, developers should always 92 * use a {@link RoundedCorner} obtained from the system via 93 * {@link WindowInsets#getRoundedCorner} or {@link Display#getRoundedCorner}.</p> 94 * 95 * @param position the position of the rounded corner. 96 * @param radius the radius of the rounded corner. 97 * @param centerX the x of center point of the rounded corner. 98 * @param centerY the y of center point of the rounded corner. 99 * 100 */ RoundedCorner(@osition int position, int radius, int centerX, int centerY)101 public RoundedCorner(@Position int position, int radius, int centerX, 102 int centerY) { 103 mPosition = position; 104 mRadius = radius; 105 mCenter = new Point(centerX, centerY); 106 } 107 108 /** 109 * Creates a {@link RoundedCorner} from a passed in {@link RoundedCorner}. 110 * 111 * @hide 112 */ RoundedCorner(RoundedCorner rc)113 RoundedCorner(RoundedCorner rc) { 114 mPosition = rc.getPosition(); 115 mRadius = rc.getRadius(); 116 mCenter = new Point(rc.getCenter()); 117 } 118 119 /** 120 * Get the position of this {@link RoundedCorner}. 121 * 122 * @see #POSITION_TOP_LEFT 123 * @see #POSITION_TOP_RIGHT 124 * @see #POSITION_BOTTOM_RIGHT 125 * @see #POSITION_BOTTOM_LEFT 126 */ getPosition()127 public @Position int getPosition() { 128 return mPosition; 129 } 130 131 /** 132 * Returns the radius of a quarter circle approximation of this {@link RoundedCorner}. 133 * 134 * @return the rounded corner radius of this {@link RoundedCorner}. Returns 0 if there is no 135 * rounded corner. 136 */ getRadius()137 public int getRadius() { 138 return mRadius; 139 } 140 141 /** 142 * Returns the circle center of a quarter circle approximation of this {@link RoundedCorner}. 143 * 144 * @return the center point of this {@link RoundedCorner} in the application's coordinate. 145 */ 146 @NonNull getCenter()147 public Point getCenter() { 148 return new Point(mCenter); 149 } 150 151 /** 152 * Checks whether this {@link RoundedCorner} exists and is inside the application's bounds. 153 * 154 * @return {@code false} if there is a rounded corner and is contained in the application's 155 * bounds. Otherwise return {@code true}. 156 * 157 * @hide 158 */ isEmpty()159 public boolean isEmpty() { 160 return mRadius == 0 || mCenter.x <= 0 || mCenter.y <= 0; 161 } 162 getPositionString(@osition int position)163 private String getPositionString(@Position int position) { 164 switch (position) { 165 case POSITION_TOP_LEFT: 166 return "TopLeft"; 167 case POSITION_TOP_RIGHT: 168 return "TopRight"; 169 case POSITION_BOTTOM_RIGHT: 170 return "BottomRight"; 171 case POSITION_BOTTOM_LEFT: 172 return "BottomLeft"; 173 default: 174 return "Invalid"; 175 } 176 } 177 178 @Override equals(Object o)179 public boolean equals(Object o) { 180 if (o == this) { 181 return true; 182 } 183 if (o instanceof RoundedCorner) { 184 RoundedCorner r = (RoundedCorner) o; 185 return mPosition == r.mPosition && mRadius == r.mRadius 186 && mCenter.equals(r.mCenter); 187 } 188 return false; 189 } 190 191 @Override hashCode()192 public int hashCode() { 193 int result = 0; 194 result = 31 * result + mPosition; 195 result = 31 * result + mRadius; 196 result = 31 * result + mCenter.hashCode(); 197 return result; 198 } 199 200 @Override toString()201 public String toString() { 202 return "RoundedCorner{" 203 + "position=" + getPositionString(mPosition) 204 + ", radius=" + mRadius 205 + ", center=" + mCenter 206 + '}'; 207 } 208 209 @Override describeContents()210 public int describeContents() { 211 return 0; 212 } 213 214 @Override writeToParcel(@onNull Parcel out, int flags)215 public void writeToParcel(@NonNull Parcel out, int flags) { 216 out.writeInt(mPosition); 217 out.writeInt(mRadius); 218 out.writeInt(mCenter.x); 219 out.writeInt(mCenter.y); 220 } 221 222 public static final @NonNull Creator<RoundedCorner> CREATOR = new Creator<RoundedCorner>() { 223 @Override 224 public RoundedCorner createFromParcel(Parcel in) { 225 return new RoundedCorner(in.readInt(), in.readInt(), in.readInt(), in.readInt()); 226 } 227 228 @Override 229 public RoundedCorner[] newArray(int size) { 230 return new RoundedCorner[size]; 231 } 232 }; 233 } 234